diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc --- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc @@ -1008,7 +1008,7 @@ std::unique_ptr D3DImageBacking::ProduceVideo( device, src_texture); } -std::vector> +std::optional>> D3DImageBacking::GetPendingWaitFences( const Microsoft::WRL::ComPtr& wait_d3d11_device, const wgpu::Device& wait_dawn_device, @@ -1018,7 +1018,7 @@ D3DImageBacking::GetPendingWaitFences( // (i.e. scanout cases) means we always need to check for the presence of the // availability fence. if (!use_cross_device_fence_synchronization() && !dcomp_texture_) { - return {}; + return std::vector>{}; } // Lazily create and signal the D3D11 fence on the texture's original device @@ -1029,18 +1029,22 @@ D3DImageBacking::GetPendingWaitFences( gfx::D3DSharedFence::CreateForD3D11(texture_d3d11_device_); if (!texture_device_fence) { LOG(ERROR) << "Failed to retrieve D3D11 signal fence"; - return {}; + return std::nullopt; } // Make D3D11 device wait for |write_fences_| since we'll replace it below. for (auto& fence : write_fences_) { if (!fence->WaitD3D11(texture_d3d11_device_)) { LOG(ERROR) << "Failed to wait for write fence"; - return {}; + // Roll back the partial mutation of d3d11_signaled_fence_map_ so + // a future BeginAccess can retry the lazy-init path instead of + // skipping it forever. + texture_device_fence = nullptr; + return std::nullopt; } } if (!texture_device_fence->IncrementAndSignalD3D11()) { LOG(ERROR) << "Failed to signal D3D11 signal fence"; - return {}; + texture_device_fence = nullptr; + return std::nullopt; } // Store it in |write_fences_| so it's waited on for all subsequent access. write_fences_.clear(); @@ -1150,10 +1154,14 @@ wgpu::Texture D3DImageBacking::BeginAccessDawn( backend_type == wgpu::BackendType::D3D11 ? texture_d3d11_device_ : nullptr; - std::vector> wait_fences = + auto wait_fences_or = GetPendingWaitFences(dawn_d3d11_device, device, write_access); + if (!wait_fences_or.has_value()) { + LOG(ERROR) << "GetPendingWaitFences failed; refusing Dawn access"; + return nullptr; + } std::vector shared_fences; std::vector signaled_values; - for (auto& wait_fence : wait_fences) { + for (auto& wait_fence : *wait_fences_or) { wgpu::SharedFenceDXGISharedHandleDescriptor dxgi_desc; dxgi_desc.handle = wait_fence->GetSharedHandle(); wgpu::SharedFenceDescriptor fence_desc; @@ -1394,9 +1402,13 @@ bool D3DImageBacking::BeginAccessD3D11( } // Defer clearing fences until later to handle D3D11 failure to synchronize. - std::vector> wait_fences = + auto wait_fences_or = GetPendingWaitFences(d3d11_device, /*dawn_device=*/nullptr, write_access); - for (auto& wait_fence : wait_fences) { + if (!wait_fences_or.has_value()) { + LOG(ERROR) << "GetPendingWaitFences failed; refusing D3D11 access"; + return false; + } + for (auto& wait_fence : *wait_fences_or) { if (!wait_fence->WaitD3D11(d3d11_device)) { LOG(ERROR) << "Failed to wait for fence"; return false; diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.h b/gpu/command_buffer/service/shared_image/d3d_image_backing.h --- a/gpu/command_buffer/service/shared_image/d3d_image_backing.h +++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -290,7 +291,10 @@ class GPU_GLES2_EXPORT D3DImageBacking final : public ClearTrackingSharedImage bool ValidateBeginAccess(bool write_access) GUARDED_BY_CONTEXT(lock_); void BeginAccessCommon(bool write_access) GUARDED_BY_CONTEXT(lock_); void EndAccessCommon(const D3DSharedFenceSet& signaled_fences) GUARDED_BY_CONTEXT(lock_); - std::vector> GetPendingWaitFences( + // Returns std::nullopt on internal error (caller MUST fail BeginAccess). + // Returns an empty vector when no synchronization is needed. + std::optional>> + GetPendingWaitFences( const Microsoft::WRL::ComPtr& wait_d3d11_device, const wgpu::Device& wait_dawn_device, bool write_access) GUARDED_BY_CONTEXT(lock_);