blob: c18a569315863c1148b98722e4b056cc465ea60b [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
#include <cstdint>
#include <cstring>
#include <utility>
#include <vector>
#include "impeller/base/thread_safety.h"
#include "impeller/renderer/backend/vulkan/vk.h" // IWYU pragma: keep.
#include "third_party/swiftshader/include/vulkan/vulkan_core.h"
#include "vulkan/vulkan.hpp"
#include "vulkan/vulkan_core.h"
namespace impeller {
namespace testing {
namespace {
struct MockCommandBuffer {
explicit MockCommandBuffer(
std::shared_ptr<std::vector<std::string>> called_functions)
: called_functions_(std::move(called_functions)) {}
std::shared_ptr<std::vector<std::string>> called_functions_;
};
struct MockQueryPool {};
struct MockCommandPool {};
struct MockDescriptorPool {};
struct MockSurfaceKHR {};
struct MockImage {};
struct MockSwapchainKHR {
std::array<MockImage, 3> images;
size_t current_image = 0;
};
struct MockSemaphore {};
struct MockFramebuffer {};
static ISize currentImageSize = ISize{1, 1};
class MockDevice final {
public:
explicit MockDevice() : called_functions_(new std::vector<std::string>()) {}
MockCommandBuffer* NewCommandBuffer() {
auto buffer = std::make_unique<MockCommandBuffer>(called_functions_);
MockCommandBuffer* result = buffer.get();
Lock lock(command_buffers_mutex_);
command_buffers_.emplace_back(std::move(buffer));
return result;
}
MockCommandPool* NewCommandPool() {
auto pool = std::make_unique<MockCommandPool>();
MockCommandPool* result = pool.get();
Lock lock(commmand_pools_mutex_);
command_pools_.emplace_back(std::move(pool));
return result;
}
void DeleteCommandPool(MockCommandPool* pool) {
Lock lock(commmand_pools_mutex_);
auto it = std::find_if(command_pools_.begin(), command_pools_.end(),
[pool](const std::unique_ptr<MockCommandPool>& p) {
return p.get() == pool;
});
if (it != command_pools_.end()) {
command_pools_.erase(it);
}
}
const std::shared_ptr<std::vector<std::string>>& GetCalledFunctions() {
return called_functions_;
}
void AddCalledFunction(const std::string& function) {
Lock lock(called_functions_mutex_);
called_functions_->push_back(function);
}
private:
MockDevice(const MockDevice&) = delete;
MockDevice& operator=(const MockDevice&) = delete;
Mutex called_functions_mutex_;
std::shared_ptr<std::vector<std::string>> called_functions_ IPLR_GUARDED_BY(
called_functions_mutex_);
Mutex command_buffers_mutex_;
std::vector<std::unique_ptr<MockCommandBuffer>> command_buffers_
IPLR_GUARDED_BY(command_buffers_mutex_);
Mutex commmand_pools_mutex_;
std::vector<std::unique_ptr<MockCommandPool>> command_pools_ IPLR_GUARDED_BY(
commmand_pools_mutex_);
};
void noop() {}
static thread_local std::vector<std::string> g_instance_extensions;
VkResult vkEnumerateInstanceExtensionProperties(
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (!pProperties) {
*pPropertyCount = g_instance_extensions.size();
} else {
uint32_t count = 0;
for (const std::string& ext : g_instance_extensions) {
strncpy(pProperties[count].extensionName, ext.c_str(),
sizeof(VkExtensionProperties::extensionName));
pProperties[count].specVersion = 0;
count++;
}
}
return VK_SUCCESS;
}
static thread_local std::vector<std::string> g_instance_layers;
VkResult vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
VkLayerProperties* pProperties) {
if (!pProperties) {
*pPropertyCount = g_instance_layers.size();
} else {
uint32_t count = 0;
for (const std::string& layer : g_instance_layers) {
strncpy(pProperties[count].layerName, layer.c_str(),
sizeof(VkLayerProperties::layerName));
pProperties[count].specVersion = 0;
count++;
}
}
return VK_SUCCESS;
}
VkResult vkEnumeratePhysicalDevices(VkInstance instance,
uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices) {
if (!pPhysicalDevices) {
*pPhysicalDeviceCount = 1;
} else {
pPhysicalDevices[0] = reinterpret_cast<VkPhysicalDevice>(0xfeedface);
}
return VK_SUCCESS;
}
static thread_local std::function<void(VkPhysicalDevice physicalDevice,
VkFormat format,
VkFormatProperties* pFormatProperties)>
g_format_properties_callback;
void vkGetPhysicalDeviceFormatProperties(
VkPhysicalDevice physicalDevice,
VkFormat format,
VkFormatProperties* pFormatProperties) {
g_format_properties_callback(physicalDevice, format, pFormatProperties);
}
void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties) {
pProperties->limits.framebufferColorSampleCounts =
static_cast<VkSampleCountFlags>(VK_SAMPLE_COUNT_1_BIT |
VK_SAMPLE_COUNT_4_BIT);
pProperties->limits.maxImageDimension2D = 4096;
pProperties->limits.timestampPeriod = 1;
}
void vkGetPhysicalDeviceQueueFamilyProperties(
VkPhysicalDevice physicalDevice,
uint32_t* pQueueFamilyPropertyCount,
VkQueueFamilyProperties* pQueueFamilyProperties) {
if (!pQueueFamilyProperties) {
*pQueueFamilyPropertyCount = 1;
} else {
pQueueFamilyProperties[0].queueCount = 3;
pQueueFamilyProperties[0].queueFlags = static_cast<VkQueueFlags>(
VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT);
}
}
VkResult vkEnumerateDeviceExtensionProperties(
VkPhysicalDevice physicalDevice,
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (!pProperties) {
*pPropertyCount = 1;
} else {
strcpy(pProperties[0].extensionName, "VK_KHR_swapchain");
pProperties[0].specVersion = 0;
}
return VK_SUCCESS;
}
VkResult vkCreateDevice(VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice) {
*pDevice = reinterpret_cast<VkDevice>(new MockDevice());
return VK_SUCCESS;
}
VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) {
*pInstance = reinterpret_cast<VkInstance>(0xbaadf00d);
return VK_SUCCESS;
}
void vkGetPhysicalDeviceMemoryProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
pMemoryProperties->memoryTypeCount = 2;
pMemoryProperties->memoryHeapCount = 2;
pMemoryProperties->memoryTypes[0].heapIndex = 0;
pMemoryProperties->memoryTypes[0].propertyFlags =
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
pMemoryProperties->memoryTypes[1].heapIndex = 1;
pMemoryProperties->memoryTypes[1].propertyFlags =
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
pMemoryProperties->memoryHeaps[0].size = 1024 * 1024 * 1024;
pMemoryProperties->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
pMemoryProperties->memoryHeaps[1].size = 1024 * 1024 * 1024;
pMemoryProperties->memoryHeaps[1].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
}
VkResult vkCreatePipelineCache(VkDevice device,
const VkPipelineCacheCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkPipelineCache* pPipelineCache) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkCreatePipelineCache");
*pPipelineCache = reinterpret_cast<VkPipelineCache>(0xb000dead);
return VK_SUCCESS;
}
VkResult vkCreateCommandPool(VkDevice device,
const VkCommandPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkCommandPool* pCommandPool) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkCreateCommandPool");
*pCommandPool =
reinterpret_cast<VkCommandPool>(mock_device->NewCommandPool());
return VK_SUCCESS;
}
VkResult vkResetCommandPool(VkDevice device,
VkCommandPool commandPool,
VkCommandPoolResetFlags flags) {
return VK_SUCCESS;
}
VkResult vkAllocateCommandBuffers(
VkDevice device,
const VkCommandBufferAllocateInfo* pAllocateInfo,
VkCommandBuffer* pCommandBuffers) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkAllocateCommandBuffers");
*pCommandBuffers =
reinterpret_cast<VkCommandBuffer>(mock_device->NewCommandBuffer());
return VK_SUCCESS;
}
VkResult vkBeginCommandBuffer(VkCommandBuffer commandBuffer,
const VkCommandBufferBeginInfo* pBeginInfo) {
return VK_SUCCESS;
}
VkResult vkCreateImage(VkDevice device,
const VkImageCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkImage* pImage) {
*pImage = reinterpret_cast<VkImage>(0xD0D0CACA);
return VK_SUCCESS;
}
void vkGetImageMemoryRequirements2KHR(
VkDevice device,
const VkImageMemoryRequirementsInfo2* pInfo,
VkMemoryRequirements2* pMemoryRequirements) {
pMemoryRequirements->memoryRequirements.size = 1024;
pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
}
VkResult vkAllocateMemory(VkDevice device,
const VkMemoryAllocateInfo* pAllocateInfo,
const VkAllocationCallbacks* pAllocator,
VkDeviceMemory* pMemory) {
*pMemory = reinterpret_cast<VkDeviceMemory>(0xCAFEB0BA);
return VK_SUCCESS;
}
VkResult vkBindImageMemory(VkDevice device,
VkImage image,
VkDeviceMemory memory,
VkDeviceSize memoryOffset) {
return VK_SUCCESS;
}
VkResult vkCreateImageView(VkDevice device,
const VkImageViewCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkImageView* pView) {
*pView = reinterpret_cast<VkImageView>(0xFEE1DEAD);
return VK_SUCCESS;
}
VkResult vkCreateBuffer(VkDevice device,
const VkBufferCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkBuffer* pBuffer) {
*pBuffer = reinterpret_cast<VkBuffer>(0xDEADDEAD);
return VK_SUCCESS;
}
void vkGetBufferMemoryRequirements2KHR(
VkDevice device,
const VkBufferMemoryRequirementsInfo2* pInfo,
VkMemoryRequirements2* pMemoryRequirements) {
pMemoryRequirements->memoryRequirements.size = 1024;
pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
}
VkResult vkBindBufferMemory(VkDevice device,
VkBuffer buffer,
VkDeviceMemory memory,
VkDeviceSize memoryOffset) {
return VK_SUCCESS;
}
VkResult vkCreateRenderPass(VkDevice device,
const VkRenderPassCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkRenderPass* pRenderPass) {
*pRenderPass = reinterpret_cast<VkRenderPass>(0x12341234);
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkCreateRenderPass");
return VK_SUCCESS;
}
VkResult vkCreateDescriptorSetLayout(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorSetLayout* pSetLayout) {
*pSetLayout = reinterpret_cast<VkDescriptorSetLayout>(0x77777777);
return VK_SUCCESS;
}
VkResult vkCreatePipelineLayout(VkDevice device,
const VkPipelineLayoutCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkPipelineLayout* pPipelineLayout) {
*pPipelineLayout = reinterpret_cast<VkPipelineLayout>(0x88888888);
return VK_SUCCESS;
}
VkResult vkCreateGraphicsPipelines(
VkDevice device,
VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo* pCreateInfos,
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkCreateGraphicsPipelines");
*pPipelines = reinterpret_cast<VkPipeline>(0x99999999);
return VK_SUCCESS;
}
void vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkDestroyDevice");
delete reinterpret_cast<MockDevice*>(device);
}
void vkDestroyPipeline(VkDevice device,
VkPipeline pipeline,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkDestroyPipeline");
}
VkResult vkCreateShaderModule(VkDevice device,
const VkShaderModuleCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkShaderModule* pShaderModule) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkCreateShaderModule");
*pShaderModule = reinterpret_cast<VkShaderModule>(0x11111111);
return VK_SUCCESS;
}
void vkDestroyShaderModule(VkDevice device,
VkShaderModule shaderModule,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkDestroyShaderModule");
}
void vkDestroyPipelineCache(VkDevice device,
VkPipelineCache pipelineCache,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkDestroyPipelineCache");
}
void vkDestroySurfaceKHR(VkInstance instance,
VkSurfaceKHR surface,
const VkAllocationCallbacks* pAllocator) {
return;
}
void vkCmdBindPipeline(VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipeline pipeline) {
MockCommandBuffer* mock_command_buffer =
reinterpret_cast<MockCommandBuffer*>(commandBuffer);
mock_command_buffer->called_functions_->push_back("vkCmdBindPipeline");
}
void vkCmdSetStencilReference(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t reference) {
MockCommandBuffer* mock_command_buffer =
reinterpret_cast<MockCommandBuffer*>(commandBuffer);
mock_command_buffer->called_functions_->push_back("vkCmdSetStencilReference");
}
void vkCmdSetScissor(VkCommandBuffer commandBuffer,
uint32_t firstScissor,
uint32_t scissorCount,
const VkRect2D* pScissors) {
MockCommandBuffer* mock_command_buffer =
reinterpret_cast<MockCommandBuffer*>(commandBuffer);
mock_command_buffer->called_functions_->push_back("vkCmdSetScissor");
}
void vkCmdSetViewport(VkCommandBuffer commandBuffer,
uint32_t firstViewport,
uint32_t viewportCount,
const VkViewport* pViewports) {
MockCommandBuffer* mock_command_buffer =
reinterpret_cast<MockCommandBuffer*>(commandBuffer);
mock_command_buffer->called_functions_->push_back("vkCmdSetViewport");
}
void vkFreeCommandBuffers(VkDevice device,
VkCommandPool commandPool,
uint32_t commandBufferCount,
const VkCommandBuffer* pCommandBuffers) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkFreeCommandBuffers");
}
void vkDestroyCommandPool(VkDevice device,
VkCommandPool commandPool,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->DeleteCommandPool(
reinterpret_cast<MockCommandPool*>(commandPool));
mock_device->AddCalledFunction("vkDestroyCommandPool");
}
VkResult vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
return VK_SUCCESS;
}
VkResult vkCreateFence(VkDevice device,
const VkFenceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
*pFence = reinterpret_cast<VkFence>(new MockFence());
return VK_SUCCESS;
}
VkResult vkDestroyFence(VkDevice device,
VkFence fence,
const VkAllocationCallbacks* pAllocator) {
delete reinterpret_cast<MockFence*>(fence);
return VK_SUCCESS;
}
VkResult vkQueueSubmit(VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo* pSubmits,
VkFence fence) {
return VK_SUCCESS;
}
VkResult vkWaitForFences(VkDevice device,
uint32_t fenceCount,
const VkFence* pFences,
VkBool32 waitAll,
uint64_t timeout) {
return VK_SUCCESS;
}
VkResult vkGetFenceStatus(VkDevice device, VkFence fence) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
MockFence* mock_fence = reinterpret_cast<MockFence*>(fence);
return mock_fence->GetStatus();
}
VkResult vkResetFences(VkDevice device,
uint32_t fenceCount,
const VkFence* fences) {
return VK_SUCCESS;
}
VkResult vkCreateDebugUtilsMessengerEXT(
VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDebugUtilsMessengerEXT* pMessenger) {
return VK_SUCCESS;
}
VkResult vkSetDebugUtilsObjectNameEXT(
VkDevice device,
const VkDebugUtilsObjectNameInfoEXT* pNameInfo) {
return VK_SUCCESS;
}
VkResult vkCreateQueryPool(VkDevice device,
const VkQueryPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkQueryPool* pQueryPool) {
*pQueryPool = reinterpret_cast<VkQueryPool>(new MockQueryPool());
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkCreateQueryPool");
return VK_SUCCESS;
}
void vkDestroyQueryPool(VkDevice device,
VkQueryPool queryPool,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkDestroyQueryPool");
delete reinterpret_cast<MockQueryPool*>(queryPool);
}
VkResult vkGetQueryPoolResults(VkDevice device,
VkQueryPool queryPool,
uint32_t firstQuery,
uint32_t queryCount,
size_t dataSize,
void* pData,
VkDeviceSize stride,
VkQueryResultFlags flags) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
if (dataSize == sizeof(uint32_t)) {
uint32_t* data = static_cast<uint32_t*>(pData);
for (auto i = firstQuery; i < queryCount; i++) {
data[0] = i;
}
} else if (dataSize == sizeof(int64_t)) {
uint64_t* data = static_cast<uint64_t*>(pData);
for (auto i = firstQuery; i < queryCount; i++) {
data[0] = i;
}
}
mock_device->AddCalledFunction("vkGetQueryPoolResults");
return VK_SUCCESS;
}
VkResult vkCreateDescriptorPool(VkDevice device,
const VkDescriptorPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorPool* pDescriptorPool) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
*pDescriptorPool =
reinterpret_cast<VkDescriptorPool>(new MockDescriptorPool());
mock_device->AddCalledFunction("vkCreateDescriptorPool");
return VK_SUCCESS;
}
void vkDestroyDescriptorPool(VkDevice device,
VkDescriptorPool descriptorPool,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkDestroyDescriptorPool");
delete reinterpret_cast<MockDescriptorPool*>(descriptorPool);
}
VkResult vkResetDescriptorPool(VkDevice device,
VkDescriptorPool descriptorPool,
VkDescriptorPoolResetFlags flags) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkResetDescriptorPool");
return VK_SUCCESS;
}
VkResult vkAllocateDescriptorSets(
VkDevice device,
const VkDescriptorSetAllocateInfo* pAllocateInfo,
VkDescriptorSet* pDescriptorSets) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->AddCalledFunction("vkAllocateDescriptorSets");
return VK_SUCCESS;
}
VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
uint32_t* pSurfaceFormatCount,
VkSurfaceFormatKHR* pSurfaceFormats) {
*pSurfaceFormatCount = 1u;
if (pSurfaceFormats != nullptr) {
pSurfaceFormats[0] =
VkSurfaceFormatKHR{.format = VK_FORMAT_R8G8B8A8_UNORM,
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
}
return VK_SUCCESS;
}
VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
*pSurfaceCapabilities = VkSurfaceCapabilitiesKHR{
.minImageCount = 3,
.maxImageCount = 6,
.currentExtent =
VkExtent2D{
.width = static_cast<uint32_t>(currentImageSize.width),
.height = static_cast<uint32_t>(currentImageSize.height),
},
.minImageExtent =
VkExtent2D{
.width = 0,
.height = 0,
},
.maxImageExtent =
VkExtent2D{
.width = static_cast<uint32_t>(currentImageSize.width),
.height = static_cast<uint32_t>(currentImageSize.height),
},
.maxImageArrayLayers = 1,
.supportedTransforms =
VkSurfaceTransformFlagBitsKHR::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
.currentTransform =
VkSurfaceTransformFlagBitsKHR::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
.supportedCompositeAlpha = VkCompositeAlphaFlagBitsKHR::
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
.supportedUsageFlags =
VkImageUsageFlagBits::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT};
return VK_SUCCESS;
}
VkResult vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
VkSurfaceKHR surface,
VkBool32* pSupported) {
*pSupported = VK_TRUE;
return VK_SUCCESS;
}
VkResult vkCreateSwapchainKHR(VkDevice device,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSwapchainKHR* pSwapchain) {
*pSwapchain = reinterpret_cast<VkSwapchainKHR>(new MockSwapchainKHR());
return VK_SUCCESS;
}
void vkDestroySwapchainKHR(VkDevice device,
VkSwapchainKHR swapchain,
const VkAllocationCallbacks* pAllocator) {
delete reinterpret_cast<MockSwapchainKHR*>(swapchain);
}
VkResult vkGetSwapchainImagesKHR(VkDevice device,
VkSwapchainKHR swapchain,
uint32_t* pSwapchainImageCount,
VkImage* pSwapchainImages) {
MockSwapchainKHR* mock_swapchain =
reinterpret_cast<MockSwapchainKHR*>(swapchain);
auto& images = mock_swapchain->images;
*pSwapchainImageCount = images.size();
if (pSwapchainImages != nullptr) {
for (size_t i = 0; i < images.size(); i++) {
pSwapchainImages[i] = reinterpret_cast<VkImage>(&images[i]);
}
}
return VK_SUCCESS;
}
VkResult vkCreateSemaphore(VkDevice device,
const VkSemaphoreCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSemaphore* pSemaphore) {
*pSemaphore = reinterpret_cast<VkSemaphore>(new MockSemaphore());
return VK_SUCCESS;
}
void vkDestroySemaphore(VkDevice device,
VkSemaphore semaphore,
const VkAllocationCallbacks* pAllocator) {
delete reinterpret_cast<MockSemaphore*>(semaphore);
}
VkResult vkAcquireNextImageKHR(VkDevice device,
VkSwapchainKHR swapchain,
uint64_t timeout,
VkSemaphore semaphore,
VkFence fence,
uint32_t* pImageIndex) {
auto current_index =
reinterpret_cast<MockSwapchainKHR*>(swapchain)->current_image++;
*pImageIndex = (current_index + 1) % 3u;
return VK_SUCCESS;
}
VkResult vkCreateFramebuffer(VkDevice device,
const VkFramebufferCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFramebuffer* pFramebuffer) {
*pFramebuffer = reinterpret_cast<VkFramebuffer>(new MockFramebuffer());
return VK_SUCCESS;
}
void vkDestroyFramebuffer(VkDevice device,
VkFramebuffer framebuffer,
const VkAllocationCallbacks* pAllocator) {
delete reinterpret_cast<MockFramebuffer*>(framebuffer);
}
PFN_vkVoidFunction GetMockVulkanProcAddress(VkInstance instance,
const char* pName) {
if (strcmp("vkEnumerateInstanceExtensionProperties", pName) == 0) {
return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties;
} else if (strcmp("vkEnumerateInstanceLayerProperties", pName) == 0) {
return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties;
} else if (strcmp("vkEnumeratePhysicalDevices", pName) == 0) {
return (PFN_vkVoidFunction)vkEnumeratePhysicalDevices;
} else if (strcmp("vkGetPhysicalDeviceFormatProperties", pName) == 0) {
return (PFN_vkVoidFunction)vkGetPhysicalDeviceFormatProperties;
} else if (strcmp("vkGetPhysicalDeviceProperties", pName) == 0) {
return (PFN_vkVoidFunction)vkGetPhysicalDeviceProperties;
} else if (strcmp("vkGetPhysicalDeviceQueueFamilyProperties", pName) == 0) {
return (PFN_vkVoidFunction)vkGetPhysicalDeviceQueueFamilyProperties;
} else if (strcmp("vkEnumerateDeviceExtensionProperties", pName) == 0) {
return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
} else if (strcmp("vkCreateDevice", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateDevice;
} else if (strcmp("vkCreateInstance", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateInstance;
} else if (strcmp("vkGetPhysicalDeviceMemoryProperties", pName) == 0) {
return (PFN_vkVoidFunction)vkGetPhysicalDeviceMemoryProperties;
} else if (strcmp("vkCreatePipelineCache", pName) == 0) {
return (PFN_vkVoidFunction)vkCreatePipelineCache;
} else if (strcmp("vkCreateCommandPool", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateCommandPool;
} else if (strcmp("vkResetCommandPool", pName) == 0) {
return (PFN_vkVoidFunction)vkResetCommandPool;
} else if (strcmp("vkAllocateCommandBuffers", pName) == 0) {
return (PFN_vkVoidFunction)vkAllocateCommandBuffers;
} else if (strcmp("vkBeginCommandBuffer", pName) == 0) {
return (PFN_vkVoidFunction)vkBeginCommandBuffer;
} else if (strcmp("vkCreateImage", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateImage;
} else if (strcmp("vkGetInstanceProcAddr", pName) == 0) {
return (PFN_vkVoidFunction)GetMockVulkanProcAddress;
} else if (strcmp("vkGetDeviceProcAddr", pName) == 0) {
return (PFN_vkVoidFunction)GetMockVulkanProcAddress;
} else if (strcmp("vkGetImageMemoryRequirements2KHR", pName) == 0 ||
strcmp("vkGetImageMemoryRequirements2", pName) == 0) {
return (PFN_vkVoidFunction)vkGetImageMemoryRequirements2KHR;
} else if (strcmp("vkAllocateMemory", pName) == 0) {
return (PFN_vkVoidFunction)vkAllocateMemory;
} else if (strcmp("vkBindImageMemory", pName) == 0) {
return (PFN_vkVoidFunction)vkBindImageMemory;
} else if (strcmp("vkCreateImageView", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateImageView;
} else if (strcmp("vkCreateBuffer", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateBuffer;
} else if (strcmp("vkGetBufferMemoryRequirements2KHR", pName) == 0 ||
strcmp("vkGetBufferMemoryRequirements2", pName) == 0) {
return (PFN_vkVoidFunction)vkGetBufferMemoryRequirements2KHR;
} else if (strcmp("vkBindBufferMemory", pName) == 0) {
return (PFN_vkVoidFunction)vkBindBufferMemory;
} else if (strcmp("vkCreateRenderPass", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateRenderPass;
} else if (strcmp("vkCreateDescriptorSetLayout", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateDescriptorSetLayout;
} else if (strcmp("vkCreatePipelineLayout", pName) == 0) {
return (PFN_vkVoidFunction)vkCreatePipelineLayout;
} else if (strcmp("vkCreateGraphicsPipelines", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateGraphicsPipelines;
} else if (strcmp("vkDestroyDevice", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyDevice;
} else if (strcmp("vkDestroyPipeline", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyPipeline;
} else if (strcmp("vkCreateShaderModule", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateShaderModule;
} else if (strcmp("vkDestroyShaderModule", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyShaderModule;
} else if (strcmp("vkDestroyPipelineCache", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyPipelineCache;
} else if (strcmp("vkCmdBindPipeline", pName) == 0) {
return (PFN_vkVoidFunction)vkCmdBindPipeline;
} else if (strcmp("vkCmdSetStencilReference", pName) == 0) {
return (PFN_vkVoidFunction)vkCmdSetStencilReference;
} else if (strcmp("vkCmdSetScissor", pName) == 0) {
return (PFN_vkVoidFunction)vkCmdSetScissor;
} else if (strcmp("vkCmdSetViewport", pName) == 0) {
return (PFN_vkVoidFunction)vkCmdSetViewport;
} else if (strcmp("vkDestroyCommandPool", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyCommandPool;
} else if (strcmp("vkFreeCommandBuffers", pName) == 0) {
return (PFN_vkVoidFunction)vkFreeCommandBuffers;
} else if (strcmp("vkEndCommandBuffer", pName) == 0) {
return (PFN_vkVoidFunction)vkEndCommandBuffer;
} else if (strcmp("vkCreateFence", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateFence;
} else if (strcmp("vkDestroyFence", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyFence;
} else if (strcmp("vkQueueSubmit", pName) == 0) {
return (PFN_vkVoidFunction)vkQueueSubmit;
} else if (strcmp("vkWaitForFences", pName) == 0) {
return (PFN_vkVoidFunction)vkWaitForFences;
} else if (strcmp("vkGetFenceStatus", pName) == 0) {
return (PFN_vkVoidFunction)vkGetFenceStatus;
} else if (strcmp("vkResetFences", pName) == 0) {
return (PFN_vkVoidFunction)vkResetFences;
} else if (strcmp("vkCreateDebugUtilsMessengerEXT", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
} else if (strcmp("vkSetDebugUtilsObjectNameEXT", pName) == 0) {
return (PFN_vkVoidFunction)vkSetDebugUtilsObjectNameEXT;
} else if (strcmp("vkCreateQueryPool", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateQueryPool;
} else if (strcmp("vkDestroyQueryPool", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyQueryPool;
} else if (strcmp("vkGetQueryPoolResults", pName) == 0) {
return (PFN_vkVoidFunction)vkGetQueryPoolResults;
} else if (strcmp("vkCreateDescriptorPool", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateDescriptorPool;
} else if (strcmp("vkDestroyDescriptorPool", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyDescriptorPool;
} else if (strcmp("vkResetDescriptorPool", pName) == 0) {
return (PFN_vkVoidFunction)vkResetDescriptorPool;
} else if (strcmp("vkAllocateDescriptorSets", pName) == 0) {
return (PFN_vkVoidFunction)vkAllocateDescriptorSets;
} else if (strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkGetPhysicalDeviceSurfaceFormatsKHR;
} else if (strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
} else if (strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkGetPhysicalDeviceSurfaceSupportKHR;
} else if (strcmp("vkCreateSwapchainKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateSwapchainKHR;
} else if (strcmp("vkDestroySwapchainKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroySwapchainKHR;
} else if (strcmp("vkGetSwapchainImagesKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkGetSwapchainImagesKHR;
} else if (strcmp("vkCreateSemaphore", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateSemaphore;
} else if (strcmp("vkDestroySemaphore", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroySemaphore;
} else if (strcmp("vkDestroySurfaceKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroySurfaceKHR;
} else if (strcmp("vkAcquireNextImageKHR", pName) == 0) {
return (PFN_vkVoidFunction)vkAcquireNextImageKHR;
} else if (strcmp("vkCreateFramebuffer", pName) == 0) {
return (PFN_vkVoidFunction)vkCreateFramebuffer;
} else if (strcmp("vkDestroyFramebuffer", pName) == 0) {
return (PFN_vkVoidFunction)vkDestroyFramebuffer;
}
return noop;
}
} // namespace
MockVulkanContextBuilder::MockVulkanContextBuilder()
: instance_extensions_({"VK_KHR_surface", "VK_MVK_macos_surface"}),
format_properties_callback_([](VkPhysicalDevice physicalDevice,
VkFormat format,
VkFormatProperties* pFormatProperties) {
if (format == VK_FORMAT_R8G8B8A8_UNORM) {
pFormatProperties->optimalTilingFeatures =
static_cast<VkFormatFeatureFlags>(
vk::FormatFeatureFlagBits::eColorAttachment);
} else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
pFormatProperties->optimalTilingFeatures =
static_cast<VkFormatFeatureFlags>(
vk::FormatFeatureFlagBits::eDepthStencilAttachment);
} else if (format == VK_FORMAT_S8_UINT) {
pFormatProperties->optimalTilingFeatures =
static_cast<VkFormatFeatureFlags>(
vk::FormatFeatureFlagBits::eDepthStencilAttachment);
}
}) {}
std::shared_ptr<ContextVK> MockVulkanContextBuilder::Build() {
auto message_loop = fml::ConcurrentMessageLoop::Create();
ContextVK::Settings settings;
settings.proc_address_callback = GetMockVulkanProcAddress;
if (settings_callback_) {
settings_callback_(settings);
}
g_instance_extensions = instance_extensions_;
g_instance_layers = instance_layers_;
g_format_properties_callback = format_properties_callback_;
std::shared_ptr<ContextVK> result = ContextVK::Create(std::move(settings));
return result;
}
std::shared_ptr<std::vector<std::string>> GetMockVulkanFunctions(
VkDevice device) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
return mock_device->GetCalledFunctions();
}
void SetSwapchainImageSize(ISize size) {
currentImageSize = size;
}
} // namespace testing
} // namespace impeller