Skip to content
This repository has been archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Add MockFence to mock_vulkan. #45862

Closed
10 changes: 8 additions & 2 deletions impeller/renderer/backend/vulkan/test/mock_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
#include <cstring>
#include <utility>
#include <vector>
#include "fml/macros.h"
#include "fml/thread_local.h"
#include "impeller/base/thread_safety.h"
#include "vulkan/vulkan_core.h"
#include "vulkan/vulkan_enums.hpp"

namespace impeller {
namespace testing {
Expand Down Expand Up @@ -410,7 +413,8 @@ VkResult vkCreateFence(VkDevice device,
const VkFenceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence) {
*pFence = reinterpret_cast<VkFence>(0xfe0ce);
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mock_device appears unused.

*pFence = reinterpret_cast<VkFence>(new MockFence());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add an override to vkDestroyFence too so you aren't leaking these.

return VK_SUCCESS;
}

Expand All @@ -430,7 +434,9 @@ VkResult vkWaitForFences(VkDevice device,
}

VkResult vkGetFenceStatus(VkDevice device, VkFence fence) {
return VK_SUCCESS;
MockDevice* mock_device = reinterpret_cast<MockDevice*>(device);
MockFence* mock_fence = reinterpret_cast<MockFence*>(fence);
return mock_fence->GetStatus();
}

VkResult vkCreateDebugUtilsMessengerEXT(
Expand Down
24 changes: 24 additions & 0 deletions impeller/renderer/backend/vulkan/test/mock_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,41 @@
#pragma once

#include <functional>
#include <memory>
#include <string>
#include <vector>

#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "vulkan/vulkan_enums.hpp"

namespace impeller {
namespace testing {

std::shared_ptr<std::vector<std::string>> GetMockVulkanFunctions(
VkDevice device);

// A test-controlled version of |vk::Fence|.
class MockFence final {
public:
MockFence() = default;

// Returns the result that was set in the constructor or |SetStatus|.
VkResult GetStatus() { return static_cast<VkResult>(result_); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think vk::Status has cast operators to make this conversion implicit


// Sets the result that will be returned by `GetFenceStatus`.
static void SetStatus(vk::UniqueFence& fence, vk::Result result) {
// Cast the fence to a MockFence and set the result.
VkFence raw_fence = fence.get();
MockFence* mock_fence = reinterpret_cast<MockFence*>(raw_fence);
mock_fence->result_ = result;
}

private:
vk::Result result_ = vk::Result::eSuccess;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should make this atomic since potentially people are reading and writing from this at the same time.


FML_DISALLOW_COPY_AND_ASSIGN(MockFence);
};

class MockVulkanContextBuilder {
public:
MockVulkanContextBuilder();
Expand Down
22 changes: 22 additions & 0 deletions impeller/renderer/backend/vulkan/test/mock_vulkan_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "gtest/gtest.h"
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
#include "vulkan/vulkan_enums.hpp"

namespace impeller {
namespace testing {
Expand Down Expand Up @@ -33,5 +34,26 @@ TEST(MockVulkanContextTest, IsThreadSafe) {
context->Shutdown();
}

TEST(MockVulkanContextTest, DefaultFenceAlwaysReportsSuccess) {
auto const context = MockVulkanContextBuilder().Build();
auto const device = context->GetDevice();

auto fence = device.createFenceUnique({}).value;
EXPECT_EQ(vk::Result::eSuccess, device.getFenceStatus(*fence));
}

TEST(MockVulkanContextTest, MockedFenceReportsStatus) {
auto const context = MockVulkanContextBuilder().Build();

auto const device = context->GetDevice();
auto fence = device.createFenceUnique({}).value;
MockFence::SetStatus(fence, vk::Result::eNotReady);

EXPECT_EQ(vk::Result::eNotReady, device.getFenceStatus(fence.get()));

MockFence::SetStatus(fence, vk::Result::eSuccess);
EXPECT_EQ(vk::Result::eSuccess, device.getFenceStatus(*fence));
}

} // namespace testing
} // namespace impeller