Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions impeller/renderer/backend/vulkan/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ impeller_component("vulkan_unittests") {
"resource_manager_vk_unittests.cc",
"test/mock_vulkan.cc",
"test/mock_vulkan.h",
"test/mock_vulkan_unittests.cc",
]
deps = [
":vulkan",
Expand Down
48 changes: 34 additions & 14 deletions impeller/renderer/backend/vulkan/test/mock_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// found in the LICENSE file.

#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
#include <vector>
#include "fml/macros.h"

namespace impeller {
namespace testing {
Expand All @@ -16,16 +18,34 @@ struct MockCommandBuffer {
std::shared_ptr<std::vector<std::string>> called_functions_;
};

struct MockDevice {
MockDevice() : called_functions_(new std::vector<std::string>()) {}
class MockDevice final {
public:
explicit MockDevice() : called_functions_(new std::vector<std::string>()) {}

MockCommandBuffer* NewCommandBuffer() {
std::unique_ptr<MockCommandBuffer> buffer =
std::make_unique<MockCommandBuffer>(called_functions_);
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;
}

std::shared_ptr<std::vector<std::string>>& GetCalledFunctions() {
return called_functions_;
}

void was_called(const std::string& function) {
Lock lock(called_functions_mutex_);
called_functions_->push_back(function);
}

private:
FML_DISALLOW_COPY_AND_ASSIGN(MockDevice);

Mutex called_functions_mutex_;
std::shared_ptr<std::vector<std::string>> called_functions_;

Mutex command_buffers_mutex_;
std::vector<std::unique_ptr<MockCommandBuffer>> command_buffers_;
};

Expand Down Expand Up @@ -147,7 +167,7 @@ VkResult vkCreatePipelineCache(VkDevice device,
const VkAllocationCallbacks* pAllocator,
VkPipelineCache* pPipelineCache) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkCreatePipelineCache");
mock_device->was_called("vkCreatePipelineCache");
*pPipelineCache = reinterpret_cast<VkPipelineCache>(0xb000dead);
return VK_SUCCESS;
}
Expand Down Expand Up @@ -270,30 +290,30 @@ VkResult vkCreateGraphicsPipelines(
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkCreateGraphicsPipelines");
mock_device->was_called("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->called_functions_->push_back("vkDestroyDevice");
mock_device->was_called("vkDestroyDevice");
delete reinterpret_cast<MockDevice*>(device);
}

void vkDestroyPipeline(VkDevice device,
VkPipeline pipeline,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkDestroyPipeline");
mock_device->was_called("vkDestroyPipeline");
}

VkResult vkCreateShaderModule(VkDevice device,
const VkShaderModuleCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkShaderModule* pShaderModule) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkCreateShaderModule");
mock_device->was_called("vkCreateShaderModule");
*pShaderModule = reinterpret_cast<VkShaderModule>(0x11111111);
return VK_SUCCESS;
}
Expand All @@ -302,14 +322,14 @@ void vkDestroyShaderModule(VkDevice device,
VkShaderModule shaderModule,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkDestroyShaderModule");
mock_device->was_called("vkDestroyShaderModule");
}

void vkDestroyPipelineCache(VkDevice device,
VkPipelineCache pipelineCache,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkDestroyPipelineCache");
mock_device->was_called("vkDestroyPipelineCache");
}

void vkCmdBindPipeline(VkCommandBuffer commandBuffer,
Expand Down Expand Up @@ -351,14 +371,14 @@ void vkFreeCommandBuffers(VkDevice device,
uint32_t commandBufferCount,
const VkCommandBuffer* pCommandBuffers) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkFreeCommandBuffers");
mock_device->was_called("vkFreeCommandBuffers");
}

void vkDestroyCommandPool(VkDevice device,
VkCommandPool commandPool,
const VkAllocationCallbacks* pAllocator) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
mock_device->called_functions_->push_back("vkDestroyCommandPool");
mock_device->was_called("vkDestroyCommandPool");
}

VkResult vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
Expand Down Expand Up @@ -500,7 +520,7 @@ std::shared_ptr<ContextVK> CreateMockVulkanContext(void) {
std::shared_ptr<std::vector<std::string>> GetMockVulkanFunctions(
VkDevice device) {
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
return mock_device->called_functions_;
return mock_device->GetCalledFunctions();
}

} // namespace testing
Expand Down
37 changes: 37 additions & 0 deletions impeller/renderer/backend/vulkan/test/mock_vulkan_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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 "flutter/testing/testing.h" // IWYU pragma: keep
#include "gtest/gtest.h"
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"

namespace impeller {
namespace testing {

TEST(MockVulkanContextTest, IsThreadSafe) {
// In a typical app, there is a single ContextVK per app, shared b/w threads.
//
// This test ensures that the (mock) ContextVK is thread-safe.
auto const context = CreateMockVulkanContext();

// Spawn two threads, and have them create a CommandPoolVK each.
std::thread thread1([&context]() {
auto const pool = CommandPoolVK::GetThreadLocal(context.get());
EXPECT_TRUE(pool);
});

std::thread thread2([&context]() {
auto const pool = CommandPoolVK::GetThreadLocal(context.get());
EXPECT_TRUE(pool);
});

thread1.join();
thread2.join();

context->Shutdown();
}

} // namespace testing
} // namespace impeller