Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
mock_vulkan.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <cstdint>
8#include <cstring>
9#include <utility>
10#include <vector>
11
12#include "flutter/fml/logging.h"
14#include "impeller/renderer/backend/vulkan/vk.h" // IWYU pragma: keep.
15#include "third_party/swiftshader/include/vulkan/vulkan_core.h"
16#include "vulkan/vulkan.hpp"
17
18namespace impeller {
19namespace testing {
20
21namespace {
22
23class MockDevice;
24
25struct MockCommandBuffer {
26 explicit MockCommandBuffer(
27 std::shared_ptr<std::vector<std::string>> called_functions)
28 : called_functions_(std::move(called_functions)) {}
29 std::shared_ptr<std::vector<std::string>> called_functions_;
30 std::vector<VkImageMemoryBarrier> image_memory_barriers_;
31 std::vector<VkViewport> recorded_viewports_;
32};
33
34class MockQueue {
35 public:
36 explicit MockQueue(MockDevice& device) : device_(device) {}
37
38 MockDevice& device() const { return device_; }
39
40 private:
41 // The MockDevice owns the MockQueues, and each MockQueue holds a reference
42 // to its parent device.
43 MockDevice& device_;
44};
45
46struct MockQueryPool {};
47
48struct MockCommandPool {};
49
50struct MockDescriptorPool {};
51
52struct MockSurfaceKHR {};
53
54struct MockImage {};
55
56struct MockSwapchainKHR {
57 std::array<MockImage, 3> images;
58 size_t current_image = 0;
59};
60
61struct MockSemaphore {};
62
63struct MockFramebuffer {};
64
65static ISize currentImageSize = ISize{1, 1};
66
67class MockPhysicalDevice {
68 public:
69 std::weak_ptr<MockDevice>* CreateDevice();
70 void DestroyDevice(const std::weak_ptr<MockDevice>& device);
71
72 private:
73 std::vector<std::shared_ptr<MockDevice>> devices_;
74 std::vector<std::unique_ptr<std::weak_ptr<MockDevice>>> weak_devices_;
75};
76
77class MockInstance {
78 public:
79 MockPhysicalDevice& physical_device() { return physical_device_; }
80
81 private:
82 MockPhysicalDevice physical_device_;
83};
84
85class MockDevice final {
86 public:
87 explicit MockDevice(MockPhysicalDevice& physical_device)
88 : physical_device_(physical_device),
89 called_functions_(new std::vector<std::string>()),
90 queue_(*this) {}
91
92 MockPhysicalDevice& physical_device() { return physical_device_; }
93
94 // Get the MockDevice wrapped by a VkDevice handle and check that the
95 // VkDevice has not been destroyed.
96 static MockDevice* Unwrap(VkDevice vk_device) {
97 std::weak_ptr<MockDevice>* weak_device =
98 reinterpret_cast<std::weak_ptr<MockDevice>*>(vk_device);
99 std::shared_ptr strong_device = weak_device->lock();
100 FML_CHECK(strong_device);
101 return strong_device.get();
102 }
103
104 MockCommandBuffer* NewCommandBuffer() {
105 auto buffer = std::make_unique<MockCommandBuffer>(called_functions_);
106 MockCommandBuffer* result = buffer.get();
107 Lock lock(command_buffers_mutex_);
108 command_buffers_.emplace_back(std::move(buffer));
109 return result;
110 }
111
112 MockCommandPool* NewCommandPool() {
113 auto pool = std::make_unique<MockCommandPool>();
114 MockCommandPool* result = pool.get();
115 Lock lock(commmand_pools_mutex_);
116 command_pools_.emplace_back(std::move(pool));
117 return result;
118 }
119
120 void DeleteCommandPool(MockCommandPool* pool) {
121 Lock lock(commmand_pools_mutex_);
122 auto it = std::find_if(command_pools_.begin(), command_pools_.end(),
123 [pool](const std::unique_ptr<MockCommandPool>& p) {
124 return p.get() == pool;
125 });
126 if (it != command_pools_.end()) {
127 command_pools_.erase(it);
128 }
129 }
130
131 const std::shared_ptr<std::vector<std::string>>& GetCalledFunctions() {
132 return called_functions_;
133 }
134
135 void AddCalledFunction(const std::string& function) {
136 Lock lock(called_functions_mutex_);
137 called_functions_->push_back(function);
138 }
139
140 MockQueue& GetQueue() { return queue_; }
141
142 private:
143 MockDevice(const MockDevice&) = delete;
144
145 MockDevice& operator=(const MockDevice&) = delete;
146
147 MockPhysicalDevice& physical_device_;
148
149 Mutex called_functions_mutex_;
150 std::shared_ptr<std::vector<std::string>> called_functions_
151 IPLR_GUARDED_BY(called_functions_mutex_);
152
153 Mutex command_buffers_mutex_;
154 std::vector<std::unique_ptr<MockCommandBuffer>> command_buffers_
155 IPLR_GUARDED_BY(command_buffers_mutex_);
156
157 Mutex commmand_pools_mutex_;
158 std::vector<std::unique_ptr<MockCommandPool>> command_pools_
159 IPLR_GUARDED_BY(commmand_pools_mutex_);
160
161 MockQueue queue_;
162};
163
164std::weak_ptr<MockDevice>* MockPhysicalDevice::CreateDevice() {
165 auto strong_device = std::make_shared<MockDevice>(*this);
166 devices_.push_back(strong_device);
167 weak_devices_.push_back(
168 std::make_unique<std::weak_ptr<MockDevice>>(strong_device));
169 return weak_devices_.back().get();
170}
171
172void MockPhysicalDevice::DestroyDevice(
173 const std::weak_ptr<MockDevice>& device) {
174 std::shared_ptr<MockDevice> strong_device = device.lock();
175 FML_CHECK(strong_device);
176
177 // Remove the strong reference to the device from the devices_ list but keep
178 // the weak pointer in weak_devices_ that is wrapped by the VkDevice handle.
179 // This allows MockDevice::Unwrap to safely detect that the VkDevice
180 // references a device that has been destroyed.
181 std::erase(devices_, strong_device);
182}
183
184struct MockVulkanState {
185 std::vector<std::string> instance_extensions;
186 std::vector<std::string> instance_layers;
187 std::vector<std::string> device_extensions;
188 std::function<void(VkPhysicalDevice physicalDevice,
189 VkFormat format,
190 VkFormatProperties* pFormatProperties)>
192 std::function<void(VkPhysicalDevice physicalDevice,
193 VkPhysicalDeviceProperties* pProperties)>
195 std::function<std::remove_pointer_t<PFN_vkWaitForFences>>
197 std::function<std::remove_pointer_t<PFN_vkAcquireNextImageKHR>>
199 // When > 0, the next vkCreateImage for a fixed-rate-compressed image returns
200 // VK_ERROR_COMPRESSION_EXHAUSTED_EXT and decrements (models PowerVR).
202};
203
204class MockVulkanStatePtr {
205 public:
206 MockVulkanStatePtr() = default;
207
208 ~MockVulkanStatePtr() {
209 FML_CHECK(ptr_ == nullptr)
210 << "MockVulkanState was not null upon thread exit. Leak detected!";
211 }
212
213 void reset(MockVulkanState* ptr = nullptr) {
214 if (ptr_) {
215 delete ptr_;
216 }
217 ptr_ = ptr;
218 }
219
220 MockVulkanStatePtr(const MockVulkanStatePtr&) = delete;
221 MockVulkanStatePtr& operator=(const MockVulkanStatePtr&) = delete;
222 MockVulkanState* get() const { return ptr_; }
223 MockVulkanState& operator*() const { return *ptr_; }
224 MockVulkanState* operator->() const { return ptr_; }
225 explicit operator bool() const { return ptr_ != nullptr; }
226
227 private:
228 MockVulkanState* ptr_ = nullptr;
229};
230
231static thread_local MockVulkanStatePtr g_mock_vulkan_state;
232
233static MockVulkanState& GetMockVulkanState() {
234 FML_CHECK(g_mock_vulkan_state) << "MockVulkanState must be initialized.";
235 return *g_mock_vulkan_state;
236}
237
238void noop() {}
239
240VkResult vkEnumerateInstanceExtensionProperties(
241 const char* pLayerName,
242 uint32_t* pPropertyCount,
243 VkExtensionProperties* pProperties) {
244 if (!pProperties) {
245 *pPropertyCount = GetMockVulkanState().instance_extensions.size();
246 return VK_SUCCESS;
247 } else {
248 uint32_t count = 0;
249 VkResult result = VK_SUCCESS;
250 for (const std::string& ext : GetMockVulkanState().instance_extensions) {
251 if (count >= *pPropertyCount) {
252 result = VK_INCOMPLETE;
253 break;
254 }
255 snprintf(pProperties[count].extensionName,
256 sizeof(pProperties[count].extensionName), "%s", ext.c_str());
257 pProperties[count].specVersion = 0;
258 count++;
259 }
260 *pPropertyCount = count;
261 return result;
262 }
263}
264
265VkResult vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
266 VkLayerProperties* pProperties) {
267 if (!pProperties) {
268 *pPropertyCount = GetMockVulkanState().instance_layers.size();
269 return VK_SUCCESS;
270 } else {
271 uint32_t count = 0;
272 VkResult result = VK_SUCCESS;
273 for (const std::string& ext : GetMockVulkanState().instance_layers) {
274 if (count >= *pPropertyCount) {
275 result = VK_INCOMPLETE;
276 break;
277 }
278 snprintf(pProperties[count].layerName,
279 sizeof(pProperties[count].layerName), "%s", ext.c_str());
280 pProperties[count].specVersion = 0;
281 count++;
282 }
283 *pPropertyCount = count;
284 return result;
285 }
286}
287
288VkResult vkEnumeratePhysicalDevices(VkInstance instance,
289 uint32_t* pPhysicalDeviceCount,
290 VkPhysicalDevice* pPhysicalDevices) {
291 if (!pPhysicalDevices) {
292 *pPhysicalDeviceCount = 1;
293 } else {
294 MockInstance* mock_instance = reinterpret_cast<MockInstance*>(instance);
295 pPhysicalDevices[0] =
296 reinterpret_cast<VkPhysicalDevice>(&mock_instance->physical_device());
297 }
298 return VK_SUCCESS;
299}
300
301void vkGetPhysicalDeviceFormatProperties(
302 VkPhysicalDevice physicalDevice,
303 VkFormat format,
304 VkFormatProperties* pFormatProperties) {
305 if (GetMockVulkanState().format_properties_callback) {
306 GetMockVulkanState().format_properties_callback(physicalDevice, format,
307 pFormatProperties);
308 }
309}
310
311void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
312 VkPhysicalDeviceProperties* pProperties) {
313 pProperties->limits.framebufferColorSampleCounts =
314 static_cast<VkSampleCountFlags>(VK_SAMPLE_COUNT_1_BIT |
315 VK_SAMPLE_COUNT_4_BIT);
316 pProperties->limits.maxImageDimension2D = 4096;
317 pProperties->limits.timestampPeriod = 1;
318 if (GetMockVulkanState().physical_device_properties_callback) {
319 GetMockVulkanState().physical_device_properties_callback(physicalDevice,
320 pProperties);
321 }
322}
323
324void vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
325 VkPhysicalDeviceFeatures2* pFeatures) {
326 // Advertise the features the mock supports by walking the pNext chain.
327 auto* next = reinterpret_cast<VkBaseOutStructure*>(pFeatures->pNext);
328 while (next != nullptr) {
329 if (next->sType ==
330 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT) {
331 reinterpret_cast<VkPhysicalDeviceImageCompressionControlFeaturesEXT*>(
332 next)
333 ->imageCompressionControl = VK_TRUE;
334 }
335 next = next->pNext;
336 }
337}
338
339VkResult vkGetPhysicalDeviceImageFormatProperties2(
340 VkPhysicalDevice physicalDevice,
341 const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
342 VkImageFormatProperties2* pImageFormatProperties) {
343 // Report fixed-rate compression support when it is queried (i.e. the input
344 // carries a VkImageCompressionControlEXT and the output a
345 // VkImageCompressionPropertiesEXT).
346 bool compression_requested = false;
347 const auto* in =
348 reinterpret_cast<const VkBaseInStructure*>(pImageFormatInfo->pNext);
349 while (in != nullptr) {
350 if (in->sType == VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT) {
351 compression_requested = true;
352 }
353 in = in->pNext;
354 }
355 auto* out =
356 reinterpret_cast<VkBaseOutStructure*>(pImageFormatProperties->pNext);
357 while (compression_requested && out != nullptr) {
358 if (out->sType == VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT) {
359 auto* props = reinterpret_cast<VkImageCompressionPropertiesEXT*>(out);
360 props->imageCompressionFlags =
361 VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
362 props->imageCompressionFixedRateFlags =
363 VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT;
364 }
365 out = out->pNext;
366 }
367 return VK_SUCCESS;
368}
369
370void vkGetPhysicalDeviceQueueFamilyProperties(
371 VkPhysicalDevice physicalDevice,
372 uint32_t* pQueueFamilyPropertyCount,
373 VkQueueFamilyProperties* pQueueFamilyProperties) {
374 if (!pQueueFamilyProperties) {
375 *pQueueFamilyPropertyCount = 1;
376 } else {
377 pQueueFamilyProperties[0].queueCount = 3;
378 pQueueFamilyProperties[0].queueFlags = static_cast<VkQueueFlags>(
379 VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT);
380 }
381}
382
383VkResult vkEnumerateDeviceExtensionProperties(
384 VkPhysicalDevice physicalDevice,
385 const char* pLayerName,
386 uint32_t* pPropertyCount,
387 VkExtensionProperties* pProperties) {
388 if (!pProperties) {
389 *pPropertyCount = GetMockVulkanState().device_extensions.size();
390 return VK_SUCCESS;
391 } else {
392 uint32_t count = 0;
393 VkResult result = VK_SUCCESS;
394 for (const std::string& ext : GetMockVulkanState().device_extensions) {
395 if (count >= *pPropertyCount) {
396 result = VK_INCOMPLETE;
397 break;
398 }
399 snprintf(pProperties[count].extensionName,
400 sizeof(pProperties[count].extensionName), "%s", ext.c_str());
401 pProperties[count].specVersion = 0;
402 count++;
403 }
404 *pPropertyCount = count;
405 return result;
406 }
407}
408
409VkResult vkCreateDevice(VkPhysicalDevice physicalDevice,
410 const VkDeviceCreateInfo* pCreateInfo,
411 const VkAllocationCallbacks* pAllocator,
412 VkDevice* pDevice) {
413 MockPhysicalDevice* mock_physical_device =
414 reinterpret_cast<MockPhysicalDevice*>(physicalDevice);
415 *pDevice = reinterpret_cast<VkDevice>(mock_physical_device->CreateDevice());
416 return VK_SUCCESS;
417}
418
419VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
420 const VkAllocationCallbacks* pAllocator,
421 VkInstance* pInstance) {
422 *pInstance = reinterpret_cast<VkInstance>(new MockInstance());
423 return VK_SUCCESS;
424}
425
426void vkGetPhysicalDeviceMemoryProperties(
427 VkPhysicalDevice physicalDevice,
428 VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
429 pMemoryProperties->memoryTypeCount = 2;
430 pMemoryProperties->memoryHeapCount = 2;
431 pMemoryProperties->memoryTypes[0].heapIndex = 0;
432 pMemoryProperties->memoryTypes[0].propertyFlags =
433 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
434 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
435 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
436 pMemoryProperties->memoryTypes[1].heapIndex = 1;
437 pMemoryProperties->memoryTypes[1].propertyFlags =
438 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
439 pMemoryProperties->memoryHeaps[0].size = 1024 * 1024 * 1024;
440 pMemoryProperties->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
441 pMemoryProperties->memoryHeaps[1].size = 1024 * 1024 * 1024;
442 pMemoryProperties->memoryHeaps[1].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
443}
444
445VkResult vkCreatePipelineCache(VkDevice device,
446 const VkPipelineCacheCreateInfo* pCreateInfo,
447 const VkAllocationCallbacks* pAllocator,
448 VkPipelineCache* pPipelineCache) {
449 MockDevice* mock_device = MockDevice::Unwrap(device);
450 mock_device->AddCalledFunction("vkCreatePipelineCache");
451 *pPipelineCache = reinterpret_cast<VkPipelineCache>(0xb000dead);
452 return VK_SUCCESS;
453}
454
455VkResult vkCreateCommandPool(VkDevice device,
456 const VkCommandPoolCreateInfo* pCreateInfo,
457 const VkAllocationCallbacks* pAllocator,
458 VkCommandPool* pCommandPool) {
459 MockDevice* mock_device = MockDevice::Unwrap(device);
460 mock_device->AddCalledFunction("vkCreateCommandPool");
461 *pCommandPool =
462 reinterpret_cast<VkCommandPool>(mock_device->NewCommandPool());
463 return VK_SUCCESS;
464}
465
466VkResult vkResetCommandPool(VkDevice device,
467 VkCommandPool commandPool,
468 VkCommandPoolResetFlags flags) {
469 MockDevice* mock_device = MockDevice::Unwrap(device);
470 if (flags & VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT) {
471 mock_device->AddCalledFunction("vkResetCommandPoolReleaseResources");
472 } else {
473 mock_device->AddCalledFunction("vkResetCommandPool");
474 }
475 return VK_SUCCESS;
476}
477
478VkResult vkAllocateCommandBuffers(
479 VkDevice device,
480 const VkCommandBufferAllocateInfo* pAllocateInfo,
481 VkCommandBuffer* pCommandBuffers) {
482 MockDevice* mock_device = MockDevice::Unwrap(device);
483 mock_device->AddCalledFunction("vkAllocateCommandBuffers");
484 *pCommandBuffers =
485 reinterpret_cast<VkCommandBuffer>(mock_device->NewCommandBuffer());
486 return VK_SUCCESS;
487}
488
489VkResult vkBeginCommandBuffer(VkCommandBuffer commandBuffer,
490 const VkCommandBufferBeginInfo* pBeginInfo) {
491 return VK_SUCCESS;
492}
493
494VkResult vkCreateImage(VkDevice device,
495 const VkImageCreateInfo* pCreateInfo,
496 const VkAllocationCallbacks* pAllocator,
497 VkImage* pImage) {
498 MockDevice::Unwrap(device)->AddCalledFunction("vkCreateImage");
499 // Simulate VK_ERROR_COMPRESSION_EXHAUSTED_EXT for fixed-rate-compressed image
500 // creates (the spec only returns this error for compression requests).
501 if (g_mock_vulkan_state &&
502 g_mock_vulkan_state->compression_exhausted_create_image_failures > 0) {
503 const auto* next =
504 reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext);
505 while (next != nullptr) {
506 if (next->sType == VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT) {
507 g_mock_vulkan_state->compression_exhausted_create_image_failures--;
508 return VK_ERROR_COMPRESSION_EXHAUSTED_EXT;
509 }
510 next = next->pNext;
511 }
512 }
513 *pImage = reinterpret_cast<VkImage>(0xD0D0CACA);
514 return VK_SUCCESS;
515}
516
517void vkDestroyImage(VkDevice device,
518 VkImage image,
519 const VkAllocationCallbacks* pAllocator) {
520 MockDevice* mock_device = MockDevice::Unwrap(device);
521 mock_device->AddCalledFunction("vkDestroyImage");
522}
523
524void vkGetImageMemoryRequirements2KHR(
525 VkDevice device,
526 const VkImageMemoryRequirementsInfo2* pInfo,
527 VkMemoryRequirements2* pMemoryRequirements) {
528 pMemoryRequirements->memoryRequirements.size = 1024;
529 pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
530}
531
532VkResult vkAllocateMemory(VkDevice device,
533 const VkMemoryAllocateInfo* pAllocateInfo,
534 const VkAllocationCallbacks* pAllocator,
535 VkDeviceMemory* pMemory) {
536 *pMemory = reinterpret_cast<VkDeviceMemory>(0xCAFEB0BA);
537 return VK_SUCCESS;
538}
539
540VkResult vkBindImageMemory(VkDevice device,
541 VkImage image,
542 VkDeviceMemory memory,
543 VkDeviceSize memoryOffset) {
544 return VK_SUCCESS;
545}
546
547VkResult vkCreateImageView(VkDevice device,
548 const VkImageViewCreateInfo* pCreateInfo,
549 const VkAllocationCallbacks* pAllocator,
550 VkImageView* pView) {
551 *pView = reinterpret_cast<VkImageView>(0xFEE1DEAD);
552 return VK_SUCCESS;
553}
554
555void vkDestroyImageView(VkDevice device,
556 VkImageView imageView,
557 const VkAllocationCallbacks* pAllocator) {
558 MockDevice* mock_device = MockDevice::Unwrap(device);
559 mock_device->AddCalledFunction("vkDestroyImageView");
560}
561
562VkResult vkCreateBuffer(VkDevice device,
563 const VkBufferCreateInfo* pCreateInfo,
564 const VkAllocationCallbacks* pAllocator,
565 VkBuffer* pBuffer) {
566 *pBuffer = reinterpret_cast<VkBuffer>(0xDEADDEAD);
567 return VK_SUCCESS;
568}
569
570void vkGetBufferMemoryRequirements2KHR(
571 VkDevice device,
572 const VkBufferMemoryRequirementsInfo2* pInfo,
573 VkMemoryRequirements2* pMemoryRequirements) {
574 pMemoryRequirements->memoryRequirements.size = 1024;
575 pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
576}
577
578VkResult vkBindBufferMemory(VkDevice device,
579 VkBuffer buffer,
580 VkDeviceMemory memory,
581 VkDeviceSize memoryOffset) {
582 return VK_SUCCESS;
583}
584
585VkResult vkCreateRenderPass(VkDevice device,
586 const VkRenderPassCreateInfo* pCreateInfo,
587 const VkAllocationCallbacks* pAllocator,
588 VkRenderPass* pRenderPass) {
589 *pRenderPass = reinterpret_cast<VkRenderPass>(0x12341234);
590 MockDevice* mock_device = MockDevice::Unwrap(device);
591 mock_device->AddCalledFunction("vkCreateRenderPass");
592 return VK_SUCCESS;
593}
594
595VkResult vkCreateDescriptorSetLayout(
596 VkDevice device,
597 const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
598 const VkAllocationCallbacks* pAllocator,
599 VkDescriptorSetLayout* pSetLayout) {
600 *pSetLayout = reinterpret_cast<VkDescriptorSetLayout>(0x77777777);
601 return VK_SUCCESS;
602}
603
604VkResult vkCreatePipelineLayout(VkDevice device,
605 const VkPipelineLayoutCreateInfo* pCreateInfo,
606 const VkAllocationCallbacks* pAllocator,
607 VkPipelineLayout* pPipelineLayout) {
608 *pPipelineLayout = reinterpret_cast<VkPipelineLayout>(0x88888888);
609 return VK_SUCCESS;
610}
611
612VkResult vkCreateGraphicsPipelines(
613 VkDevice device,
614 VkPipelineCache pipelineCache,
615 uint32_t createInfoCount,
616 const VkGraphicsPipelineCreateInfo* pCreateInfos,
617 const VkAllocationCallbacks* pAllocator,
618 VkPipeline* pPipelines) {
619 MockDevice* mock_device = MockDevice::Unwrap(device);
620 mock_device->AddCalledFunction("vkCreateGraphicsPipelines");
621 *pPipelines = reinterpret_cast<VkPipeline>(0x99999999);
622 return VK_SUCCESS;
623}
624
625VkResult vkDeviceWaitIdle(VkDevice device) {
626 MockDevice* mock_device = MockDevice::Unwrap(device);
627 mock_device->AddCalledFunction("vkDeviceWaitIdle");
628 return VK_SUCCESS;
629}
630
631void vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
632 std::weak_ptr<MockDevice>* weak_device =
633 reinterpret_cast<std::weak_ptr<MockDevice>*>(device);
634
635 {
636 MockDevice* mock_device = MockDevice::Unwrap(device);
637 mock_device->AddCalledFunction("vkDestroyDevice");
638
639 // mock_device is no longer usable after calling DestroyDevice
640 mock_device->physical_device().DestroyDevice(*weak_device);
641 }
642}
643
644void vkDestroyInstance(VkInstance instance,
645 const VkAllocationCallbacks* pAllocator) {
646 if (g_mock_vulkan_state) {
647 g_mock_vulkan_state.reset();
648 }
649 MockInstance* mock_instance = reinterpret_cast<MockInstance*>(instance);
650 delete mock_instance;
651}
652
653void vkDestroyPipeline(VkDevice device,
654 VkPipeline pipeline,
655 const VkAllocationCallbacks* pAllocator) {
656 MockDevice* mock_device = MockDevice::Unwrap(device);
657 mock_device->AddCalledFunction("vkDestroyPipeline");
658}
659
660VkResult vkCreateShaderModule(VkDevice device,
661 const VkShaderModuleCreateInfo* pCreateInfo,
662 const VkAllocationCallbacks* pAllocator,
663 VkShaderModule* pShaderModule) {
664 MockDevice* mock_device = MockDevice::Unwrap(device);
665 mock_device->AddCalledFunction("vkCreateShaderModule");
666 *pShaderModule = reinterpret_cast<VkShaderModule>(0x11111111);
667 return VK_SUCCESS;
668}
669
670void vkDestroyShaderModule(VkDevice device,
671 VkShaderModule shaderModule,
672 const VkAllocationCallbacks* pAllocator) {
673 MockDevice* mock_device = MockDevice::Unwrap(device);
674 mock_device->AddCalledFunction("vkDestroyShaderModule");
675}
676
677void vkDestroyPipelineCache(VkDevice device,
678 VkPipelineCache pipelineCache,
679 const VkAllocationCallbacks* pAllocator) {
680 MockDevice* mock_device = MockDevice::Unwrap(device);
681 mock_device->AddCalledFunction("vkDestroyPipelineCache");
682}
683
684void vkDestroySurfaceKHR(VkInstance instance,
685 VkSurfaceKHR surface,
686 const VkAllocationCallbacks* pAllocator) {
687 return;
688}
689
690void vkCmdBindPipeline(VkCommandBuffer commandBuffer,
691 VkPipelineBindPoint pipelineBindPoint,
692 VkPipeline pipeline) {
693 MockCommandBuffer* mock_command_buffer =
694 reinterpret_cast<MockCommandBuffer*>(commandBuffer);
695 mock_command_buffer->called_functions_->push_back("vkCmdBindPipeline");
696}
697
698void vkCmdPipelineBarrier(VkCommandBuffer commandBuffer,
699 VkPipelineStageFlags srcStageMask,
700 VkPipelineStageFlags dstStageMask,
701 VkDependencyFlags dependencyFlags,
702 uint32_t memoryBarrierCount,
703 const VkMemoryBarrier* pMemoryBarriers,
704 uint32_t bufferMemoryBarrierCount,
705 const VkBufferMemoryBarrier* pBufferMemoryBarriers,
706 uint32_t imageMemoryBarrierCount,
707 const VkImageMemoryBarrier* pImageMemoryBarriers) {
708 MockCommandBuffer* mock_command_buffer =
709 reinterpret_cast<MockCommandBuffer*>(commandBuffer);
710 mock_command_buffer->called_functions_->push_back("vkCmdPipelineBarrier");
711 if (pImageMemoryBarriers) {
712 for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) {
713 mock_command_buffer->image_memory_barriers_.push_back(
714 pImageMemoryBarriers[i]);
715 }
716 }
717}
718
719void vkCmdSetStencilReference(VkCommandBuffer commandBuffer,
720 VkStencilFaceFlags faceMask,
721 uint32_t reference) {
722 MockCommandBuffer* mock_command_buffer =
723 reinterpret_cast<MockCommandBuffer*>(commandBuffer);
724 mock_command_buffer->called_functions_->push_back("vkCmdSetStencilReference");
725}
726
727void vkCmdSetScissor(VkCommandBuffer commandBuffer,
728 uint32_t firstScissor,
729 uint32_t scissorCount,
730 const VkRect2D* pScissors) {
731 MockCommandBuffer* mock_command_buffer =
732 reinterpret_cast<MockCommandBuffer*>(commandBuffer);
733 mock_command_buffer->called_functions_->push_back("vkCmdSetScissor");
734}
735
736void vkCmdSetViewport(VkCommandBuffer commandBuffer,
737 uint32_t firstViewport,
738 uint32_t viewportCount,
739 const VkViewport* pViewports) {
740 MockCommandBuffer* mock_command_buffer =
741 reinterpret_cast<MockCommandBuffer*>(commandBuffer);
742 mock_command_buffer->called_functions_->push_back("vkCmdSetViewport");
743 for (uint32_t i = 0; i < viewportCount; ++i) {
744 mock_command_buffer->recorded_viewports_.push_back(pViewports[i]);
745 }
746}
747
748void vkFreeCommandBuffers(VkDevice device,
749 VkCommandPool commandPool,
750 uint32_t commandBufferCount,
751 const VkCommandBuffer* pCommandBuffers) {
752 MockDevice* mock_device = MockDevice::Unwrap(device);
753 mock_device->AddCalledFunction("vkFreeCommandBuffers");
754}
755
756void vkDestroyCommandPool(VkDevice device,
757 VkCommandPool commandPool,
758 const VkAllocationCallbacks* pAllocator) {
759 MockDevice* mock_device = MockDevice::Unwrap(device);
760 mock_device->DeleteCommandPool(
761 reinterpret_cast<MockCommandPool*>(commandPool));
762 mock_device->AddCalledFunction("vkDestroyCommandPool");
763}
764
765VkResult vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
766 return VK_SUCCESS;
767}
768
769VkResult vkCreateFence(VkDevice device,
770 const VkFenceCreateInfo* pCreateInfo,
771 const VkAllocationCallbacks* pAllocator,
772 VkFence* pFence) {
773 MockDevice* mock_device = MockDevice::Unwrap(device);
774 mock_device->AddCalledFunction("vkCreateFence");
775 *pFence = reinterpret_cast<VkFence>(new MockFence());
776 return VK_SUCCESS;
777}
778
779VkResult vkDestroyFence(VkDevice device,
780 VkFence fence,
781 const VkAllocationCallbacks* pAllocator) {
782 delete reinterpret_cast<MockFence*>(fence);
783 return VK_SUCCESS;
784}
785
786void vkGetDeviceQueue(VkDevice device,
787 uint32_t queueFamilyIndex,
788 uint32_t queueIndex,
789 VkQueue* pQueue) {
790 MockDevice* mock_device = MockDevice::Unwrap(device);
791 *pQueue = reinterpret_cast<VkQueue>(&mock_device->GetQueue());
792}
793
794VkResult vkQueueSubmit(VkQueue queue,
795 uint32_t submitCount,
796 const VkSubmitInfo* pSubmits,
797 VkFence fence) {
798 const MockQueue* mock_queue = reinterpret_cast<const MockQueue*>(queue);
799 mock_queue->device().AddCalledFunction("vkQueueSubmit");
800 return VK_SUCCESS;
801}
802
803VkResult vkWaitForFences(VkDevice device,
804 uint32_t fenceCount,
805 const VkFence* pFences,
806 VkBool32 waitAll,
807 uint64_t timeout) {
808 if (g_mock_vulkan_state && GetMockVulkanState().wait_for_fences_callback) {
809 return GetMockVulkanState().wait_for_fences_callback(
810 device, fenceCount, pFences, waitAll, timeout);
811 }
812 return VK_SUCCESS;
813}
814
815VkResult vkGetFenceStatus(VkDevice device, VkFence fence) {
816 MockFence* mock_fence = reinterpret_cast<MockFence*>(fence);
817 return mock_fence->GetStatus();
818}
819
820VkResult vkResetFences(VkDevice device,
821 uint32_t fenceCount,
822 const VkFence* fences) {
823 return VK_SUCCESS;
824}
825
826VkResult vkCreateDebugUtilsMessengerEXT(
827 VkInstance instance,
828 const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
829 const VkAllocationCallbacks* pAllocator,
830 VkDebugUtilsMessengerEXT* pMessenger) {
831 return VK_SUCCESS;
832}
833
834VkResult vkSetDebugUtilsObjectNameEXT(
835 VkDevice device,
836 const VkDebugUtilsObjectNameInfoEXT* pNameInfo) {
837 return VK_SUCCESS;
838}
839
840VkResult vkCreateQueryPool(VkDevice device,
841 const VkQueryPoolCreateInfo* pCreateInfo,
842 const VkAllocationCallbacks* pAllocator,
843 VkQueryPool* pQueryPool) {
844 *pQueryPool = reinterpret_cast<VkQueryPool>(new MockQueryPool());
845 MockDevice* mock_device = MockDevice::Unwrap(device);
846 mock_device->AddCalledFunction("vkCreateQueryPool");
847 return VK_SUCCESS;
848}
849
850void vkDestroyQueryPool(VkDevice device,
851 VkQueryPool queryPool,
852 const VkAllocationCallbacks* pAllocator) {
853 MockDevice* mock_device = MockDevice::Unwrap(device);
854 mock_device->AddCalledFunction("vkDestroyQueryPool");
855 delete reinterpret_cast<MockQueryPool*>(queryPool);
856}
857
858VkResult vkGetQueryPoolResults(VkDevice device,
859 VkQueryPool queryPool,
860 uint32_t firstQuery,
861 uint32_t queryCount,
862 size_t dataSize,
863 void* pData,
864 VkDeviceSize stride,
865 VkQueryResultFlags flags) {
866 MockDevice* mock_device = MockDevice::Unwrap(device);
867 if (dataSize == sizeof(uint32_t)) {
868 uint32_t* data = static_cast<uint32_t*>(pData);
869 for (auto i = firstQuery; i < queryCount; i++) {
870 data[0] = i;
871 }
872 } else if (dataSize == sizeof(int64_t)) {
873 uint64_t* data = static_cast<uint64_t*>(pData);
874 for (auto i = firstQuery; i < queryCount; i++) {
875 data[0] = i;
876 }
877 }
878 mock_device->AddCalledFunction("vkGetQueryPoolResults");
879 return VK_SUCCESS;
880}
881
882VkResult vkCreateDescriptorPool(VkDevice device,
883 const VkDescriptorPoolCreateInfo* pCreateInfo,
884 const VkAllocationCallbacks* pAllocator,
885 VkDescriptorPool* pDescriptorPool) {
886 MockDevice* mock_device = MockDevice::Unwrap(device);
887 *pDescriptorPool =
888 reinterpret_cast<VkDescriptorPool>(new MockDescriptorPool());
889 mock_device->AddCalledFunction("vkCreateDescriptorPool");
890 return VK_SUCCESS;
891}
892
893void vkDestroyDescriptorPool(VkDevice device,
894 VkDescriptorPool descriptorPool,
895 const VkAllocationCallbacks* pAllocator) {
896 MockDevice* mock_device = MockDevice::Unwrap(device);
897 mock_device->AddCalledFunction("vkDestroyDescriptorPool");
898 delete reinterpret_cast<MockDescriptorPool*>(descriptorPool);
899}
900
901VkResult vkResetDescriptorPool(VkDevice device,
902 VkDescriptorPool descriptorPool,
903 VkDescriptorPoolResetFlags flags) {
904 MockDevice* mock_device = MockDevice::Unwrap(device);
905 mock_device->AddCalledFunction("vkResetDescriptorPool");
906 return VK_SUCCESS;
907}
908
909VkResult vkAllocateDescriptorSets(
910 VkDevice device,
911 const VkDescriptorSetAllocateInfo* pAllocateInfo,
912 VkDescriptorSet* pDescriptorSets) {
913 MockDevice* mock_device = MockDevice::Unwrap(device);
914 mock_device->AddCalledFunction("vkAllocateDescriptorSets");
915 return VK_SUCCESS;
916}
917
918VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(
919 VkPhysicalDevice physicalDevice,
920 VkSurfaceKHR surface,
921 uint32_t* pSurfaceFormatCount,
922 VkSurfaceFormatKHR* pSurfaceFormats) {
923 *pSurfaceFormatCount = 1u;
924 if (pSurfaceFormats != nullptr) {
925 pSurfaceFormats[0] =
926 VkSurfaceFormatKHR{.format = VK_FORMAT_R8G8B8A8_UNORM,
927 .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
928 }
929 return VK_SUCCESS;
930}
931
932VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
933 VkPhysicalDevice physicalDevice,
934 VkSurfaceKHR surface,
935 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
936 *pSurfaceCapabilities = VkSurfaceCapabilitiesKHR{
937 .minImageCount = 3,
938 .maxImageCount = 6,
939 .currentExtent =
940 VkExtent2D{
941 .width = static_cast<uint32_t>(currentImageSize.width),
942 .height = static_cast<uint32_t>(currentImageSize.height),
943 },
944 .minImageExtent =
945 VkExtent2D{
946 .width = 0,
947 .height = 0,
948 },
949 .maxImageExtent =
950 VkExtent2D{
951 .width = static_cast<uint32_t>(currentImageSize.width),
952 .height = static_cast<uint32_t>(currentImageSize.height),
953 },
954 .maxImageArrayLayers = 1,
955 .supportedTransforms =
956 VkSurfaceTransformFlagBitsKHR::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
957 .currentTransform =
958 VkSurfaceTransformFlagBitsKHR::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
959 .supportedCompositeAlpha = VkCompositeAlphaFlagBitsKHR::
960 VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
961 .supportedUsageFlags =
962 VkImageUsageFlagBits::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT};
963 return VK_SUCCESS;
964}
965
966VkResult vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
967 uint32_t queueFamilyIndex,
968 VkSurfaceKHR surface,
969 VkBool32* pSupported) {
970 *pSupported = VK_TRUE;
971 return VK_SUCCESS;
972}
973
974VkResult vkCreateSwapchainKHR(VkDevice device,
975 const VkSwapchainCreateInfoKHR* pCreateInfo,
976 const VkAllocationCallbacks* pAllocator,
977 VkSwapchainKHR* pSwapchain) {
978 *pSwapchain = reinterpret_cast<VkSwapchainKHR>(new MockSwapchainKHR());
979 return VK_SUCCESS;
980}
981
982void vkDestroySwapchainKHR(VkDevice device,
983 VkSwapchainKHR swapchain,
984 const VkAllocationCallbacks* pAllocator) {
985 delete reinterpret_cast<MockSwapchainKHR*>(swapchain);
986}
987
988VkResult vkGetSwapchainImagesKHR(VkDevice device,
989 VkSwapchainKHR swapchain,
990 uint32_t* pSwapchainImageCount,
991 VkImage* pSwapchainImages) {
992 MockSwapchainKHR* mock_swapchain =
993 reinterpret_cast<MockSwapchainKHR*>(swapchain);
994 auto& images = mock_swapchain->images;
995 *pSwapchainImageCount = images.size();
996 if (pSwapchainImages != nullptr) {
997 for (size_t i = 0; i < images.size(); i++) {
998 pSwapchainImages[i] = reinterpret_cast<VkImage>(&images[i]);
999 }
1000 }
1001 return VK_SUCCESS;
1002}
1003
1004VkResult vkCreateSemaphore(VkDevice device,
1005 const VkSemaphoreCreateInfo* pCreateInfo,
1006 const VkAllocationCallbacks* pAllocator,
1007 VkSemaphore* pSemaphore) {
1008 *pSemaphore = reinterpret_cast<VkSemaphore>(new MockSemaphore());
1009 return VK_SUCCESS;
1010}
1011
1012void vkDestroySemaphore(VkDevice device,
1013 VkSemaphore semaphore,
1014 const VkAllocationCallbacks* pAllocator) {
1015 delete reinterpret_cast<MockSemaphore*>(semaphore);
1016}
1017
1018VkResult vkAcquireNextImageKHR(VkDevice device,
1019 VkSwapchainKHR swapchain,
1020 uint64_t timeout,
1021 VkSemaphore semaphore,
1022 VkFence fence,
1023 uint32_t* pImageIndex) {
1024 if (g_mock_vulkan_state && GetMockVulkanState().acquire_next_image_callback) {
1025 return GetMockVulkanState().acquire_next_image_callback(
1026 device, swapchain, timeout, semaphore, fence, pImageIndex);
1027 }
1028 auto current_index =
1029 reinterpret_cast<MockSwapchainKHR*>(swapchain)->current_image++;
1030 *pImageIndex = (current_index + 1) % 3u;
1031 return VK_SUCCESS;
1032}
1033
1034VkResult vkCreateFramebuffer(VkDevice device,
1035 const VkFramebufferCreateInfo* pCreateInfo,
1036 const VkAllocationCallbacks* pAllocator,
1037 VkFramebuffer* pFramebuffer) {
1038 *pFramebuffer = reinterpret_cast<VkFramebuffer>(new MockFramebuffer());
1039 return VK_SUCCESS;
1040}
1041
1042void vkDestroyFramebuffer(VkDevice device,
1043 VkFramebuffer framebuffer,
1044 const VkAllocationCallbacks* pAllocator) {
1045 delete reinterpret_cast<MockFramebuffer*>(framebuffer);
1046}
1047
1048void vkTrimCommandPool(VkDevice device,
1049 VkCommandPool commandPool,
1050 VkCommandPoolTrimFlags flags) {
1051 MockDevice* mock_device = MockDevice::Unwrap(device);
1052 mock_device->AddCalledFunction("vkTrimCommandPool");
1053}
1054
1055VkResult vkGetPipelineCacheData(VkDevice device,
1056 VkPipelineCache pipelineCache,
1057 size_t* pDataSize,
1058 void* pData) {
1059 if (pData) {
1060 const std::array<uint8_t, 5> cache_data{1, 2, 3, 4, 5};
1061 size_t dst_buffer_size = *pDataSize;
1062 size_t length = std::min(dst_buffer_size, cache_data.size());
1063 std::memcpy(pData, cache_data.data(), length);
1064 *pDataSize = length;
1065 return (dst_buffer_size >= length) ? VK_SUCCESS : VK_INCOMPLETE;
1066 } else {
1067 *pDataSize = 10;
1068 return VK_SUCCESS;
1069 }
1070}
1071
1072#if FML_OS_ANDROID
1073
1074VkResult vkGetAndroidHardwareBufferPropertiesANDROID(
1075 VkDevice device,
1076 const struct AHardwareBuffer* buffer,
1077 VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
1078 pProperties->memoryTypeBits = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1079
1080 auto* out = reinterpret_cast<VkBaseOutStructure*>(pProperties->pNext);
1081 while (out != nullptr) {
1082 if (out->sType ==
1083 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID) {
1084 reinterpret_cast<VkAndroidHardwareBufferFormatPropertiesANDROID*>(out)
1085 ->format = VK_FORMAT_R8G8B8A8_UNORM;
1086 }
1087 out = out->pNext;
1088 }
1089
1090 return VK_SUCCESS;
1091}
1092
1093#endif // FML_OS_ANDROID
1094
1095PFN_vkVoidFunction GetMockVulkanProcAddress(VkInstance instance,
1096 const char* pName) {
1097 if (strcmp("vkEnumerateInstanceExtensionProperties", pName) == 0) {
1098 return reinterpret_cast<PFN_vkVoidFunction>(
1099 vkEnumerateInstanceExtensionProperties);
1100 } else if (strcmp("vkEnumerateInstanceLayerProperties", pName) == 0) {
1101 return reinterpret_cast<PFN_vkVoidFunction>(
1102 vkEnumerateInstanceLayerProperties);
1103 } else if (strcmp("vkEnumeratePhysicalDevices", pName) == 0) {
1104 return reinterpret_cast<PFN_vkVoidFunction>(vkEnumeratePhysicalDevices);
1105 } else if (strcmp("vkGetPhysicalDeviceFormatProperties", pName) == 0) {
1106 return reinterpret_cast<PFN_vkVoidFunction>(
1107 vkGetPhysicalDeviceFormatProperties);
1108 } else if (strcmp("vkGetPhysicalDeviceProperties", pName) == 0) {
1109 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceProperties);
1110 } else if (strcmp("vkGetPhysicalDeviceFeatures2", pName) == 0 ||
1111 strcmp("vkGetPhysicalDeviceFeatures2KHR", pName) == 0) {
1112 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceFeatures2);
1113 } else if (strcmp("vkGetPhysicalDeviceImageFormatProperties2", pName) == 0 ||
1114 strcmp("vkGetPhysicalDeviceImageFormatProperties2KHR", pName) ==
1115 0) {
1116 return reinterpret_cast<PFN_vkVoidFunction>(
1117 vkGetPhysicalDeviceImageFormatProperties2);
1118 } else if (strcmp("vkGetPhysicalDeviceQueueFamilyProperties", pName) == 0) {
1119 return reinterpret_cast<PFN_vkVoidFunction>(
1120 vkGetPhysicalDeviceQueueFamilyProperties);
1121 } else if (strcmp("vkEnumerateDeviceExtensionProperties", pName) == 0) {
1122 return reinterpret_cast<PFN_vkVoidFunction>(
1123 vkEnumerateDeviceExtensionProperties);
1124 } else if (strcmp("vkCreateDevice", pName) == 0) {
1125 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateDevice);
1126 } else if (strcmp("vkCreateInstance", pName) == 0) {
1127 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateInstance);
1128 } else if (strcmp("vkGetPhysicalDeviceMemoryProperties", pName) == 0) {
1129 return reinterpret_cast<PFN_vkVoidFunction>(
1130 vkGetPhysicalDeviceMemoryProperties);
1131 } else if (strcmp("vkCreatePipelineCache", pName) == 0) {
1132 return reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineCache);
1133 } else if (strcmp("vkCreateCommandPool", pName) == 0) {
1134 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateCommandPool);
1135 } else if (strcmp("vkResetCommandPool", pName) == 0) {
1136 return reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandPool);
1137 } else if (strcmp("vkAllocateCommandBuffers", pName) == 0) {
1138 return reinterpret_cast<PFN_vkVoidFunction>(vkAllocateCommandBuffers);
1139 } else if (strcmp("vkBeginCommandBuffer", pName) == 0) {
1140 return reinterpret_cast<PFN_vkVoidFunction>(vkBeginCommandBuffer);
1141 } else if (strcmp("vkCreateImage", pName) == 0) {
1142 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateImage);
1143 } else if (strcmp("vkDestroyImage", pName) == 0) {
1144 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImage);
1145 } else if (strcmp("vkGetInstanceProcAddr", pName) == 0) {
1146 return reinterpret_cast<PFN_vkVoidFunction>(GetMockVulkanProcAddress);
1147 } else if (strcmp("vkGetDeviceProcAddr", pName) == 0) {
1148 return reinterpret_cast<PFN_vkVoidFunction>(GetMockVulkanProcAddress);
1149 } else if (strcmp("vkGetImageMemoryRequirements2KHR", pName) == 0 ||
1150 strcmp("vkGetImageMemoryRequirements2", pName) == 0) {
1151 return reinterpret_cast<PFN_vkVoidFunction>(
1152 vkGetImageMemoryRequirements2KHR);
1153 } else if (strcmp("vkAllocateMemory", pName) == 0) {
1154 return reinterpret_cast<PFN_vkVoidFunction>(vkAllocateMemory);
1155 } else if (strcmp("vkBindImageMemory", pName) == 0) {
1156 return reinterpret_cast<PFN_vkVoidFunction>(vkBindImageMemory);
1157 } else if (strcmp("vkCreateImageView", pName) == 0) {
1158 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateImageView);
1159 } else if (strcmp("vkDestroyImageView", pName) == 0) {
1160 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImageView);
1161 } else if (strcmp("vkCreateBuffer", pName) == 0) {
1162 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateBuffer);
1163 } else if (strcmp("vkGetBufferMemoryRequirements2KHR", pName) == 0 ||
1164 strcmp("vkGetBufferMemoryRequirements2", pName) == 0) {
1165 return reinterpret_cast<PFN_vkVoidFunction>(
1166 vkGetBufferMemoryRequirements2KHR);
1167 } else if (strcmp("vkBindBufferMemory", pName) == 0) {
1168 return reinterpret_cast<PFN_vkVoidFunction>(vkBindBufferMemory);
1169 } else if (strcmp("vkCreateRenderPass", pName) == 0) {
1170 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateRenderPass);
1171 } else if (strcmp("vkCreateDescriptorSetLayout", pName) == 0) {
1172 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorSetLayout);
1173 } else if (strcmp("vkCreatePipelineLayout", pName) == 0) {
1174 return reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineLayout);
1175 } else if (strcmp("vkCreateGraphicsPipelines", pName) == 0) {
1176 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateGraphicsPipelines);
1177 } else if (strcmp("vkDeviceWaitIdle", pName) == 0) {
1178 return reinterpret_cast<PFN_vkVoidFunction>(vkDeviceWaitIdle);
1179 } else if (strcmp("vkDestroyDevice", pName) == 0) {
1180 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDevice);
1181 } else if (strcmp("vkDestroyInstance", pName) == 0) {
1182 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyInstance);
1183 } else if (strcmp("vkDestroyPipeline", pName) == 0) {
1184 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipeline);
1185 } else if (strcmp("vkCreateShaderModule", pName) == 0) {
1186 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateShaderModule);
1187 } else if (strcmp("vkDestroyShaderModule", pName) == 0) {
1188 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyShaderModule);
1189 } else if (strcmp("vkDestroyPipelineCache", pName) == 0) {
1190 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineCache);
1191 } else if (strcmp("vkCmdBindPipeline", pName) == 0) {
1192 return reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindPipeline);
1193 } else if (strcmp("vkCmdPipelineBarrier", pName) == 0) {
1194 return reinterpret_cast<PFN_vkVoidFunction>(vkCmdPipelineBarrier);
1195 } else if (strcmp("vkCmdSetStencilReference", pName) == 0) {
1196 return reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilReference);
1197 } else if (strcmp("vkCmdSetScissor", pName) == 0) {
1198 return reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetScissor);
1199 } else if (strcmp("vkCmdSetViewport", pName) == 0) {
1200 return reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetViewport);
1201 } else if (strcmp("vkDestroyCommandPool", pName) == 0) {
1202 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyCommandPool);
1203 } else if (strcmp("vkFreeCommandBuffers", pName) == 0) {
1204 return reinterpret_cast<PFN_vkVoidFunction>(vkFreeCommandBuffers);
1205 } else if (strcmp("vkEndCommandBuffer", pName) == 0) {
1206 return reinterpret_cast<PFN_vkVoidFunction>(vkEndCommandBuffer);
1207 } else if (strcmp("vkCreateFence", pName) == 0) {
1208 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateFence);
1209 } else if (strcmp("vkDestroyFence", pName) == 0) {
1210 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFence);
1211 } else if (strcmp("vkGetDeviceQueue", pName) == 0) {
1212 return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue);
1213 } else if (strcmp("vkQueueSubmit", pName) == 0) {
1214 return reinterpret_cast<PFN_vkVoidFunction>(vkQueueSubmit);
1215 } else if (strcmp("vkWaitForFences", pName) == 0) {
1216 return reinterpret_cast<PFN_vkVoidFunction>(vkWaitForFences);
1217 } else if (strcmp("vkGetFenceStatus", pName) == 0) {
1218 return reinterpret_cast<PFN_vkVoidFunction>(vkGetFenceStatus);
1219 } else if (strcmp("vkResetFences", pName) == 0) {
1220 return reinterpret_cast<PFN_vkVoidFunction>(vkResetFences);
1221 } else if (strcmp("vkCreateDebugUtilsMessengerEXT", pName) == 0) {
1222 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateDebugUtilsMessengerEXT);
1223 } else if (strcmp("vkSetDebugUtilsObjectNameEXT", pName) == 0) {
1224 return reinterpret_cast<PFN_vkVoidFunction>(vkSetDebugUtilsObjectNameEXT);
1225 } else if (strcmp("vkCreateQueryPool", pName) == 0) {
1226 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateQueryPool);
1227 } else if (strcmp("vkDestroyQueryPool", pName) == 0) {
1228 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyQueryPool);
1229 } else if (strcmp("vkGetQueryPoolResults", pName) == 0) {
1230 return reinterpret_cast<PFN_vkVoidFunction>(vkGetQueryPoolResults);
1231 } else if (strcmp("vkCreateDescriptorPool", pName) == 0) {
1232 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorPool);
1233 } else if (strcmp("vkDestroyDescriptorPool", pName) == 0) {
1234 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorPool);
1235 } else if (strcmp("vkResetDescriptorPool", pName) == 0) {
1236 return reinterpret_cast<PFN_vkVoidFunction>(vkResetDescriptorPool);
1237 } else if (strcmp("vkAllocateDescriptorSets", pName) == 0) {
1238 return reinterpret_cast<PFN_vkVoidFunction>(vkAllocateDescriptorSets);
1239 } else if (strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", pName) == 0) {
1240 return reinterpret_cast<PFN_vkVoidFunction>(
1241 vkGetPhysicalDeviceSurfaceFormatsKHR);
1242 } else if (strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", pName) == 0) {
1243 return reinterpret_cast<PFN_vkVoidFunction>(
1244 vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
1245 } else if (strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", pName) == 0) {
1246 return reinterpret_cast<PFN_vkVoidFunction>(
1247 vkGetPhysicalDeviceSurfaceSupportKHR);
1248 } else if (strcmp("vkCreateSwapchainKHR", pName) == 0) {
1249 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1250 } else if (strcmp("vkDestroySwapchainKHR", pName) == 0) {
1251 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1252 } else if (strcmp("vkGetSwapchainImagesKHR", pName) == 0) {
1253 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1254 } else if (strcmp("vkCreateSemaphore", pName) == 0) {
1255 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSemaphore);
1256 } else if (strcmp("vkDestroySemaphore", pName) == 0) {
1257 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySemaphore);
1258 } else if (strcmp("vkDestroySurfaceKHR", pName) == 0) {
1259 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySurfaceKHR);
1260 } else if (strcmp("vkAcquireNextImageKHR", pName) == 0) {
1261 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1262 } else if (strcmp("vkCreateFramebuffer", pName) == 0) {
1263 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateFramebuffer);
1264 } else if (strcmp("vkDestroyFramebuffer", pName) == 0) {
1265 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFramebuffer);
1266 } else if (strcmp("vkTrimCommandPool", pName) == 0) {
1267 return reinterpret_cast<PFN_vkVoidFunction>(vkTrimCommandPool);
1268 } else if (strcmp("vkGetPipelineCacheData", pName) == 0) {
1269 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPipelineCacheData);
1270 }
1271
1272#if FML_OS_ANDROID
1273 if (strcmp("vkGetAndroidHardwareBufferPropertiesANDROID", pName) == 0) {
1274 return reinterpret_cast<PFN_vkVoidFunction>(
1275 vkGetAndroidHardwareBufferPropertiesANDROID);
1276 }
1277#endif // FML_OS_ANDROID
1278
1279 return noop;
1280}
1281
1282} // namespace
1283
1285 : instance_extensions_({"VK_KHR_surface", "VK_MVK_macos_surface"}),
1286 device_extensions_({"VK_KHR_swapchain"}),
1287 format_properties_callback_([](VkPhysicalDevice physicalDevice,
1288 VkFormat format,
1289 VkFormatProperties* pFormatProperties) {
1290 if (format == VK_FORMAT_R8G8B8A8_UNORM) {
1291 pFormatProperties->optimalTilingFeatures =
1292 static_cast<VkFormatFeatureFlags>(
1293 vk::FormatFeatureFlagBits::eColorAttachment);
1294 } else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
1295 pFormatProperties->optimalTilingFeatures =
1296 static_cast<VkFormatFeatureFlags>(
1297 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
1298 } else if (format == VK_FORMAT_S8_UINT) {
1299 pFormatProperties->optimalTilingFeatures =
1300 static_cast<VkFormatFeatureFlags>(
1301 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
1302 }
1303 }) {}
1304
1305std::shared_ptr<ContextVK> MockVulkanContextBuilder::Build() {
1306 auto message_loop = fml::ConcurrentMessageLoop::Create();
1307 ContextVK::Settings settings;
1308 settings.proc_address_callback = GetMockVulkanProcAddress;
1309 if (settings_callback_) {
1310 settings_callback_(settings);
1311 }
1312 g_mock_vulkan_state.reset(new MockVulkanState());
1313 g_mock_vulkan_state->instance_extensions = instance_extensions_;
1314 g_mock_vulkan_state->instance_layers = instance_layers_;
1315 g_mock_vulkan_state->device_extensions = device_extensions_;
1316 g_mock_vulkan_state->format_properties_callback = format_properties_callback_;
1317 g_mock_vulkan_state->physical_device_properties_callback =
1318 physical_properties_callback_;
1319 g_mock_vulkan_state->acquire_next_image_callback =
1320 acquire_next_image_callback_;
1321 g_mock_vulkan_state->wait_for_fences_callback = wait_for_fences_callback_;
1322 g_mock_vulkan_state->compression_exhausted_create_image_failures =
1323 compression_exhausted_create_image_failures_;
1324 settings.embedder_data = embedder_data_;
1325 std::shared_ptr<ContextVK> result = ContextVK::Create(std::move(settings));
1326 return result;
1327}
1328
1329std::shared_ptr<std::vector<std::string>> GetMockVulkanFunctions(
1330 VkDevice device) {
1331 MockDevice* mock_device = MockDevice::Unwrap(device);
1332 return mock_device->GetCalledFunctions();
1333}
1334
1336 currentImageSize = size;
1337}
1338
1339std::vector<VkImageMemoryBarrier>& GetImageMemoryBarriers(
1340 VkCommandBuffer buffer) {
1341 MockCommandBuffer* mock_command_buffer =
1342 reinterpret_cast<MockCommandBuffer*>(buffer);
1343 return mock_command_buffer->image_memory_barriers_;
1344}
1345
1346const std::vector<VkViewport>& GetRecordedViewports(VkCommandBuffer buffer) {
1347 MockCommandBuffer* mock_command_buffer =
1348 reinterpret_cast<MockCommandBuffer*>(buffer);
1349 return mock_command_buffer->recorded_viewports_;
1350}
1351
1352} // namespace testing
1353} // namespace impeller
static std::shared_ptr< ConcurrentMessageLoop > Create(size_t worker_count=std::thread::hardware_concurrency())
static std::shared_ptr< ContextVK > Create(Settings settings)
MockCommandBuffer(std::weak_ptr< const Context > context)
Definition mocks.h:143
std::shared_ptr< ContextVK > Build()
Create a Vulkan context with Vulkan functions mocked. The caller is given a chance to tinker on the s...
FlutterVulkanImage * image
VkSwapchainKHR swapchain
Definition main.cc:80
VkPhysicalDevice physical_device
Definition main.cc:67
VkDevice device
Definition main.cc:69
VkInstance instance
Definition main.cc:64
VkQueue queue
Definition main.cc:71
#define FML_CHECK(condition)
Definition logging.h:104
size_t length
size_t current_image
std::vector< std::string > instance_layers
std::vector< std::string > device_extensions
std::function< void(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties)> format_properties_callback
std::function< void(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)> physical_device_properties_callback
std::function< std::remove_pointer_t< PFN_vkWaitForFences > > wait_for_fences_callback
int compression_exhausted_create_image_failures
std::shared_ptr< std::vector< std::string > > called_functions_
std::array< MockImage, 3 > images
std::vector< std::string > instance_extensions
std::function< std::remove_pointer_t< PFN_vkAcquireNextImageKHR > > acquire_next_image_callback
std::vector< VkImageMemoryBarrier > image_memory_barriers_
std::vector< VkViewport > recorded_viewports_
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
std::shared_ptr< std::vector< std::string > > GetMockVulkanFunctions(VkDevice device)
const std::vector< VkViewport > & GetRecordedViewports(VkCommandBuffer buffer)
Returns the viewports passed to vkCmdSetViewport calls on the given command buffer,...
std::vector< VkImageMemoryBarrier > & GetImageMemoryBarriers(VkCommandBuffer buffer)
void SetSwapchainImageSize(ISize size)
Override the image size returned by all swapchain images.
constexpr Color operator*(T value, const Color &c)
Definition color.h:914
ISize64 ISize
Definition size.h:162
Definition ref_ptr.h:261
std::shared_ptr< PipelineGLES > pipeline
int32_t height
PFN_vkGetInstanceProcAddr proc_address_callback
Definition context_vk.h:84
std::optional< EmbedderData > embedder_data
Definition context_vk.h:94
#define IPLR_GUARDED_BY(x)