vulkan_fence_helper_unittest.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // Copyright 2019 The Chromium 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. #include "testing/gtest/include/gtest/gtest.h"
  5. #include "base/bind.h"
  6. #include "gpu/vulkan/tests/basic_vulkan_test.h"
  7. #include "gpu/vulkan/vulkan_device_queue.h"
  8. #include "gpu/vulkan/vulkan_fence_helper.h"
  9. #include "gpu/vulkan/vulkan_function_pointers.h"
  10. #include "gpu/vulkan/vulkan_util.h"
  11. namespace gpu {
  12. using VulkanFenceHelperTest = BasicVulkanTest;
  13. TEST_F(VulkanFenceHelperTest, BasicFenceUsage) {
  14. VulkanFenceHelper* fence_helper = GetDeviceQueue()->GetFenceHelper();
  15. VkFence fence = VK_NULL_HANDLE;
  16. ASSERT_TRUE(VK_SUCCESS == fence_helper->GetFence(&fence));
  17. ASSERT_TRUE(fence != VK_NULL_HANDLE);
  18. ASSERT_TRUE(VK_SUCCESS == vkQueueSubmit(GetDeviceQueue()->GetVulkanQueue(), 0,
  19. nullptr, fence));
  20. VulkanFenceHelper::FenceHandle fence_handle =
  21. fence_helper->EnqueueFence(fence);
  22. EXPECT_TRUE(fence_helper->Wait(fence_handle, UINT64_MAX));
  23. EXPECT_TRUE(fence_helper->HasPassed(fence_handle));
  24. }
  25. TEST_F(VulkanFenceHelperTest, TestBasicCallback) {
  26. VulkanFenceHelper* fence_helper = GetDeviceQueue()->GetFenceHelper();
  27. bool cleanup_run = false;
  28. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  29. base::BindOnce([](bool* cleanup_run, VulkanDeviceQueue* device_queue,
  30. bool is_lost) { *cleanup_run = true; },
  31. &cleanup_run));
  32. VulkanFenceHelper::FenceHandle fence_handle =
  33. fence_helper->GenerateCleanupFence();
  34. EXPECT_TRUE(fence_handle.is_valid());
  35. fence_helper->Wait(fence_handle, UINT64_MAX);
  36. EXPECT_TRUE(cleanup_run);
  37. }
  38. TEST_F(VulkanFenceHelperTest, TestBasicCallbackExternalSubmission) {
  39. VulkanFenceHelper* fence_helper = GetDeviceQueue()->GetFenceHelper();
  40. bool cleanup_run = false;
  41. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  42. base::BindOnce([](bool* cleanup_run, VulkanDeviceQueue* device_queue,
  43. bool is_lost) { *cleanup_run = true; },
  44. &cleanup_run));
  45. VkFence fence = VK_NULL_HANDLE;
  46. ASSERT_TRUE(VK_SUCCESS == fence_helper->GetFence(&fence));
  47. ASSERT_TRUE(fence != VK_NULL_HANDLE);
  48. ASSERT_TRUE(VK_SUCCESS == vkQueueSubmit(GetDeviceQueue()->GetVulkanQueue(), 0,
  49. nullptr, fence));
  50. VulkanFenceHelper::FenceHandle fence_handle =
  51. fence_helper->EnqueueFence(fence);
  52. EXPECT_TRUE(fence_handle.is_valid());
  53. fence_helper->Wait(fence_handle, UINT64_MAX);
  54. EXPECT_TRUE(cleanup_run);
  55. }
  56. TEST_F(VulkanFenceHelperTest, TestMultipleCallbacks) {
  57. VulkanFenceHelper* fence_helper = GetDeviceQueue()->GetFenceHelper();
  58. uint32_t cleanups_run = 0;
  59. auto increment_cleanups_callback =
  60. [](uint32_t expected_index, uint32_t* cleanups_run,
  61. VulkanDeviceQueue* device_queue, bool is_lost) {
  62. EXPECT_EQ(expected_index, *cleanups_run);
  63. *cleanups_run = *cleanups_run + 1;
  64. };
  65. // Enqueue 5 callbacks.
  66. for (int i = 0; i < 5; i++) {
  67. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  68. base::BindOnce(increment_cleanups_callback, i, &cleanups_run));
  69. }
  70. // Generate a cleanup fence for the first 5 callbacks.
  71. VulkanFenceHelper::FenceHandle fence_handle =
  72. fence_helper->GenerateCleanupFence();
  73. // Enqueue 5 more callbacks.
  74. for (int i = 5; i < 10; i++) {
  75. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  76. base::BindOnce(increment_cleanups_callback, i, &cleanups_run));
  77. }
  78. // Generate a cleanup fence for the next 5 callbacks.
  79. fence_handle = fence_helper->GenerateCleanupFence();
  80. EXPECT_TRUE(fence_handle.is_valid());
  81. fence_helper->Wait(fence_handle, UINT64_MAX);
  82. EXPECT_EQ(10u, cleanups_run);
  83. }
  84. TEST_F(VulkanFenceHelperTest, TestSkiaCallback) {
  85. VulkanFenceHelper* fence_helper = GetDeviceQueue()->GetFenceHelper();
  86. bool cleanup_run = false;
  87. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  88. base::BindOnce([](bool* cleanup_run, VulkanDeviceQueue* device_queue,
  89. bool is_lost) { *cleanup_run = true; },
  90. &cleanup_run));
  91. auto cleanup_closure = fence_helper->CreateExternalCallback();
  92. EXPECT_FALSE(cleanup_run);
  93. std::move(cleanup_closure).Run();
  94. EXPECT_TRUE(cleanup_run);
  95. }
  96. TEST_F(VulkanFenceHelperTest, SkiaCallbackBeforeFences) {
  97. VulkanFenceHelper* fence_helper = GetDeviceQueue()->GetFenceHelper();
  98. uint32_t cleanups_run = 0;
  99. auto increment_cleanups_callback =
  100. [](uint32_t expected_index, uint32_t* cleanups_run,
  101. VulkanDeviceQueue* device_queue, bool is_lost) {
  102. EXPECT_EQ(expected_index, *cleanups_run);
  103. *cleanups_run = *cleanups_run + 1;
  104. };
  105. // Enqueue 5 callbacks.
  106. for (int i = 0; i < 5; i++) {
  107. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  108. base::BindOnce(increment_cleanups_callback, i, &cleanups_run));
  109. }
  110. // The first 5 callbacks use a callback to trigger.
  111. auto cleanup_closure = fence_helper->CreateExternalCallback();
  112. // Enqueue 5 more callbacks.
  113. for (int i = 5; i < 10; i++) {
  114. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  115. base::BindOnce(increment_cleanups_callback, i, &cleanups_run));
  116. }
  117. // Generate a cleanup fence for the next 5 callbacks.
  118. VulkanFenceHelper::FenceHandle fence_handle =
  119. fence_helper->GenerateCleanupFence();
  120. EXPECT_TRUE(fence_handle.is_valid());
  121. // After waiting for the second fence, all callbacks should have run, Skia
  122. // callbacks can be delayed, so we check future fences as well.
  123. EXPECT_TRUE(fence_helper->Wait(fence_handle, UINT64_MAX));
  124. EXPECT_EQ(10u, cleanups_run);
  125. // Running the callback now should be a no-op.
  126. std::move(cleanup_closure).Run();
  127. EXPECT_EQ(10u, cleanups_run);
  128. }
  129. TEST_F(VulkanFenceHelperTest, SkiaCallbackAfterFences) {
  130. VulkanFenceHelper* fence_helper = GetDeviceQueue()->GetFenceHelper();
  131. uint32_t cleanups_run = 0;
  132. auto increment_cleanups_callback =
  133. [](uint32_t expected_index, uint32_t* cleanups_run,
  134. VulkanDeviceQueue* device_queue, bool is_lost) {
  135. EXPECT_EQ(expected_index, *cleanups_run);
  136. *cleanups_run = *cleanups_run + 1;
  137. };
  138. // Enqueue 5 callbacks.
  139. for (int i = 0; i < 5; i++) {
  140. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  141. base::BindOnce(increment_cleanups_callback, i, &cleanups_run));
  142. }
  143. // The first 5 callbacks use a fence to trigger.
  144. VulkanFenceHelper::FenceHandle fence_handle =
  145. fence_helper->GenerateCleanupFence();
  146. EXPECT_TRUE(fence_handle.is_valid());
  147. // Call vkQueueWaitIdle() to make sure the |fence_handle| is passed.
  148. vkQueueWaitIdle(queue());
  149. // Enqueue 5 more callbacks.
  150. for (int i = 5; i < 10; i++) {
  151. fence_helper->EnqueueCleanupTaskForSubmittedWork(
  152. base::BindOnce(increment_cleanups_callback, i, &cleanups_run));
  153. }
  154. // The next 5 callbacks use a callback to trigger.
  155. auto cleanup_closure = fence_helper->CreateExternalCallback();
  156. // Call the cleanup closure, all callbacks should run.
  157. // Generate a cleanup fence for the next 5 callbacks.
  158. std::move(cleanup_closure).Run();
  159. EXPECT_EQ(10u, cleanups_run);
  160. }
  161. } // namespace gpu