| // copyright (c) 2022 the android open source project |
| // |
| // licensed under the apache license, version 2.0 (the "license"); |
| // you may not use this file except in compliance with the license. |
| // you may obtain a copy of the license at |
| // |
| // http://www.apache.org/licenses/license-2.0 |
| // |
| // unless required by applicable law or agreed to in writing, software |
| // distributed under the license is distributed on an "as is" basis, |
| // without warranties or conditions of any kind, either express or implied. |
| // see the license for the specific language governing permissions and |
| // limitations under the license. |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "VkDecoderGlobalState.cpp" |
| |
| #include "aemu/base/testing/TestUtils.h" |
| |
| namespace gfxstream { |
| namespace vk { |
| namespace { |
| using ::testing::_; |
| using ::testing::InSequence; |
| using ::testing::MockFunction; |
| using ::testing::Return; |
| using ::testing::Test; |
| using ::testing::UnorderedElementsAre; |
| |
| class VkDecoderGlobalStateExternalFenceTest : public Test { |
| protected: |
| class MockDispatch { |
| public: |
| MOCK_METHOD(VkResult, vkGetFenceStatus, (VkDevice device, VkFence fence), ()); |
| MOCK_METHOD(VkResult, |
| vkResetFences, |
| (VkDevice device, uint32_t numFences, const VkFence* fence), |
| ()); |
| }; |
| |
| VkDecoderGlobalStateExternalFenceTest() |
| : mDevice(reinterpret_cast<VkDevice>(0x2222'0000)), mPool(&mMockDispatch, mDevice) {} |
| |
| ~VkDecoderGlobalStateExternalFenceTest() { |
| mPool.popAll(); |
| } |
| |
| MockDispatch mMockDispatch; |
| VkDevice mDevice; |
| ExternalFencePool<MockDispatch> mPool; |
| }; |
| |
| using VkDecoderGlobalStateExternalFenceDeathTest = VkDecoderGlobalStateExternalFenceTest; |
| |
| TEST_F(VkDecoderGlobalStateExternalFenceTest, poolNoDeviceFences) { |
| VkFenceCreateInfo createInfo{ |
| .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
| .pNext = 0, |
| .flags = 0, |
| }; |
| ASSERT_EQ(VK_NULL_HANDLE, mPool.pop(&createInfo)); |
| } |
| |
| TEST_F(VkDecoderGlobalStateExternalFenceTest, poolReuseSignalledFence) { |
| { |
| InSequence s; |
| EXPECT_CALL(mMockDispatch, vkGetFenceStatus(_, _)).WillOnce(Return(VK_SUCCESS)); |
| EXPECT_CALL(mMockDispatch, vkResetFences(_, _, _)).WillOnce(Return(VK_SUCCESS)); |
| } |
| |
| VkFence fence = reinterpret_cast<VkFence>(0x1234'0000); |
| VkFenceCreateInfo createInfo{ |
| .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
| .pNext = 0, |
| .flags = 0, |
| }; |
| mPool.add(fence); |
| VkFence reusedFence = mPool.pop(&createInfo); |
| |
| ASSERT_EQ(fence, reusedFence); |
| } |
| |
| TEST_F(VkDecoderGlobalStateExternalFenceTest, poolReuseSignalledFenceAsSignaled) { |
| { |
| InSequence s; |
| EXPECT_CALL(mMockDispatch, vkGetFenceStatus(_, _)).WillOnce(Return(VK_SUCCESS)); |
| EXPECT_CALL(mMockDispatch, vkResetFences(_, _, _)).Times(0); |
| } |
| |
| VkFence fence = reinterpret_cast<VkFence>(0x1234'0000); |
| VkFenceCreateInfo createInfo{ |
| .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
| .pNext = 0, |
| .flags = VK_FENCE_CREATE_SIGNALED_BIT, |
| }; |
| mPool.add(fence); |
| VkFence reusedFence = mPool.pop(&createInfo); |
| |
| ASSERT_EQ(fence, reusedFence); |
| } |
| |
| TEST_F(VkDecoderGlobalStateExternalFenceTest, poolUnsignalledFence) { |
| { |
| InSequence s; |
| EXPECT_CALL(mMockDispatch, vkGetFenceStatus(_, _)).WillOnce(Return(VK_NOT_READY)); |
| EXPECT_CALL(mMockDispatch, vkResetFences(_, _, _)).Times(0); |
| } |
| |
| VkFence fence = reinterpret_cast<VkFence>(0x1234'0000); |
| VkFenceCreateInfo createInfo{ |
| .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, |
| .pNext = 0, |
| .flags = 0, |
| }; |
| mPool.add(fence); |
| |
| ASSERT_EQ(VK_NULL_HANDLE, mPool.pop(&createInfo)); |
| } |
| |
| TEST_F(VkDecoderGlobalStateExternalFenceTest, poolPopAll) { |
| VkFence fence1 = reinterpret_cast<VkFence>(0x1234'0000); |
| VkFence fence2 = reinterpret_cast<VkFence>(0x2234'0000); |
| VkFence fence3 = reinterpret_cast<VkFence>(0x3234'0000); |
| mPool.add(fence1); |
| mPool.add(fence2); |
| mPool.add(fence3); |
| |
| std::vector<VkFence> result = mPool.popAll(); |
| ASSERT_THAT(result, UnorderedElementsAre(fence1, fence2, fence3)); |
| } |
| |
| TEST_F(VkDecoderGlobalStateExternalFenceDeathTest, undestroyedFences) { |
| ASSERT_DEATH( |
| { |
| ExternalFencePool<MockDispatch> pool(&mMockDispatch, mDevice); |
| VkFence fence = reinterpret_cast<VkFence>(0x1234'0000); |
| pool.add(fence); |
| }, |
| MatchesStdRegex( |
| "External fence pool for device 0000000022220000|0x22220000 destroyed but 1 " |
| "fences still not destroyed.")); |
| } |
| |
| } // namespace |
| } // namespace vk |
| } // namespace gfxstream |