Remove auto lock from CreateTexture/Sampler API calls Add "no autolock" to Device::CreateTexture in dawn.json to prevent automatic locking at the API boundary. Introduce virtual method UseGuardForCreateTexture() that returns std::optional<DeviceGuard>. The default implementation returns a guard, but D3D11 overrides to return nullopt since its CreateTextureImpl is already thread-safe. Lock acquisition must happen at the API level, not within Impl methods, to avoid potential lock inversion issues when Impl methods are called by other internal functions. This CL also does similar things for Device::CreateSampler. Bug: 474265307 Bug: 475520968 Change-Id: I1f3df3e525c447abceeea9ec56e59791e071835f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/284276 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json index 2a5c3e0..33f4810 100644 --- a/src/dawn/dawn.json +++ b/src/dawn/dawn.json
@@ -1360,6 +1360,7 @@ }, { "name": "create sampler", + "no autolock": true, "returns": "sampler", "args": [ {"name": "descriptor", "type": "sampler descriptor", "annotation": "const*", "optional": true} @@ -1384,6 +1385,7 @@ }, { "name": "create texture", + "no autolock": true, "returns": "texture", "args": [ {"name": "descriptor", "type": "texture descriptor", "annotation": "const*"}
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp index 7087ca9..05e6838 100644 --- a/src/dawn/native/Device.cpp +++ b/src/dawn/native/Device.cpp
@@ -1459,6 +1459,7 @@ return ReturnToAPI(std::move(result)); } SamplerBase* DeviceBase::APICreateSampler(const SamplerDescriptor* descriptor) { + auto deviceGuard = UseGuardForCreateSampler(); Ref<SamplerBase> result; if (ConsumedError(CreateSampler(descriptor), &result, "calling %s.CreateSampler(%s).", this, descriptor)) { @@ -1592,6 +1593,7 @@ return ReturnToAPI(std::move(result)); } TextureBase* DeviceBase::APICreateTexture(const TextureDescriptor* descriptor) { + auto deviceGuard = UseGuardForCreateTexture(); Ref<TextureBase> result; if (ConsumedError(CreateTexture(descriptor), &result, InternalErrorType::OutOfMemory, "calling %s.CreateTexture(%s).", this, descriptor)) { @@ -2543,6 +2545,18 @@ void DeviceBase::PerformIdleTasksImpl() {} +std::optional<DeviceGuard> DeviceBase::UseGuardForCreateTexture() { + // Backends with thread-safe CreateTextureImpl() can override this to return nullopt. + // TODO(crbug.com/475530346): Even with a thread-safe CreateTextureImpl(), there's still a + // potential race between Device::Destroy() and APICreateTexture() without the device lock. We + // assume callers are responsible for synchronizing Destroy() calls with texture creation. + return GetGuard(); +} + +std::optional<DeviceGuard> DeviceBase::UseGuardForCreateSampler() { + return GetGuard(); +} + bool DeviceBase::ShouldDuplicateNumWorkgroupsForDispatchIndirect( ComputePipelineBase* computePipeline) const { return false;
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h index c3e8b72..1f099f4 100644 --- a/src/dawn/native/Device.h +++ b/src/dawn/native/Device.h
@@ -32,6 +32,7 @@ #include <atomic> #include <memory> +#include <optional> #include <string> #include <utility> #include <vector> @@ -559,6 +560,11 @@ virtual bool ReduceMemoryUsageImpl(); virtual void PerformIdleTasksImpl(); + // TODO(crbug.com/475520968): Remove this once all backends' Create*Impl methods are + // thread-safe + virtual std::optional<DeviceGuard> UseGuardForCreateTexture(); + virtual std::optional<DeviceGuard> UseGuardForCreateSampler(); + virtual MaybeError TickImpl() = 0; void FlushCallbackTaskQueue();
diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp index 6ee0c73..4b9b47e 100644 --- a/src/dawn/native/d3d11/DeviceD3D11.cpp +++ b/src/dawn/native/d3d11/DeviceD3D11.cpp
@@ -525,6 +525,14 @@ return false; } +std::optional<DeviceGuard> Device::UseGuardForCreateTexture() { + return std::nullopt; +} + +std::optional<DeviceGuard> Device::UseGuardForCreateSampler() { + return std::nullopt; +} + bool Device::MayRequireDuplicationOfIndirectParameters() const { return true; }
diff --git a/src/dawn/native/d3d11/DeviceD3D11.h b/src/dawn/native/d3d11/DeviceD3D11.h index 2e48f50..952f521 100644 --- a/src/dawn/native/d3d11/DeviceD3D11.h +++ b/src/dawn/native/d3d11/DeviceD3D11.h
@@ -97,6 +97,9 @@ bool ReduceMemoryUsageImpl() override; + std::optional<DeviceGuard> UseGuardForCreateTexture() override; + std::optional<DeviceGuard> UseGuardForCreateSampler() override; + uint32_t GetUAVSlotCount() const; ResultOrError<TextureViewBase*> GetOrCreateCachedImplicitPixelLocalStorageAttachment(