gl_fence_win.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // Copyright 2020 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 "ui/gl/gl_fence_win.h"
  5. #include "base/logging.h"
  6. #include "base/notreached.h"
  7. #include "ui/gl/gl_angle_util_win.h"
  8. #include <d3d11_4.h>
  9. namespace gl {
  10. bool GLFenceWin::IsSupported() {
  11. Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
  12. gl::QueryD3D11DeviceObjectFromANGLE();
  13. if (!d3d11_device)
  14. return false;
  15. // Support for ID3D11Device5 implies support for ID3D11DeviceContext4.
  16. // No point in letting you create fences if you can't signal or wait on them.
  17. Microsoft::WRL::ComPtr<ID3D11Device5> d3d11_device5;
  18. HRESULT hr = d3d11_device.As(&d3d11_device5);
  19. if (FAILED(hr)) {
  20. return false;
  21. }
  22. return true;
  23. }
  24. std::unique_ptr<GLFenceWin> GLFenceWin::CreateForGpuFence() {
  25. Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
  26. gl::QueryD3D11DeviceObjectFromANGLE();
  27. if (!d3d11_device) {
  28. DLOG(ERROR) << "Unable to retrieve ID3D11Device from ANGLE";
  29. return nullptr;
  30. }
  31. return CreateForGpuFence(d3d11_device.Get());
  32. }
  33. std::unique_ptr<GLFenceWin> GLFenceWin::CreateForGpuFence(
  34. ID3D11Device* d3d11_device) {
  35. Microsoft::WRL::ComPtr<ID3D11Device5> d3d11_device5;
  36. HRESULT hr = d3d11_device->QueryInterface(IID_PPV_ARGS(&d3d11_device5));
  37. if (FAILED(hr)) {
  38. DLOG(ERROR) << "Unable to retrieve ID3D11Device5 interface "
  39. << logging::SystemErrorCodeToString(hr);
  40. return nullptr;
  41. }
  42. Microsoft::WRL::ComPtr<ID3D11Fence> d3d11_fence;
  43. hr = d3d11_device5->CreateFence(0, D3D11_FENCE_FLAG_SHARED,
  44. IID_PPV_ARGS(&d3d11_fence));
  45. if (FAILED(hr)) {
  46. DLOG(ERROR) << "Unable to create ID3D11Fence "
  47. << logging::SystemErrorCodeToString(hr);
  48. return nullptr;
  49. }
  50. HANDLE shared_handle;
  51. hr = d3d11_fence->CreateSharedHandle(
  52. nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr,
  53. &shared_handle);
  54. if (FAILED(hr)) {
  55. DLOG(ERROR) << "Unable to create shared handle for DXGIResource "
  56. << logging::SystemErrorCodeToString(hr);
  57. return nullptr;
  58. }
  59. // Put the shared handle into an RAII object as quickly as possible to
  60. // ensure we do not leak it.
  61. base::win::ScopedHandle scoped_handle(shared_handle);
  62. Microsoft::WRL::ComPtr<ID3D11DeviceContext> d3d11_device_context;
  63. d3d11_device5->GetImmediateContext(&d3d11_device_context);
  64. Microsoft::WRL::ComPtr<ID3D11DeviceContext4> d3d11_device_context4;
  65. hr = d3d11_device_context.As(&d3d11_device_context4);
  66. if (FAILED(hr)) {
  67. DLOG(ERROR) << "Unable to retrieve ID3D11DeviceContext4 interface "
  68. << logging::SystemErrorCodeToString(hr);
  69. return nullptr;
  70. }
  71. hr = d3d11_device_context4->Signal(d3d11_fence.Get(), 1);
  72. if (FAILED(hr)) {
  73. DLOG(ERROR) << "Unable to Signal D3D11 fence "
  74. << logging::SystemErrorCodeToString(hr);
  75. return nullptr;
  76. }
  77. gfx::GpuFenceHandle gpu_fence_handle;
  78. gpu_fence_handle.owned_handle = std::move(scoped_handle);
  79. return std::make_unique<GLFenceWin>(std::move(d3d11_fence),
  80. std::move(gpu_fence_handle));
  81. }
  82. std::unique_ptr<GLFenceWin> GLFenceWin::CreateFromGpuFence(
  83. const gfx::GpuFence& gpu_fence) {
  84. Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
  85. gl::QueryD3D11DeviceObjectFromANGLE();
  86. return CreateFromGpuFence(d3d11_device.Get(), gpu_fence);
  87. }
  88. std::unique_ptr<GLFenceWin> GLFenceWin::CreateFromGpuFence(
  89. ID3D11Device* d3d11_device,
  90. const gfx::GpuFence& gpu_fence) {
  91. Microsoft::WRL::ComPtr<ID3D11Device5> d3d11_device5;
  92. HRESULT hr = d3d11_device->QueryInterface(IID_PPV_ARGS(&d3d11_device5));
  93. if (FAILED(hr)) {
  94. DLOG(ERROR) << "Unable to retrieve ID3D11Device5 interface "
  95. << logging::SystemErrorCodeToString(hr);
  96. return nullptr;
  97. }
  98. gfx::GpuFenceHandle gpu_fence_handle = gpu_fence.GetGpuFenceHandle().Clone();
  99. Microsoft::WRL::ComPtr<ID3D11Fence> d3d11_fence;
  100. hr = d3d11_device5->OpenSharedFence(gpu_fence_handle.owned_handle.Get(),
  101. IID_PPV_ARGS(&d3d11_fence));
  102. if (FAILED(hr)) {
  103. DLOG(ERROR) << "Unable to open a shared fence "
  104. << logging::SystemErrorCodeToString(hr);
  105. return nullptr;
  106. }
  107. return std::make_unique<GLFenceWin>(std::move(d3d11_fence),
  108. std::move(gpu_fence_handle));
  109. }
  110. GLFenceWin::GLFenceWin(Microsoft::WRL::ComPtr<ID3D11Fence> d3d11_fence,
  111. gfx::GpuFenceHandle gpu_fence_handle)
  112. : d3d11_fence_(std::move(d3d11_fence)),
  113. gpu_fence_handle_(std::move(gpu_fence_handle)) {}
  114. GLFenceWin::~GLFenceWin() = default;
  115. bool GLFenceWin::HasCompleted() {
  116. NOTREACHED();
  117. return false;
  118. }
  119. void GLFenceWin::ClientWait() {
  120. NOTREACHED();
  121. }
  122. void GLFenceWin::ServerWait() {
  123. Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device;
  124. d3d11_fence_->GetDevice(&d3d11_device);
  125. Microsoft::WRL::ComPtr<ID3D11DeviceContext> d3d11_device_context;
  126. d3d11_device->GetImmediateContext(&d3d11_device_context);
  127. Microsoft::WRL::ComPtr<ID3D11DeviceContext4> d3d11_device_context4;
  128. HRESULT hr = d3d11_device_context.As(&d3d11_device_context4);
  129. if (FAILED(hr)) {
  130. DLOG(ERROR) << "Unable to retrieve ID3D11DeviceContext4 interface "
  131. << logging::SystemErrorCodeToString(hr);
  132. return;
  133. }
  134. hr = d3d11_device_context4->Wait(d3d11_fence_.Get(), 1);
  135. if (FAILED(hr)) {
  136. DLOG(ERROR) << "Unable to Wait on D3D11 fence "
  137. << logging::SystemErrorCodeToString(hr);
  138. return;
  139. }
  140. }
  141. std::unique_ptr<gfx::GpuFence> GLFenceWin::GetGpuFence() {
  142. return std::make_unique<gfx::GpuFence>(gpu_fence_handle_.Clone());
  143. }
  144. } // namespace gl