diff --git a/include/dawn/native/D3D12Backend.h b/include/dawn/native/D3D12Backend.h index f8f22715cc..cb148051df 100644 --- a/include/dawn/native/D3D12Backend.h +++ b/include/dawn/native/D3D12Backend.h @@ -29,8 +29,6 @@ namespace dawn::native::d3d12 { class Device; -DAWN_NATIVE_EXPORT Microsoft::WRL::ComPtr GetD3D12Device(WGPUDevice device); - enum MemorySegment { Local, NonLocal, diff --git a/include/dawn/native/D3DBackend.h b/include/dawn/native/D3DBackend.h index 77e785c8f4..590f8fa226 100644 --- a/include/dawn/native/D3DBackend.h +++ b/include/dawn/native/D3DBackend.h @@ -28,6 +28,8 @@ namespace dawn::native::d3d { class ExternalImageDXGIImpl; +DAWN_NATIVE_EXPORT Microsoft::WRL::ComPtr GetDXGIAdapter(WGPUAdapter adapter); + struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase { AdapterDiscoveryOptions(WGPUBackendType type, Microsoft::WRL::ComPtr adapter); Microsoft::WRL::ComPtr dxgiAdapter; diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn index 486c8fa254..e56d9d9515 100644 --- a/src/dawn/native/BUILD.gn +++ b/src/dawn/native/BUILD.gn @@ -410,6 +410,8 @@ source_set("sources") { "d3d/DeviceD3D.h", "d3d/ExternalImageDXGIImpl.cpp", "d3d/ExternalImageDXGIImpl.h", + "d3d/Fence.cpp", + "d3d/Fence.h", "d3d/Forward.h", "d3d/PhysicalDeviceD3D.cpp", "d3d/PhysicalDeviceD3D.h", @@ -419,6 +421,8 @@ source_set("sources") { "d3d/ShaderUtils.h", "d3d/SwapChainD3D.cpp", "d3d/SwapChainD3D.h", + "d3d/TextureD3D.cpp", + "d3d/TextureD3D.h", "d3d/UtilsD3D.cpp", "d3d/UtilsD3D.h", "d3d/d3d_platform.h", @@ -448,6 +452,8 @@ source_set("sources") { "d3d11/DeviceD3D11.h", "d3d11/DeviceInfoD3D11.cpp", "d3d11/DeviceInfoD3D11.h", + "d3d11/FenceD3D11.cpp", + "d3d11/FenceD3D11.h", "d3d11/Forward.h", "d3d11/PhysicalDeviceD3D11.cpp", "d3d11/PhysicalDeviceD3D11.h", @@ -497,8 +503,6 @@ source_set("sources") { "d3d12/D3D12Info.h", "d3d12/DeviceD3D12.cpp", "d3d12/DeviceD3D12.h", - "d3d12/ExternalImageDXGIImplD3D12.cpp", - "d3d12/ExternalImageDXGIImplD3D12.h", "d3d12/FenceD3D12.cpp", "d3d12/FenceD3D12.h", "d3d12/Forward.h", diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt index 5aeb6089cd..deda9b0591 100644 --- a/src/dawn/native/CMakeLists.txt +++ b/src/dawn/native/CMakeLists.txt @@ -267,6 +267,8 @@ if (DAWN_ENABLE_D3D11 OR DAWN_ENABLE_D3D12) "d3d/DeviceD3D.h" "d3d/ExternalImageDXGIImpl.cpp" "d3d/ExternalImageDXGIImpl.h" + "d3d/Fence.cpp" + "d3d/Fence.h" "d3d/Forward.h" "d3d/PhysicalDeviceD3D.cpp" "d3d/PhysicalDeviceD3D.h" @@ -276,6 +278,8 @@ if (DAWN_ENABLE_D3D11 OR DAWN_ENABLE_D3D12) "d3d/ShaderUtils.h" "d3d/SwapChainD3D.cpp" "d3d/SwapChainD3D.h" + "d3d/TextureD3D.cpp" + "d3d/TextureD3D.h" "d3d/UtilsD3D.cpp" "d3d/UtilsD3D.h" "d3d/d3d_platform.h" @@ -305,6 +309,8 @@ if (DAWN_ENABLE_D3D11) "d3d11/DeviceD3D11.h" "d3d11/DeviceInfoD3D11.cpp" "d3d11/DeviceInfoD3D11.h" + "d3d11/FenceD3D11.cpp" + "d3d11/FenceD3D11.h" "d3d11/Forward.h" "d3d11/PhysicalDeviceD3D11.cpp" "d3d11/PhysicalDeviceD3D11.h" @@ -354,8 +360,6 @@ if (DAWN_ENABLE_D3D12) "d3d12/D3D12Info.h" "d3d12/DeviceD3D12.cpp" "d3d12/DeviceD3D12.h" - "d3d12/ExternalImageDXGIImplD3D12.cpp" - "d3d12/ExternalImageDXGIImplD3D12.h" "d3d12/FenceD3D12.cpp" "d3d12/FenceD3D12.h" "d3d12/Forward.h" diff --git a/src/dawn/native/d3d/D3DBackend.cpp b/src/dawn/native/d3d/D3DBackend.cpp index 0aff6b4881..c03d4e8d1b 100644 --- a/src/dawn/native/d3d/D3DBackend.cpp +++ b/src/dawn/native/d3d/D3DBackend.cpp @@ -21,12 +21,18 @@ #include #include "dawn/common/Log.h" +#include "dawn/native/Adapter.h" #include "dawn/native/d3d/DeviceD3D.h" #include "dawn/native/d3d/ExternalImageDXGIImpl.h" #include "dawn/native/d3d/Forward.h" +#include "dawn/native/d3d/PhysicalDeviceD3D.h" namespace dawn::native::d3d { +Microsoft::WRL::ComPtr GetDXGIAdapter(WGPUAdapter adapter) { + return ToBackend(FromAPI(adapter)->GetPhysicalDevice())->GetHardwareAdapter(); +} + AdapterDiscoveryOptions::AdapterDiscoveryOptions(WGPUBackendType type, Microsoft::WRL::ComPtr adapter) : AdapterDiscoveryOptionsBase(type), dxgiAdapter(std::move(adapter)) {} diff --git a/src/dawn/native/d3d/DeviceD3D.cpp b/src/dawn/native/d3d/DeviceD3D.cpp index df1c6ead89..b92f169000 100644 --- a/src/dawn/native/d3d/DeviceD3D.cpp +++ b/src/dawn/native/d3d/DeviceD3D.cpp @@ -15,6 +15,7 @@ #include "dawn/native/d3d/DeviceD3D.h" #include "dawn/native/d3d/BackendD3D.h" +#include "dawn/native/d3d/ExternalImageDXGIImpl.h" #include "dawn/native/d3d/Forward.h" #include "dawn/native/d3d/PhysicalDeviceD3D.h" @@ -25,7 +26,25 @@ Device::Device(AdapterBase* adapter, const TogglesState& deviceToggles) : DeviceBase(adapter, descriptor, deviceToggles) {} -Device::~Device() = default; +Device::~Device() { + Destroy(); + + // Close the handle here instead of in DestroyImpl. The handle is returned from + // ExternalImageDXGI, so it needs to live as long as the Device ref does, even if the device + // state is destroyed. + if (mFenceHandle != nullptr) { + ::CloseHandle(mFenceHandle); + mFenceHandle = nullptr; + } +} + +void Device::DestroyImpl() { + while (!mExternalImageList.empty()) { + d3d::ExternalImageDXGIImpl* externalImage = mExternalImageList.head()->value(); + // ExternalImageDXGIImpl::DestroyInternal() calls RemoveFromList(). + externalImage->DestroyInternal(); + } +} ResultOrError Device::GetSupportedSurfaceUsageImpl( const Surface* surface) const { @@ -54,4 +73,18 @@ ComPtr Device::GetDxcValidator() const { return ToBackend(GetPhysicalDevice())->GetBackend()->GetDxcValidator(); } +HANDLE Device::GetFenceHandle() const { + return mFenceHandle; +} + +std::unique_ptr Device::CreateExternalImageDXGIImpl( + const ExternalImageDescriptorDXGISharedHandle* descriptor) { + std::unique_ptr externalImage; + if (!ConsumedError(CreateExternalImageDXGIImplImpl(descriptor), &externalImage)) { + mExternalImageList.Append(externalImage.get()); + return externalImage; + } + return {}; +} + } // namespace dawn::native::d3d diff --git a/src/dawn/native/d3d/DeviceD3D.h b/src/dawn/native/d3d/DeviceD3D.h index 13f993f0a3..2b31f52973 100644 --- a/src/dawn/native/d3d/DeviceD3D.h +++ b/src/dawn/native/d3d/DeviceD3D.h @@ -16,6 +16,7 @@ #define SRC_DAWN_NATIVE_D3D_DEVICED3D_H_ #include +#include #include "dawn/native/Device.h" #include "dawn/native/d3d/d3d_platform.h" @@ -23,7 +24,9 @@ namespace dawn::native::d3d { struct ExternalImageDescriptorDXGISharedHandle; +struct ExternalImageDXGIFenceDescriptor; class ExternalImageDXGIImpl; +class Fence; class PlatformFunctions; class Device : public DeviceBase { @@ -46,8 +49,30 @@ class Device : public DeviceBase { ComPtr GetDxcCompiler() const; ComPtr GetDxcValidator() const; - virtual std::unique_ptr CreateExternalImageDXGIImpl( + HANDLE GetFenceHandle() const; + + std::unique_ptr CreateExternalImageDXGIImpl( + const ExternalImageDescriptorDXGISharedHandle* descriptor); + + virtual ResultOrError> CreateFence( + const ExternalImageDXGIFenceDescriptor* descriptor) = 0; + virtual Ref CreateD3DExternalTexture(const TextureDescriptor* descriptor, + ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized) = 0; + + protected: + void DestroyImpl() override; + + virtual ResultOrError> CreateExternalImageDXGIImplImpl( const ExternalImageDescriptorDXGISharedHandle* descriptor) = 0; + + HANDLE mFenceHandle = nullptr; + + private: + // List of external image resources opened using this device. + LinkedList mExternalImageList; }; } // namespace dawn::native::d3d diff --git a/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp b/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp index 29346c53ec..1c7885d9e2 100644 --- a/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp +++ b/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp @@ -20,13 +20,35 @@ #include "dawn/common/Log.h" #include "dawn/native/D3D12Backend.h" #include "dawn/native/DawnNative.h" -#include "dawn/native/d3d12/DeviceD3D12.h" +#include "dawn/native/d3d/DeviceD3D.h" +#include "dawn/native/d3d/Fence.h" +#include "dawn/native/d3d/Forward.h" +#include "dawn/native/d3d/TextureD3D.h" namespace dawn::native::d3d { +MaybeError ValidateTextureDescriptorCanBeWrapped(const TextureDescriptor* descriptor) { + DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D, + "Texture dimension (%s) is not %s.", descriptor->dimension, + wgpu::TextureDimension::e2D); + + DAWN_INVALID_IF(descriptor->mipLevelCount != 1, "Mip level count (%u) is not 1.", + descriptor->mipLevelCount); + + DAWN_INVALID_IF(descriptor->size.depthOrArrayLayers != 1, "Array layer count (%u) is not 1.", + descriptor->size.depthOrArrayLayers); + + DAWN_INVALID_IF(descriptor->sampleCount != 1, "Sample count (%u) is not 1.", + descriptor->sampleCount); + + return {}; +} + ExternalImageDXGIImpl::ExternalImageDXGIImpl(Device* backendDevice, + ComPtr d3dResource, const TextureDescriptor* textureDescriptor) : mBackendDevice(backendDevice), + mD3DResource(std::move(d3dResource)), mUsage(textureDescriptor->usage), mDimension(textureDescriptor->dimension), mSize(textureDescriptor->size), @@ -64,6 +86,10 @@ bool ExternalImageDXGIImpl::IsValid() const { } void ExternalImageDXGIImpl::DestroyInternal() { + if (IsInList()) { + mD3DResource = nullptr; + } + // Linked list is not thread safe. A mutex must already be locked before // endtering this method. Either via Device::DestroyImpl() or ~ExternalImageDXGIImpl. ASSERT(mBackendDevice == nullptr || mBackendDevice->IsLockedByCurrentThreadIfNeeded()); @@ -72,4 +98,82 @@ void ExternalImageDXGIImpl::DestroyInternal() { } } +WGPUTexture ExternalImageDXGIImpl::BeginAccess( + const d3d::ExternalImageDXGIBeginAccessDescriptor* descriptor) { + ASSERT(descriptor != nullptr); + + auto deviceLock(GetScopedDeviceLock()); + + if (!IsInList()) { + dawn::ErrorLog() << "Cannot use external image after device destruction"; + return nullptr; + } + + // Ensure the texture usage is allowed + if (!IsSubset(descriptor->usage, static_cast(mUsage))) { + dawn::ErrorLog() << "Texture usage is not valid for external image"; + return nullptr; + } + + ASSERT(mBackendDevice != nullptr); + + TextureDescriptor textureDescriptor = {}; + textureDescriptor.usage = static_cast(descriptor->usage); + textureDescriptor.dimension = mDimension; + textureDescriptor.size = {mSize.width, mSize.height, mSize.depthOrArrayLayers}; + textureDescriptor.format = mFormat; + textureDescriptor.mipLevelCount = mMipLevelCount; + textureDescriptor.sampleCount = mSampleCount; + textureDescriptor.viewFormats = mViewFormats.data(); + textureDescriptor.viewFormatCount = static_cast(mViewFormats.size()); + + DawnTextureInternalUsageDescriptor internalDesc = {}; + if (mUsageInternal != wgpu::TextureUsage::None) { + textureDescriptor.nextInChain = &internalDesc; + internalDesc.internalUsage = mUsageInternal; + } + + std::vector> waitFences; + for (const d3d::ExternalImageDXGIFenceDescriptor& fenceDescriptor : descriptor->waitFences) { + Ref fence; + if (mBackendDevice->ConsumedError( + ToBackend(mBackendDevice.Get())->CreateFence(&fenceDescriptor), &fence)) { + dawn::ErrorLog() << "Unable to create D3D11 fence for external image"; + return nullptr; + } + waitFences.push_back(std::move(fence)); + } + + Ref texture = + ToBackend(mBackendDevice.Get()) + ->CreateD3DExternalTexture(&textureDescriptor, mD3DResource, std::move(waitFences), + descriptor->isSwapChainTexture, descriptor->isInitialized); + + return ToAPI(texture.Detach()); +} + +void ExternalImageDXGIImpl::EndAccess(WGPUTexture texture, + d3d::ExternalImageDXGIFenceDescriptor* signalFence) { + auto deviceLock(GetScopedDeviceLock()); + + if (!IsInList()) { + dawn::ErrorLog() << "Cannot use external image after device destruction"; + return; + } + + ASSERT(mBackendDevice != nullptr); + ASSERT(signalFence != nullptr); + + Texture* backendTexture = ToBackend(FromAPI(texture)); + ASSERT(backendTexture != nullptr); + + ExecutionSerial fenceValue; + if (mBackendDevice->ConsumedError(backendTexture->EndAccess(), &fenceValue)) { + dawn::ErrorLog() << "D3D11 fence end access failed"; + return; + } + signalFence->fenceHandle = ToBackend(mBackendDevice.Get())->GetFenceHandle(); + signalFence->fenceValue = static_cast(fenceValue); +} + } // namespace dawn::native::d3d diff --git a/src/dawn/native/d3d/ExternalImageDXGIImpl.h b/src/dawn/native/d3d/ExternalImageDXGIImpl.h index ba6ddace58..08a30edfd0 100644 --- a/src/dawn/native/d3d/ExternalImageDXGIImpl.h +++ b/src/dawn/native/d3d/ExternalImageDXGIImpl.h @@ -25,6 +25,7 @@ #include "dawn/native/Error.h" #include "dawn/native/Forward.h" #include "dawn/native/IntegerTypes.h" +#include "dawn/native/d3d/d3d_platform.h" #include "dawn/webgpu_cpp.h" namespace dawn::native::d3d { @@ -34,29 +35,32 @@ struct ExternalImageDXGIBeginAccessDescriptor; struct ExternalImageDXGIFenceDescriptor; struct ExternalImageDescriptorDXGISharedHandle; +MaybeError ValidateTextureDescriptorCanBeWrapped(const TextureDescriptor* descriptor); + class ExternalImageDXGIImpl : public LinkNode { public: - ExternalImageDXGIImpl(Device* backendDevice, const TextureDescriptor* textureDescriptor); - virtual ~ExternalImageDXGIImpl(); + ExternalImageDXGIImpl(Device* backendDevice, + ComPtr d3dResource, + const TextureDescriptor* textureDescriptor); + ~ExternalImageDXGIImpl(); ExternalImageDXGIImpl(const ExternalImageDXGIImpl&) = delete; ExternalImageDXGIImpl& operator=(const ExternalImageDXGIImpl&) = delete; bool IsValid() const; - virtual WGPUTexture BeginAccess(const ExternalImageDXGIBeginAccessDescriptor* descriptor) = 0; - - virtual void EndAccess(WGPUTexture texture, ExternalImageDXGIFenceDescriptor* signalFence) = 0; + WGPUTexture BeginAccess(const ExternalImageDXGIBeginAccessDescriptor* descriptor); + void EndAccess(WGPUTexture texture, ExternalImageDXGIFenceDescriptor* signalFence); // This method should only be called by internal code. Don't call this from D3D12Backend side, // or without locking. - virtual void DestroyInternal(); + void DestroyInternal(); protected: [[nodiscard]] Mutex::AutoLock GetScopedDeviceLock() const; Ref mBackendDevice; - + ComPtr mD3DResource; wgpu::TextureUsage mUsage; wgpu::TextureUsage mUsageInternal = wgpu::TextureUsage::None; wgpu::TextureDimension mDimension; diff --git a/src/dawn/native/d3d/Fence.cpp b/src/dawn/native/d3d/Fence.cpp new file mode 100644 index 0000000000..c20b94469a --- /dev/null +++ b/src/dawn/native/d3d/Fence.cpp @@ -0,0 +1,38 @@ +// Copyright 2023 The Dawn Authors +// +// 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 "dawn/native/d3d/Fence.h" + +#include + +#include "dawn/common/Log.h" +#include "dawn/native/Error.h" +#include "dawn/native/d3d/D3DError.h" + +namespace dawn::native::d3d { + +Fence::Fence(UINT64 fenceValue, HANDLE sharedHandle) + : mFenceValue(fenceValue), mSharedHandle(sharedHandle) {} + +Fence::~Fence() { + if (mSharedHandle != nullptr) { + ::CloseHandle(mSharedHandle); + } +} + +UINT64 Fence::GetFenceValue() const { + return mFenceValue; +} + +} // namespace dawn::native::d3d diff --git a/src/dawn/native/d3d/Fence.h b/src/dawn/native/d3d/Fence.h new file mode 100644 index 0000000000..6d2e7d97c0 --- /dev/null +++ b/src/dawn/native/d3d/Fence.h @@ -0,0 +1,39 @@ +// Copyright 2023 The Dawn Authors +// +// 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. + +#ifndef SRC_DAWN_NATIVE_D3D_FENCED3D_H_ +#define SRC_DAWN_NATIVE_D3D_FENCED3D_H_ + +#include "dawn/common/RefCounted.h" +#include "dawn/native/DawnNative.h" +#include "dawn/native/Error.h" +#include "dawn/native/d3d12/d3d12_platform.h" + +namespace dawn::native::d3d { + +class Fence : public RefCounted { + public: + UINT64 GetFenceValue() const; + + protected: + Fence(UINT64 fenceValue, HANDLE sharedHandle); + ~Fence() override; + + const UINT64 mFenceValue; + const HANDLE mSharedHandle; +}; + +} // namespace dawn::native::d3d + +#endif // SRC_DAWN_NATIVE_D3D_FENCE_H_ diff --git a/src/dawn/native/d3d/Forward.h b/src/dawn/native/d3d/Forward.h index e1d4db33ac..02cebc1b5a 100644 --- a/src/dawn/native/d3d/Forward.h +++ b/src/dawn/native/d3d/Forward.h @@ -22,11 +22,13 @@ namespace dawn::native::d3d { class PhysicalDevice; class Device; class SwapChain; +class Texture; struct D3DBackendTraits { using DeviceType = Device; using PhysicalDeviceType = PhysicalDevice; using SwapChainType = SwapChain; + using TextureType = Texture; }; template diff --git a/src/dawn/native/d3d/TextureD3D.cpp b/src/dawn/native/d3d/TextureD3D.cpp new file mode 100644 index 0000000000..0c1468b3fd --- /dev/null +++ b/src/dawn/native/d3d/TextureD3D.cpp @@ -0,0 +1,21 @@ +// Copyright 2023 The Dawn Authors +// +// 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 "dawn/native/d3d/TextureD3D.h" + +namespace dawn::native::d3d { + +Texture::~Texture() = default; + +} // namespace dawn::native::d3d diff --git a/src/dawn/native/d3d/TextureD3D.h b/src/dawn/native/d3d/TextureD3D.h new file mode 100644 index 0000000000..dd311ea102 --- /dev/null +++ b/src/dawn/native/d3d/TextureD3D.h @@ -0,0 +1,35 @@ +// Copyright 2023 The Dawn Authors +// +// 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. + +#ifndef SRC_DAWN_NATIVE_D3D_TEXTURED3D_H_ +#define SRC_DAWN_NATIVE_D3D_TEXTURED3D_H_ + +#include "dawn/native/Error.h" +#include "dawn/native/IntegerTypes.h" +#include "dawn/native/Texture.h" + +namespace dawn::native::d3d { + +class Texture : public TextureBase { + public: + virtual ResultOrError EndAccess() = 0; + + protected: + using TextureBase::TextureBase; + ~Texture() override; +}; + +} // namespace dawn::native::d3d + +#endif // SRC_DAWN_NATIVE_D3D_TEXTURED3D_H_ diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp index 2fd6f3bd1b..941002e2c5 100644 --- a/src/dawn/native/d3d11/DeviceD3D11.cpp +++ b/src/dawn/native/d3d11/DeviceD3D11.cpp @@ -25,12 +25,14 @@ #include "dawn/native/Instance.h" #include "dawn/native/d3d/D3DError.h" #include "dawn/native/d3d/ExternalImageDXGIImpl.h" +#include "dawn/native/d3d/UtilsD3D.h" #include "dawn/native/d3d11/BackendD3D11.h" #include "dawn/native/d3d11/BindGroupD3D11.h" #include "dawn/native/d3d11/BindGroupLayoutD3D11.h" #include "dawn/native/d3d11/BufferD3D11.h" #include "dawn/native/d3d11/CommandBufferD3D11.h" #include "dawn/native/d3d11/ComputePipelineD3D11.h" +#include "dawn/native/d3d11/FenceD3D11.h" #include "dawn/native/d3d11/PhysicalDeviceD3D11.h" #include "dawn/native/d3d11/PipelineLayoutD3D11.h" #include "dawn/native/d3d11/PlatformFunctionsD3D11.h" @@ -126,17 +128,7 @@ MaybeError Device::Initialize(const DeviceDescriptor* descriptor) { return {}; } -Device::~Device() { - Destroy(); - - // Close the handle here instead of in DestroyImpl. The handle is returned from - // ExternalImageDXGI, so it needs to live as long as the Device ref does, even if the device - // state is destroyed. - if (mFenceHandle != nullptr) { - ::CloseHandle(mFenceHandle); - mFenceHandle = nullptr; - } -} +Device::~Device() = default; ID3D11Device* Device::GetD3D11Device() const { return mD3d11Device.Get(); @@ -390,6 +382,8 @@ void Device::AppendDebugLayerMessages(ErrorData* error) { void Device::DestroyImpl() { ASSERT(GetState() == State::Disconnected); + Base::DestroyImpl(); + if (mFenceEvent != nullptr) { ::CloseHandle(mFenceEvent); mFenceEvent = nullptr; @@ -412,11 +406,43 @@ float Device::GetTimestampPeriodInNS() const { void Device::SetLabelImpl() {} -std::unique_ptr Device::CreateExternalImageDXGIImpl( +ResultOrError> Device::CreateFence( + const d3d::ExternalImageDXGIFenceDescriptor* descriptor) { + return Fence::CreateFromHandle(mD3d11Device5.Get(), descriptor->fenceHandle, + descriptor->fenceValue); +} + +ResultOrError> Device::CreateExternalImageDXGIImplImpl( const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) { - // TODO(dawn:1724): Implement this - UNREACHABLE(); - return {}; + // ExternalImageDXGIImpl holds a weak reference to the device. If the device is destroyed before + // the image is created, the image will have a dangling reference to the device which can cause + // a use-after-free. + DAWN_TRY(ValidateIsAlive()); + + ComPtr d3d11Resource; + DAWN_TRY(CheckHRESULT( + mD3d11Device5->OpenSharedResource1(descriptor->sharedHandle, IID_PPV_ARGS(&d3d11Resource)), + "D3D11 OpenSharedResource1")); + + const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor); + DAWN_TRY(ValidateTextureDescriptor(this, textureDescriptor)); + + DAWN_TRY_CONTEXT(d3d::ValidateTextureDescriptorCanBeWrapped(textureDescriptor), + "validating that a D3D11 external image can be wrapped with %s", + textureDescriptor); + + DAWN_TRY(ValidateTextureCanBeWrapped(d3d11Resource.Get(), textureDescriptor)); + + // Shared handle is assumed to support resource sharing capability. The resource + // shared capability tier must agree to share resources between D3D devices. + const Format* format = GetInternalFormat(textureDescriptor->format).AcquireSuccess(); + if (format->IsMultiPlanar()) { + DAWN_TRY(ValidateVideoTextureCanBeShared( + this, d3d::DXGITextureFormat(textureDescriptor->format))); + } + + return std::make_unique(this, std::move(d3d11Resource), + textureDescriptor); } bool Device::MayRequireDuplicationOfIndirectParameters() const { @@ -427,8 +453,19 @@ uint64_t Device::GetBufferCopyOffsetAlignmentForDepthStencil() const { return DeviceBase::GetBufferCopyOffsetAlignmentForDepthStencil(); } -HANDLE Device::GetFenceHandle() const { - return mFenceHandle; +Ref Device::CreateD3DExternalTexture(const TextureDescriptor* descriptor, + ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized) { + Ref dawnTexture; + if (ConsumedError( + Texture::CreateExternalImage(this, descriptor, std::move(d3dTexture), + std::move(waitFences), isSwapChainTexture, isInitialized), + &dawnTexture)) { + return nullptr; + } + return {dawnTexture}; } } // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/DeviceD3D11.h b/src/dawn/native/d3d11/DeviceD3D11.h index 1b1774d201..0ab13a7640 100644 --- a/src/dawn/native/d3d11/DeviceD3D11.h +++ b/src/dawn/native/d3d11/DeviceD3D11.h @@ -51,12 +51,11 @@ class Device final : public d3d::Device { void ReferenceUntilUnused(ComPtr object); MaybeError ExecutePendingCommandContext(); - HANDLE GetFenceHandle() const; - Ref CreateD3D11ExternalTexture(const TextureDescriptor* descriptor, - ComPtr d3d11Texture, - std::vector> waitFences, - bool isSwapChainTexture, - bool isInitialized); + Ref CreateD3DExternalTexture(const TextureDescriptor* descriptor, + ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized) override; ResultOrError> CreateCommandBuffer( CommandEncoder* encoder, @@ -79,7 +78,9 @@ class Device final : public d3d::Device { uint64_t GetBufferCopyOffsetAlignmentForDepthStencil() const override; void SetLabelImpl() override; - std::unique_ptr CreateExternalImageDXGIImpl( + ResultOrError> CreateFence( + const d3d::ExternalImageDXGIFenceDescriptor* descriptor) override; + ResultOrError> CreateExternalImageDXGIImplImpl( const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) override; private: @@ -127,7 +128,6 @@ class Device final : public d3d::Device { ResultOrError CheckAndUpdateCompletedSerials() override; ComPtr mFence; - HANDLE mFenceHandle = nullptr; HANDLE mFenceEvent = nullptr; ComPtr mD3d11Device; diff --git a/src/dawn/native/d3d11/FenceD3D11.cpp b/src/dawn/native/d3d11/FenceD3D11.cpp new file mode 100644 index 0000000000..7dbffc2b15 --- /dev/null +++ b/src/dawn/native/d3d11/FenceD3D11.cpp @@ -0,0 +1,53 @@ +// Copyright 2023 The Dawn Authors +// +// 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 "dawn/native/d3d11/FenceD3D11.h" + +#include + +#include "dawn/common/Log.h" +#include "dawn/native/Error.h" +#include "dawn/native/d3d/D3DError.h" +#include "dawn/native/d3d12/DeviceD3D12.h" + +namespace dawn::native::d3d11 { + +// static +ResultOrError> Fence::CreateFromHandle(ID3D11Device5* device, + HANDLE unownedHandle, + UINT64 fenceValue) { + ASSERT(unownedHandle != nullptr); + HANDLE ownedHandle = nullptr; + if (!::DuplicateHandle(::GetCurrentProcess(), unownedHandle, ::GetCurrentProcess(), + &ownedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { + return DAWN_DEVICE_LOST_ERROR("D3D11 fence dup handle"); + } + ComPtr d3d11Fence; + DAWN_TRY_WITH_CLEANUP( + CheckHRESULT(device->OpenSharedFence(ownedHandle, IID_PPV_ARGS(&d3d11Fence)), + "D3D11 fence open handle"), + { ::CloseHandle(ownedHandle); }); + return AcquireRef(new Fence(std::move(d3d11Fence), fenceValue, ownedHandle)); +} + +Fence::Fence(ComPtr d3d11Fence, UINT64 fenceValue, HANDLE sharedHandle) + : Base(fenceValue, sharedHandle), mD3D11Fence(std::move(d3d11Fence)) {} + +Fence::~Fence() = default; + +ID3D11Fence* Fence::GetD3D11Fence() const { + return mD3D11Fence.Get(); +} + +} // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/FenceD3D11.h b/src/dawn/native/d3d11/FenceD3D11.h new file mode 100644 index 0000000000..92dc5ae3ed --- /dev/null +++ b/src/dawn/native/d3d11/FenceD3D11.h @@ -0,0 +1,45 @@ +// Copyright 2023 The Dawn Authors +// +// 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. + +#ifndef SRC_DAWN_NATIVE_D3D11_FENCED3D11_H_ +#define SRC_DAWN_NATIVE_D3D11_FENCED3D11_H_ + +#include "dawn/common/RefCounted.h" +#include "dawn/native/DawnNative.h" +#include "dawn/native/Error.h" +#include "dawn/native/d3d/Fence.h" +#include "dawn/native/d3d/d3d_platform.h" + +namespace dawn::native::d3d11 { + +class Fence : public d3d::Fence { + public: + static ResultOrError> CreateFromHandle(ID3D11Device5* device, + HANDLE unownedHandle, + UINT64 fenceValue); + + ID3D11Fence* GetD3D11Fence() const; + + private: + using Base = d3d::Fence; + + Fence(ComPtr d3d11Fence, UINT64 fenceValue, HANDLE sharedHandle); + ~Fence() override; + + ComPtr mD3D11Fence; +}; + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_FENCED3D11_H_ diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp index 2850ac08f1..ff76f6f710 100644 --- a/src/dawn/native/d3d11/TextureD3D11.cpp +++ b/src/dawn/native/d3d11/TextureD3D11.cpp @@ -28,6 +28,7 @@ #include "dawn/native/d3d/D3DError.h" #include "dawn/native/d3d/UtilsD3D.h" #include "dawn/native/d3d11/DeviceD3D11.h" +#include "dawn/native/d3d11/FenceD3D11.h" #include "dawn/native/d3d11/Forward.h" #include "dawn/native/d3d11/UtilsD3D11.h" @@ -63,6 +64,47 @@ Aspect D3D11Aspect(Aspect aspect) { } // namespace +MaybeError ValidateTextureCanBeWrapped(ID3D11Resource* d3d11Resource, + const TextureDescriptor* dawnDescriptor) { + ComPtr d3d11Texture; + DAWN_TRY( + CheckHRESULT(d3d11Resource->QueryInterface(IID_PPV_ARGS(&d3d11Texture)), "QueryInterface")); + + D3D11_TEXTURE2D_DESC d3dDescriptor; + d3d11Texture->GetDesc(&d3dDescriptor); + + DAWN_INVALID_IF( + (dawnDescriptor->size.width != d3dDescriptor.Width) || + (dawnDescriptor->size.height != d3dDescriptor.Height) || + (dawnDescriptor->size.depthOrArrayLayers != 1), + "D3D11 texture size (Width: %u, Height: %u, DepthOrArraySize: 1) doesn't match Dawn " + "descriptor size (width: %u, height: %u, depthOrArrayLayers: %u).", + d3dDescriptor.Width, d3dDescriptor.Height, dawnDescriptor->size.width, + dawnDescriptor->size.height, dawnDescriptor->size.depthOrArrayLayers); + + const DXGI_FORMAT dxgiFormatFromDescriptor = d3d::DXGITextureFormat(dawnDescriptor->format); + DAWN_INVALID_IF(dxgiFormatFromDescriptor != d3dDescriptor.Format, + "D3D11 texture format (%x) is not compatible with Dawn descriptor format (%s).", + d3dDescriptor.Format, dawnDescriptor->format); + + DAWN_INVALID_IF(d3dDescriptor.ArraySize != 1, "D3D12 texture array size (%u) is not 1.", + d3dDescriptor.ArraySize); + + DAWN_INVALID_IF(d3dDescriptor.MipLevels != 1, + "D3D11 texture number of miplevels (%u) is not 1.", d3dDescriptor.MipLevels); + + // Shared textures cannot be multi-sample so no need to check those. + ASSERT(d3dDescriptor.SampleDesc.Count == 1); + ASSERT(d3dDescriptor.SampleDesc.Quality == 0); + + return {}; +} + +MaybeError ValidateVideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat) { + // TODO(dawn:1724): support video textures + return DAWN_UNIMPLEMENTED_ERROR("Video textures are not supported."); +} + // static ResultOrError> Texture::Create(Device* device, const TextureDescriptor* descriptor) { Ref texture = AcquireRef( @@ -89,6 +131,31 @@ ResultOrError> Texture::CreateStaging(Device* device, return std::move(texture); } +// static +ResultOrError> Texture::CreateExternalImage(Device* device, + const TextureDescriptor* descriptor, + ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized) { + Ref dawnTexture = AcquireRef( + new Texture(device, descriptor, TextureState::OwnedExternal, /*isStaging=*/false)); + + DAWN_TRY(dawnTexture->InitializeAsExternalTexture(std::move(d3dTexture), std::move(waitFences), + isSwapChainTexture)); + + // Importing a multi-planar format must be initialized. This is required because + // a shared multi-planar format cannot be initialized by Dawn. + DAWN_INVALID_IF( + !isInitialized && dawnTexture->GetFormat().IsMultiPlanar(), + "Cannot create a texture with a multi-planar format (%s) with uninitialized data.", + dawnTexture->GetFormat().format); + + dawnTexture->SetIsSubresourceContentInitialized(isInitialized, + dawnTexture->GetAllSubresources()); + return std::move(dawnTexture); +} + template T Texture::GetD3D11TextureDesc() const { T desc; @@ -182,11 +249,30 @@ MaybeError Texture::InitializeAsSwapChainTexture(ComPtr d3d11Tex return {}; } +MaybeError Texture::InitializeAsExternalTexture(ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture) { + ComPtr d3d11Texture; + DAWN_TRY(CheckHRESULT(d3dTexture.As(&d3d11Texture), "Query ID3D11Resource from IUnknown")); + + CommandRecordingContext* commandContext = ToBackend(GetDevice())->GetPendingCommandContext(); + ID3D11DeviceContext4* d3d11DeviceContext4 = commandContext->GetD3D11DeviceContext4(); + for (Ref& fence : waitFences) { + DAWN_TRY(CheckHRESULT( + d3d11DeviceContext4->Wait(static_cast(fence.Get())->GetD3D11Fence(), + fence->GetFenceValue()), + "ID3D11DeviceContext4::Wait")); + } + mD3d11Resource = std::move(d3d11Texture); + SetLabelHelper("Dawn_ExternalTexture"); + return {}; +} + Texture::Texture(Device* device, const TextureDescriptor* descriptor, TextureState state, bool isStaging) - : TextureBase(device, descriptor, state), mIsStaging(isStaging) {} + : Base(device, descriptor, state), mIsStaging(isStaging) {} Texture::~Texture() = default; @@ -600,6 +686,11 @@ MaybeError Texture::Copy(CommandRecordingContext* commandContext, CopyTextureToT return {}; } +ResultOrError Texture::EndAccess() { + // TODO(dawn:1705): submit pending commands if deferred context is used. + return GetDevice()->GetLastSubmittedCommandSerial(); +} + // static Ref TextureView::Create(TextureBase* texture, const TextureViewDescriptor* descriptor) { diff --git a/src/dawn/native/d3d11/TextureD3D11.h b/src/dawn/native/d3d11/TextureD3D11.h index 00024fdcf6..06e84a21ca 100644 --- a/src/dawn/native/d3d11/TextureD3D11.h +++ b/src/dawn/native/d3d11/TextureD3D11.h @@ -15,29 +15,44 @@ #ifndef SRC_DAWN_NATIVE_D3D11_TEXTURED3D11_H_ #define SRC_DAWN_NATIVE_D3D11_TEXTURED3D11_H_ +#include + #include "dawn/native/DawnNative.h" #include "dawn/native/Error.h" #include "dawn/native/IntegerTypes.h" #include "dawn/native/PassResourceUsage.h" -#include "dawn/native/Texture.h" +#include "dawn/native/d3d/TextureD3D.h" #include "dawn/native/d3d/d3d_platform.h" namespace dawn::native { struct CopyTextureToTextureCmd; } // namespace dawn::native +namespace dawn::native::d3d { +class Fence; +} // namespace dawn::native::d3d + namespace dawn::native::d3d11 { class CommandRecordingContext; class Device; -class Texture final : public TextureBase { +MaybeError ValidateTextureCanBeWrapped(ID3D11Resource* d3d11Resource, + const TextureDescriptor* descriptor); +MaybeError ValidateVideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat); + +class Texture final : public d3d::Texture { public: static ResultOrError> Create(Device* device, const TextureDescriptor* descriptor); static ResultOrError> Create(Device* device, const TextureDescriptor* descriptor, ComPtr d3d11Texture); - + static ResultOrError> CreateExternalImage(Device* device, + const TextureDescriptor* descriptor, + ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized); DXGI_FORMAT GetD3D11Format() const; ID3D11Resource* GetD3D11Resource() const; @@ -67,7 +82,11 @@ class Texture final : public TextureBase { ReadCallback callback); static MaybeError Copy(CommandRecordingContext* commandContext, CopyTextureToTextureCmd* copy); + ResultOrError EndAccess() override; + private: + using Base = d3d::Texture; + static ResultOrError> CreateStaging(Device* device, const TextureDescriptor* descriptor); @@ -82,7 +101,9 @@ class Texture final : public TextureBase { MaybeError InitializeAsInternalTexture(); MaybeError InitializeAsSwapChainTexture(ComPtr d3d11Texture); - + MaybeError InitializeAsExternalTexture(ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture); void SetLabelHelper(const char* prefix); // Dawn API diff --git a/src/dawn/native/d3d12/D3D12Backend.cpp b/src/dawn/native/d3d12/D3D12Backend.cpp index 67093fa264..db693ed916 100644 --- a/src/dawn/native/d3d12/D3D12Backend.cpp +++ b/src/dawn/native/d3d12/D3D12Backend.cpp @@ -28,10 +28,6 @@ namespace dawn::native::d3d12 { -ComPtr GetD3D12Device(WGPUDevice device) { - return ToBackend(FromAPI(device))->GetD3D12Device(); -} - uint64_t SetExternalMemoryReservation(WGPUDevice device, uint64_t requestedReservationSize, MemorySegment memorySegment) { diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp index a799379cd2..d1088b777d 100644 --- a/src/dawn/native/d3d12/DeviceD3D12.cpp +++ b/src/dawn/native/d3d12/DeviceD3D12.cpp @@ -24,13 +24,14 @@ #include "dawn/native/DynamicUploader.h" #include "dawn/native/Instance.h" #include "dawn/native/d3d/D3DError.h" +#include "dawn/native/d3d/ExternalImageDXGIImpl.h" #include "dawn/native/d3d12/BackendD3D12.h" #include "dawn/native/d3d12/BindGroupD3D12.h" #include "dawn/native/d3d12/BindGroupLayoutD3D12.h" #include "dawn/native/d3d12/CommandAllocatorManager.h" #include "dawn/native/d3d12/CommandBufferD3D12.h" #include "dawn/native/d3d12/ComputePipelineD3D12.h" -#include "dawn/native/d3d12/ExternalImageDXGIImplD3D12.h" +#include "dawn/native/d3d12/FenceD3D12.h" #include "dawn/native/d3d12/PhysicalDeviceD3D12.h" #include "dawn/native/d3d12/PipelineLayoutD3D12.h" #include "dawn/native/d3d12/PlatformFunctionsD3D12.h" @@ -191,16 +192,7 @@ Device::Device(AdapterBase* adapter, const TogglesState& deviceToggles) : Base(adapter, descriptor, deviceToggles) {} -Device::~Device() { - Destroy(); - - // Close the handle here instead of in DestroyImpl. The handle is returned from - // ExternalImageDXGI, so it needs to live as long as the Device ref does, even if the device - // state is destroyed. - if (mFenceHandle != nullptr) { - ::CloseHandle(mFenceHandle); - } -} +Device::~Device() = default; ID3D12Device* Device::GetD3D12Device() const { return mD3d12Device.Get(); @@ -214,10 +206,6 @@ ID3D12SharingContract* Device::GetSharingContract() const { return mD3d12SharingContract.Get(); } -HANDLE Device::GetFenceHandle() const { - return mFenceHandle; -} - ComPtr Device::GetDispatchIndirectSignature() const { return mDispatchIndirectSignature; } @@ -545,61 +533,54 @@ ResultOrError Device::AllocateMemory( forceAllocateAsCommittedResource); } -std::unique_ptr Device::CreateExternalImageDXGIImpl( +ResultOrError> Device::CreateFence( + const d3d::ExternalImageDXGIFenceDescriptor* descriptor) { + return Fence::CreateFromHandle(mD3d12Device.Get(), descriptor->fenceHandle, + descriptor->fenceValue); +} + +ResultOrError> Device::CreateExternalImageDXGIImplImpl( const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) { // ExternalImageDXGIImpl holds a weak reference to the device. If the device is destroyed before // the image is created, the image will have a dangling reference to the device which can cause // a use-after-free. - if (ConsumedError(ValidateIsAlive())) { - return nullptr; - } + DAWN_TRY(ValidateIsAlive()); Microsoft::WRL::ComPtr d3d12Resource; - if (FAILED(GetD3D12Device()->OpenSharedHandle(descriptor->sharedHandle, - IID_PPV_ARGS(&d3d12Resource)))) { - return nullptr; - } + DAWN_TRY(CheckHRESULT( + GetD3D12Device()->OpenSharedHandle(descriptor->sharedHandle, IID_PPV_ARGS(&d3d12Resource)), + "D3D12 opening shared handle")); const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor); - if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) { - return nullptr; - } + DAWN_TRY(ValidateTextureDescriptor(this, textureDescriptor)); - if (ConsumedError(ValidateTextureDescriptorCanBeWrapped(textureDescriptor), - "validating that a D3D12 external image can be wrapped with %s", - textureDescriptor)) { - return nullptr; - } + DAWN_TRY_CONTEXT(d3d::ValidateTextureDescriptorCanBeWrapped(textureDescriptor), + "validating that a D3D12 external image can be wrapped with %s", + textureDescriptor); - if (ConsumedError(ValidateD3D12TextureCanBeWrapped(d3d12Resource.Get(), textureDescriptor))) { - return nullptr; - } + DAWN_TRY(ValidateTextureCanBeWrapped(d3d12Resource.Get(), textureDescriptor)); // Shared handle is assumed to support resource sharing capability. The resource // shared capability tier must agree to share resources between D3D devices. const Format* format = GetInternalFormat(textureDescriptor->format).AcquireSuccess(); if (format->IsMultiPlanar()) { - if (ConsumedError(ValidateD3D12VideoTextureCanBeShared( - this, d3d::DXGITextureFormat(textureDescriptor->format)))) { - return nullptr; - } + DAWN_TRY(ValidateVideoTextureCanBeShared( + this, d3d::DXGITextureFormat(textureDescriptor->format))); } - auto impl = - std::make_unique(this, std::move(d3d12Resource), textureDescriptor); - mExternalImageList.Append(impl.get()); - return impl; + return std::make_unique(this, std::move(d3d12Resource), + textureDescriptor); } -Ref Device::CreateD3D12ExternalTexture(const TextureDescriptor* descriptor, - ComPtr d3d12Texture, - std::vector> waitFences, - bool isSwapChainTexture, - bool isInitialized) { +Ref Device::CreateD3DExternalTexture(const TextureDescriptor* descriptor, + ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized) { Ref dawnTexture; if (ConsumedError( - Texture::CreateExternalImage(this, descriptor, std::move(d3d12Texture), + Texture::CreateExternalImage(this, descriptor, std::move(d3dTexture), std::move(waitFences), isSwapChainTexture, isInitialized), &dawnTexture)) { return nullptr; @@ -706,11 +687,7 @@ void Device::AppendDebugLayerMessages(ErrorData* error) { void Device::DestroyImpl() { ASSERT(GetState() == State::Disconnected); - while (!mExternalImageList.empty()) { - d3d::ExternalImageDXGIImpl* externalImage = mExternalImageList.head()->value(); - // ExternalImageDXGIImpl::DestroyInternal() calls RemoveFromList(). - externalImage->DestroyInternal(); - } + Base::DestroyImpl(); mZeroBuffer = nullptr; diff --git a/src/dawn/native/d3d12/DeviceD3D12.h b/src/dawn/native/d3d12/DeviceD3D12.h index a0281553d0..40a64c6e40 100644 --- a/src/dawn/native/d3d12/DeviceD3D12.h +++ b/src/dawn/native/d3d12/DeviceD3D12.h @@ -26,7 +26,6 @@ #include "dawn/native/d3d12/TextureD3D12.h" namespace dawn::native::d3d { -struct ExternalImageDescriptorDXGISharedHandle; class ExternalImageDXGIImpl; } // namespace dawn::native::d3d @@ -65,7 +64,6 @@ class Device final : public d3d::Device { ID3D12Device* GetD3D12Device() const; ComPtr GetCommandQueue() const; ID3D12SharingContract* GetSharingContract() const; - HANDLE GetFenceHandle() const; ComPtr GetDispatchIndirectSignature() const; ComPtr GetDrawIndirectSignature() const; @@ -137,14 +135,16 @@ class Device final : public d3d::Device { StagingDescriptorAllocator* GetDepthStencilViewAllocator() const; - std::unique_ptr CreateExternalImageDXGIImpl( + ResultOrError> CreateFence( + const d3d::ExternalImageDXGIFenceDescriptor* descriptor) override; + ResultOrError> CreateExternalImageDXGIImplImpl( const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) override; - Ref CreateD3D12ExternalTexture(const TextureDescriptor* descriptor, - ComPtr d3d12Texture, - std::vector> waitFences, - bool isSwapChainTexture, - bool isInitialized); + Ref CreateD3DExternalTexture(const TextureDescriptor* descriptor, + ComPtr d3dTexture, + std::vector> waitFences, + bool isSwapChainTexture, + bool isInitialized) override; uint32_t GetOptimalBytesPerRowAlignment() const override; uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override; @@ -218,7 +218,6 @@ class Device final : public d3d::Device { ComPtr mFence; HANDLE mFenceEvent = nullptr; - HANDLE mFenceHandle = nullptr; ResultOrError CheckAndUpdateCompletedSerials() override; ComPtr mD3d12Device; // Device is owned by adapter and will not be outlived. @@ -274,9 +273,6 @@ class Device final : public d3d::Device { // The number of nanoseconds required for a timestamp query to be incremented by 1 float mTimestampPeriod = 1.0f; - - // List of external image resources opened using this device. - LinkedList mExternalImageList; }; } // namespace dawn::native::d3d12 diff --git a/src/dawn/native/d3d12/ExternalImageDXGIImplD3D12.cpp b/src/dawn/native/d3d12/ExternalImageDXGIImplD3D12.cpp deleted file mode 100644 index 34aae56ff3..0000000000 --- a/src/dawn/native/d3d12/ExternalImageDXGIImplD3D12.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2022 The Dawn Authors -// -// 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 "dawn/native/d3d12/ExternalImageDXGIImplD3D12.h" - -#include -#include - -#include "dawn/common/Log.h" -#include "dawn/native/D3D12Backend.h" -#include "dawn/native/DawnNative.h" -#include "dawn/native/d3d12/DeviceD3D12.h" -#include "dawn/native/d3d12/Forward.h" - -namespace dawn::native::d3d12 { - -ExternalImageDXGIImpl::ExternalImageDXGIImpl(Device* backendDevice, - Microsoft::WRL::ComPtr d3d12Resource, - const TextureDescriptor* textureDescriptor) - : Base(backendDevice, textureDescriptor), mD3D12Resource(std::move(d3d12Resource)) { - ASSERT(mD3D12Resource != nullptr); -} - -ExternalImageDXGIImpl::~ExternalImageDXGIImpl() = default; - -void ExternalImageDXGIImpl::DestroyInternal() { - if (IsInList()) { - mD3D12Resource = nullptr; - } - Base::DestroyInternal(); -} - -WGPUTexture ExternalImageDXGIImpl::BeginAccess( - const d3d::ExternalImageDXGIBeginAccessDescriptor* descriptor) { - ASSERT(descriptor != nullptr); - - auto deviceLock(GetScopedDeviceLock()); - - if (!IsInList()) { - dawn::ErrorLog() << "Cannot use external image after device destruction"; - return nullptr; - } - - // Ensure the texture usage is allowed - if (!IsSubset(descriptor->usage, static_cast(mUsage))) { - dawn::ErrorLog() << "Texture usage is not valid for external image"; - return nullptr; - } - - ASSERT(mBackendDevice != nullptr); - - TextureDescriptor textureDescriptor = {}; - textureDescriptor.usage = static_cast(descriptor->usage); - textureDescriptor.dimension = mDimension; - textureDescriptor.size = {mSize.width, mSize.height, mSize.depthOrArrayLayers}; - textureDescriptor.format = mFormat; - textureDescriptor.mipLevelCount = mMipLevelCount; - textureDescriptor.sampleCount = mSampleCount; - textureDescriptor.viewFormats = mViewFormats.data(); - textureDescriptor.viewFormatCount = static_cast(mViewFormats.size()); - - DawnTextureInternalUsageDescriptor internalDesc = {}; - if (mUsageInternal != wgpu::TextureUsage::None) { - textureDescriptor.nextInChain = &internalDesc; - internalDesc.internalUsage = mUsageInternal; - internalDesc.sType = wgpu::SType::DawnTextureInternalUsageDescriptor; - } - - std::vector> waitFences; - for (const d3d::ExternalImageDXGIFenceDescriptor& fenceDescriptor : descriptor->waitFences) { - ASSERT(fenceDescriptor.fenceHandle != nullptr); - // TODO(sunnyps): Use a fence cache instead of re-importing fences on each BeginAccess. - Ref fence; - if (mBackendDevice->ConsumedError( - Fence::CreateFromHandle(ToBackend(mBackendDevice.Get())->GetD3D12Device(), - fenceDescriptor.fenceHandle, fenceDescriptor.fenceValue), - &fence)) { - dawn::ErrorLog() << "Unable to create D3D12 fence for external image"; - return nullptr; - } - waitFences.push_back(std::move(fence)); - } - - Ref texture = - ToBackend(mBackendDevice.Get()) - ->CreateD3D12ExternalTexture(&textureDescriptor, mD3D12Resource, std::move(waitFences), - descriptor->isSwapChainTexture, descriptor->isInitialized); - return ToAPI(texture.Detach()); -} - -void ExternalImageDXGIImpl::EndAccess(WGPUTexture texture, - d3d::ExternalImageDXGIFenceDescriptor* signalFence) { - auto deviceLock(GetScopedDeviceLock()); - - if (!IsInList()) { - dawn::ErrorLog() << "Cannot use external image after device destruction"; - return; - } - - ASSERT(mBackendDevice != nullptr); - ASSERT(signalFence != nullptr); - - Texture* backendTexture = ToBackend(FromAPI(texture)); - ASSERT(backendTexture != nullptr); - - ExecutionSerial fenceValue; - if (mBackendDevice->ConsumedError(backendTexture->EndAccess(), &fenceValue)) { - dawn::ErrorLog() << "D3D12 fence end access failed"; - return; - } - signalFence->fenceHandle = ToBackend(mBackendDevice.Get())->GetFenceHandle(); - signalFence->fenceValue = static_cast(fenceValue); -} - -} // namespace dawn::native::d3d12 diff --git a/src/dawn/native/d3d12/ExternalImageDXGIImplD3D12.h b/src/dawn/native/d3d12/ExternalImageDXGIImplD3D12.h deleted file mode 100644 index 14edcdb4ec..0000000000 --- a/src/dawn/native/d3d12/ExternalImageDXGIImplD3D12.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2022 The Dawn Authors -// -// 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. - -#ifndef SRC_DAWN_NATIVE_D3D12_EXTERNALIMAGEDXGIIMPLD3D12_H_ -#define SRC_DAWN_NATIVE_D3D12_EXTERNALIMAGEDXGIIMPLD3D12_H_ - -#include - -#include -#include - -#include "dawn/common/LinkedList.h" -#include "dawn/common/Mutex.h" -#include "dawn/native/D3D12Backend.h" -#include "dawn/native/Error.h" -#include "dawn/native/Forward.h" -#include "dawn/native/IntegerTypes.h" -#include "dawn/native/d3d/ExternalImageDXGIImpl.h" -#include "dawn/native/d3d12/FenceD3D12.h" -#include "dawn/webgpu_cpp.h" - -struct ID3D12Resource; -struct ID3D12Fence; - -namespace dawn::native::d3d { -struct ExternalImageDXGIBeginAccessDescriptor; -struct ExternalImageDescriptorDXGISharedHandle; -} // namespace dawn::native::d3d - -namespace dawn::native::d3d12 { - -class Device; - -class ExternalImageDXGIImpl : public d3d::ExternalImageDXGIImpl { - public: - ExternalImageDXGIImpl(Device* backendDevice, - Microsoft::WRL::ComPtr d3d12Resource, - const TextureDescriptor* textureDescriptor); - ~ExternalImageDXGIImpl() override; - - ExternalImageDXGIImpl(const ExternalImageDXGIImpl&) = delete; - ExternalImageDXGIImpl& operator=(const ExternalImageDXGIImpl&) = delete; - - bool IsValid() const; - - WGPUTexture BeginAccess(const d3d::ExternalImageDXGIBeginAccessDescriptor* descriptor) override; - - void EndAccess(WGPUTexture texture, - d3d::ExternalImageDXGIFenceDescriptor* signalFence) override; - - // This method should only be called by internal code. Don't call this from D3D12Backend side, - // or without locking. - void DestroyInternal() override; - - private: - using Base = d3d::ExternalImageDXGIImpl; - - Microsoft::WRL::ComPtr mD3D12Resource; -}; - -} // namespace dawn::native::d3d12 - -#endif // SRC_DAWN_NATIVE_D3D12_EXTERNALIMAGEDXGIIMPLD3D12_H_ diff --git a/src/dawn/native/d3d12/FenceD3D12.cpp b/src/dawn/native/d3d12/FenceD3D12.cpp index 562f8ba8f9..1f56208e03 100644 --- a/src/dawn/native/d3d12/FenceD3D12.cpp +++ b/src/dawn/native/d3d12/FenceD3D12.cpp @@ -42,20 +42,12 @@ ResultOrError> Fence::CreateFromHandle(ID3D12Device* device, } Fence::Fence(ComPtr d3d12Fence, UINT64 fenceValue, HANDLE sharedHandle) - : mD3D12Fence(std::move(d3d12Fence)), mFenceValue(fenceValue), mSharedHandle(sharedHandle) {} + : Base(fenceValue, sharedHandle), mD3D12Fence(std::move(d3d12Fence)) {} -Fence::~Fence() { - if (mSharedHandle != nullptr) { - ::CloseHandle(mSharedHandle); - } -} +Fence::~Fence() = default; ID3D12Fence* Fence::GetD3D12Fence() const { return mD3D12Fence.Get(); } -UINT64 Fence::GetFenceValue() const { - return mFenceValue; -} - } // namespace dawn::native::d3d12 diff --git a/src/dawn/native/d3d12/FenceD3D12.h b/src/dawn/native/d3d12/FenceD3D12.h index aa73cfabcd..25921d7468 100644 --- a/src/dawn/native/d3d12/FenceD3D12.h +++ b/src/dawn/native/d3d12/FenceD3D12.h @@ -18,26 +18,26 @@ #include "dawn/common/RefCounted.h" #include "dawn/native/DawnNative.h" #include "dawn/native/Error.h" +#include "dawn/native/d3d/Fence.h" #include "dawn/native/d3d12/d3d12_platform.h" namespace dawn::native::d3d12 { -class Fence : public RefCounted { +class Fence : public d3d::Fence { public: static ResultOrError> CreateFromHandle(ID3D12Device* device, HANDLE unownedHandle, UINT64 fenceValue); ID3D12Fence* GetD3D12Fence() const; - UINT64 GetFenceValue() const; private: + using Base = d3d::Fence; + Fence(ComPtr d3d12Fence, UINT64 fenceValue, HANDLE sharedHandle); ~Fence() override; ComPtr mD3D12Fence; - const UINT64 mFenceValue; - const HANDLE mSharedHandle; }; } // namespace dawn::native::d3d12 diff --git a/src/dawn/native/d3d12/TextureD3D12.cpp b/src/dawn/native/d3d12/TextureD3D12.cpp index 87d38308cf..78dcdda894 100644 --- a/src/dawn/native/d3d12/TextureD3D12.cpp +++ b/src/dawn/native/d3d12/TextureD3D12.cpp @@ -112,25 +112,8 @@ D3D12_RESOURCE_DIMENSION D3D12TextureDimension(wgpu::TextureDimension dimension) } // namespace -MaybeError ValidateTextureDescriptorCanBeWrapped(const TextureDescriptor* descriptor) { - DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D, - "Texture dimension (%s) is not %s.", descriptor->dimension, - wgpu::TextureDimension::e2D); - - DAWN_INVALID_IF(descriptor->mipLevelCount != 1, "Mip level count (%u) is not 1.", - descriptor->mipLevelCount); - - DAWN_INVALID_IF(descriptor->size.depthOrArrayLayers != 1, "Array layer count (%u) is not 1.", - descriptor->size.depthOrArrayLayers); - - DAWN_INVALID_IF(descriptor->sampleCount != 1, "Sample count (%u) is not 1.", - descriptor->sampleCount); - - return {}; -} - -MaybeError ValidateD3D12TextureCanBeWrapped(ID3D12Resource* d3d12Resource, - const TextureDescriptor* dawnDescriptor) { +MaybeError ValidateTextureCanBeWrapped(ID3D12Resource* d3d12Resource, + const TextureDescriptor* dawnDescriptor) { const D3D12_RESOURCE_DESC d3dDescriptor = d3d12Resource->GetDesc(); DAWN_INVALID_IF( (dawnDescriptor->size.width != d3dDescriptor.Width) || @@ -160,7 +143,7 @@ MaybeError ValidateD3D12TextureCanBeWrapped(ID3D12Resource* d3d12Resource, } // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shared_resource_compatibility_tier -MaybeError ValidateD3D12VideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat) { +MaybeError ValidateVideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat) { const bool supportsSharedResourceCapabilityTier1 = device->GetDeviceInfo().supportsSharedResourceCapabilityTier1; switch (textureFormat) { @@ -192,15 +175,15 @@ ResultOrError> Texture::Create(Device* device, const TextureDescrip // static ResultOrError> Texture::CreateExternalImage(Device* device, const TextureDescriptor* descriptor, - ComPtr d3d12Texture, - std::vector> waitFences, + ComPtr d3dTexture, + std::vector> waitFences, bool isSwapChainTexture, bool isInitialized) { Ref dawnTexture = AcquireRef(new Texture(device, descriptor, TextureState::OwnedExternal)); - DAWN_TRY(dawnTexture->InitializeAsExternalTexture(std::move(d3d12Texture), - std::move(waitFences), isSwapChainTexture)); + DAWN_TRY(dawnTexture->InitializeAsExternalTexture(std::move(d3dTexture), std::move(waitFences), + isSwapChainTexture)); // Importing a multi-planar format must be initialized. This is required because // a shared multi-planar format cannot be initialized by Dawn. @@ -224,9 +207,12 @@ ResultOrError> Texture::Create(Device* device, return std::move(dawnTexture); } -MaybeError Texture::InitializeAsExternalTexture(ComPtr d3d12Texture, - std::vector> waitFences, +MaybeError Texture::InitializeAsExternalTexture(ComPtr d3dTexture, + std::vector> waitFences, bool isSwapChainTexture) { + ComPtr d3d12Texture; + DAWN_TRY(CheckHRESULT(d3dTexture.As(&d3d12Texture), "texture is not a valid ID3D12Resource")); + D3D12_RESOURCE_DESC desc = d3d12Texture->GetDesc(); mD3D12ResourceFlags = desc.Flags; @@ -330,14 +316,14 @@ MaybeError Texture::InitializeAsSwapChainTexture(ComPtr d3d12Tex } Texture::Texture(Device* device, const TextureDescriptor* descriptor, TextureState state) - : TextureBase(device, descriptor, state), + : Base(device, descriptor, state), mSubresourceStateAndDecay( GetFormat().aspects, GetArrayLayers(), GetNumMipLevels(), {D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COMMON, kMaxExecutionSerial, false}) {} -Texture::~Texture() {} +Texture::~Texture() = default; void Texture::DestroyImpl() { TextureBase::DestroyImpl(); @@ -405,12 +391,13 @@ DXGI_FORMAT Texture::GetD3D12CopyableSubresourceFormat(Aspect aspect) const { MaybeError Texture::SynchronizeImportedTextureBeforeUse() { // Perform the wait only on the first call. Device* device = ToBackend(GetDevice()); - for (Ref& fence : mWaitFences) { - DAWN_TRY(CheckHRESULT(device->GetCommandQueue()->Wait(fence->GetD3D12Fence(), - fence->GetFenceValue()), - "D3D12 fence wait");); + for (Ref& fence : mWaitFences) { + DAWN_TRY(CheckHRESULT( + device->GetCommandQueue()->Wait( + static_cast(fence.Get())->GetD3D12Fence(), fence->GetFenceValue()), + "D3D12 fence wait");); // Keep D3D12 fence alive since we'll clear the waitFences list below. - device->ReferenceUntilUnused(fence->GetD3D12Fence()); + device->ReferenceUntilUnused(static_cast(fence.Get())->GetD3D12Fence()); } mWaitFences.clear(); return {}; diff --git a/src/dawn/native/d3d12/TextureD3D12.h b/src/dawn/native/d3d12/TextureD3D12.h index 307d6353d2..4af3620964 100644 --- a/src/dawn/native/d3d12/TextureD3D12.h +++ b/src/dawn/native/d3d12/TextureD3D12.h @@ -19,7 +19,7 @@ #include #include "dawn/native/Error.h" -#include "dawn/native/Texture.h" +#include "dawn/native/d3d/TextureD3D.h" #include "dawn/native/DawnNative.h" #include "dawn/native/IntegerTypes.h" @@ -34,18 +34,17 @@ namespace dawn::native::d3d12 { class CommandRecordingContext; class Device; -MaybeError ValidateD3D12TextureCanBeWrapped(ID3D12Resource* d3d12Resource, - const TextureDescriptor* descriptor); -MaybeError ValidateTextureDescriptorCanBeWrapped(const TextureDescriptor* descriptor); -MaybeError ValidateD3D12VideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat); +MaybeError ValidateTextureCanBeWrapped(ID3D12Resource* d3d12Resource, + const TextureDescriptor* descriptor); +MaybeError ValidateVideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat); -class Texture final : public TextureBase { +class Texture final : public d3d::Texture { public: static ResultOrError> Create(Device* device, const TextureDescriptor* descriptor); static ResultOrError> CreateExternalImage(Device* device, const TextureDescriptor* descriptor, - ComPtr d3d12Texture, - std::vector> waitFences, + ComPtr d3dTexture, + std::vector> waitFences, bool isSwapChainTexture, bool isInitialized); static ResultOrError> Create(Device* device, @@ -54,7 +53,7 @@ class Texture final : public TextureBase { // For external textures, returns the Device internal fence's value associated with the last // ExecuteCommandLists that used this texture. If nullopt is returned, the texture wasn't used. - ResultOrError EndAccess(); + ResultOrError EndAccess() override; DXGI_FORMAT GetD3D12Format() const; ID3D12Resource* GetD3D12Resource() const; @@ -97,13 +96,14 @@ class Texture final : public TextureBase { D3D12_RESOURCE_STATES newState); private: + using Base = d3d::Texture; + Texture(Device* device, const TextureDescriptor* descriptor, TextureState state); ~Texture() override; - using TextureBase::TextureBase; MaybeError InitializeAsInternalTexture(); - MaybeError InitializeAsExternalTexture(ComPtr d3d12Texture, - std::vector> waitFences, + MaybeError InitializeAsExternalTexture(ComPtr d3dTexture, + std::vector> waitFences, bool isSwapChainTexture); MaybeError InitializeAsSwapChainTexture(ComPtr d3d12Texture); @@ -140,7 +140,7 @@ class Texture final : public TextureBase { ResourceHeapAllocation mResourceAllocation; // TODO(dawn:1460): Encapsulate imported image fields e.g. std::unique_ptr. - std::vector> mWaitFences; + std::vector> mWaitFences; std::optional mSignalFenceValue; bool mSwapChainTexture = false; diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn index 0079c295f7..c2735ba224 100644 --- a/src/dawn/tests/BUILD.gn +++ b/src/dawn/tests/BUILD.gn @@ -576,12 +576,13 @@ source_set("end2end_tests_sources") { "d3d11.lib", "dxgi.lib", ] + + sources += [ "end2end/D3DResourceWrappingTests.cpp" ] } if (dawn_enable_d3d12) { sources += [ "end2end/D3D12CachingTests.cpp", - "end2end/D3D12ResourceWrappingTests.cpp", "end2end/VideoViewsTests_win.cpp", ] } diff --git a/src/dawn/tests/end2end/D3D12ResourceWrappingTests.cpp b/src/dawn/tests/end2end/D3DResourceWrappingTests.cpp similarity index 91% rename from src/dawn/tests/end2end/D3D12ResourceWrappingTests.cpp rename to src/dawn/tests/end2end/D3DResourceWrappingTests.cpp index 8bde2bd083..2ad995993b 100644 --- a/src/dawn/tests/end2end/D3D12ResourceWrappingTests.cpp +++ b/src/dawn/tests/end2end/D3DResourceWrappingTests.cpp @@ -24,6 +24,7 @@ #include #include +#include "dawn/native/D3D11Backend.h" #include "dawn/native/D3D12Backend.h" #include "dawn/tests/DawnTest.h" #include "dawn/utils/ComboRenderPipelineDescriptor.h" @@ -33,7 +34,7 @@ using Microsoft::WRL::ComPtr; namespace { -class D3D12ResourceTestBase : public DawnTest { +class D3DResourceTestBase : public DawnTest { protected: std::vector GetRequiredFeatures() override { return {wgpu::FeatureName::DawnInternalUsages}; @@ -47,16 +48,19 @@ class D3D12ResourceTestBase : public DawnTest { } // Create the D3D11 device/contexts that will be used in subsequent tests - ComPtr d3d12Device = dawn::native::d3d12::GetD3D12Device(device.Get()); + ComPtr dxgiAdapter = + dawn::native::d3d::GetDXGIAdapter(device.GetAdapter().Get()); + DXGI_ADAPTER_DESC adapterDesc; - const LUID adapterLuid = d3d12Device->GetAdapterLuid(); - - ComPtr dxgiFactory; - HRESULT hr = ::CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgiFactory)); + HRESULT hr = dxgiAdapter->GetDesc(&adapterDesc); ASSERT_EQ(hr, S_OK); - ComPtr dxgiAdapter; - hr = dxgiFactory->EnumAdapterByLuid(adapterLuid, IID_PPV_ARGS(&dxgiAdapter)); + ComPtr dxgiFactory; + hr = ::CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgiFactory)); + ASSERT_EQ(hr, S_OK); + + dxgiAdapter = nullptr; + hr = dxgiFactory->EnumAdapterByLuid(adapterDesc.AdapterLuid, IID_PPV_ARGS(&dxgiAdapter)); ASSERT_EQ(hr, S_OK); ComPtr d3d11Device; @@ -163,12 +167,12 @@ class D3D12ResourceTestBase : public DawnTest { } // anonymous namespace -// A small fixture used to initialize default data for the D3D12Resource validation tests. +// A small fixture used to initialize default data for the D3DResource validation tests. // These tests are skipped if the harness is using the wire. -class D3D12SharedHandleValidation : public D3D12ResourceTestBase {}; +class D3DSharedHandleValidation : public D3DResourceTestBase {}; -// Test a successful wrapping of an D3D12Resource in a texture -TEST_P(D3D12SharedHandleValidation, Success) { +// Test a successful wrapping of an D3DResource in a texture +TEST_P(D3DSharedHandleValidation, Success) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::Texture texture; @@ -184,8 +188,8 @@ TEST_P(D3D12SharedHandleValidation, Success) { texture.Destroy(); } -// Test a successful wrapping of an D3D12Resource with DawnTextureInternalUsageDescriptor -TEST_P(D3D12SharedHandleValidation, SuccessWithInternalUsageDescriptor) { +// Test a successful wrapping of an D3DResource with DawnTextureInternalUsageDescriptor +TEST_P(D3DSharedHandleValidation, SuccessWithInternalUsageDescriptor) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::DawnTextureInternalUsageDescriptor internalDesc = {}; @@ -207,7 +211,7 @@ TEST_P(D3D12SharedHandleValidation, SuccessWithInternalUsageDescriptor) { } // Test an error occurs if an invalid sType is the nextInChain -TEST_P(D3D12SharedHandleValidation, InvalidTextureDescriptor) { +TEST_P(D3DSharedHandleValidation, InvalidTextureDescriptor) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::ChainedStruct chainedDescriptor; @@ -224,7 +228,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidTextureDescriptor) { } // Test an error occurs if the descriptor mip level count isn't 1 -TEST_P(D3D12SharedHandleValidation, InvalidMipLevelCount) { +TEST_P(D3DSharedHandleValidation, InvalidMipLevelCount) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseDawnDescriptor.mipLevelCount = 2; @@ -238,7 +242,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidMipLevelCount) { } // Test an error occurs if the descriptor depth isn't 1 -TEST_P(D3D12SharedHandleValidation, InvalidDepth) { +TEST_P(D3DSharedHandleValidation, InvalidDepth) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseDawnDescriptor.size.depthOrArrayLayers = 2; @@ -252,7 +256,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidDepth) { } // Test an error occurs if the descriptor sample count isn't 1 -TEST_P(D3D12SharedHandleValidation, InvalidSampleCount) { +TEST_P(D3DSharedHandleValidation, InvalidSampleCount) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseDawnDescriptor.sampleCount = 4; @@ -266,7 +270,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidSampleCount) { } // Test an error occurs if the descriptor width doesn't match the texture's -TEST_P(D3D12SharedHandleValidation, InvalidWidth) { +TEST_P(D3DSharedHandleValidation, InvalidWidth) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseDawnDescriptor.size.width = kTestWidth + 1; @@ -280,7 +284,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidWidth) { } // Test an error occurs if the descriptor height doesn't match the texture's -TEST_P(D3D12SharedHandleValidation, InvalidHeight) { +TEST_P(D3DSharedHandleValidation, InvalidHeight) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseDawnDescriptor.size.height = kTestHeight + 1; @@ -293,8 +297,8 @@ TEST_P(D3D12SharedHandleValidation, InvalidHeight) { ASSERT_EQ(texture.Get(), nullptr); } -// Test an error occurs if the descriptor format isn't compatible with the D3D12 Resource -TEST_P(D3D12SharedHandleValidation, InvalidFormat) { +// Test an error occurs if the descriptor format isn't compatible with the D3D Resource +TEST_P(D3DSharedHandleValidation, InvalidFormat) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseDawnDescriptor.format = wgpu::TextureFormat::R8Unorm; @@ -308,7 +312,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidFormat) { } // Test an error occurs if the number of D3D mip levels is greater than 1. -TEST_P(D3D12SharedHandleValidation, InvalidNumD3DMipLevels) { +TEST_P(D3DSharedHandleValidation, InvalidNumD3DMipLevels) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseD3dDescriptor.MipLevels = 2; @@ -322,7 +326,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidNumD3DMipLevels) { } // Test an error occurs if the number of array levels is greater than 1. -TEST_P(D3D12SharedHandleValidation, InvalidD3DArraySize) { +TEST_P(D3DSharedHandleValidation, InvalidD3DArraySize) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); baseD3dDescriptor.ArraySize = 2; @@ -335,7 +339,7 @@ TEST_P(D3D12SharedHandleValidation, InvalidD3DArraySize) { ASSERT_EQ(texture.Get(), nullptr); } -class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase { +class D3DSharedHandleUsageTests : public D3DResourceTestBase { protected: // Submits a 1x1x1 copy from source to destination void SimpleCopyTextureToTexture(wgpu::Texture source, wgpu::Texture destination) { @@ -563,7 +567,7 @@ class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase { // 1. Create and clear a D3D11 texture // 2. Copy the wrapped texture to another dawn texture // 3. Readback the copied texture and ensure the color matches the original clear color. -TEST_P(D3D12SharedHandleUsageTests, ClearInD3D11CopyAndReadbackInD3D12) { +TEST_P(D3DSharedHandleUsageTests, ClearInD3D11CopyAndReadbackInD3D) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); const wgpu::Color clearColor{1.0f, 1.0f, 0.0f, 1.0f}; @@ -591,7 +595,7 @@ TEST_P(D3D12SharedHandleUsageTests, ClearInD3D11CopyAndReadbackInD3D12) { // 1. Create and clear a D3D11 texture // 2. Readback the wrapped texture and ensure the color matches the original clear color. -TEST_P(D3D12SharedHandleUsageTests, ClearInD3D11ReadbackInD3D12) { +TEST_P(D3DSharedHandleUsageTests, ClearInD3D11ReadbackInD3D) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); const wgpu::Color clearColor{1.0f, 1.0f, 0.0f, 1.0f}; @@ -616,7 +620,7 @@ TEST_P(D3D12SharedHandleUsageTests, ClearInD3D11ReadbackInD3D12) { // 1. Create and clear a D3D11 texture // 2. Wrap it in a Dawn texture and clear it to a different color // 3. Readback the texture with D3D11 and ensure we receive the color we cleared with Dawn. -TEST_P(D3D12SharedHandleUsageTests, ClearInD3D12ReadbackInD3D11) { +TEST_P(D3DSharedHandleUsageTests, ClearInD3DReadbackInD3D11) { // TODO(crbug.com/dawn/735): This test appears to hang for // D3D12_Microsoft_Basic_Render_Driver_CPU when validation is enabled. DAWN_SUPPRESS_TEST_IF(IsD3D12() && IsWARP() && IsBackendValidationEnabled()); @@ -631,24 +635,24 @@ TEST_P(D3D12SharedHandleUsageTests, ClearInD3D12ReadbackInD3D11) { &d3d11Texture, &externalImage, /*isInitialized=*/true); ASSERT_NE(dawnTexture.Get(), nullptr); - const wgpu::Color d3d12ClearColor{0.0f, 0.0f, 1.0f, 1.0f}; - ClearImage(dawnTexture, d3d12ClearColor, device); + const wgpu::Color d3dClearColor{0.0f, 0.0f, 1.0f, 1.0f}; + ClearImage(dawnTexture, d3dClearColor, device); dawn::native::d3d::ExternalImageDXGIFenceDescriptor signalFence; externalImage->EndAccess(dawnTexture.Get(), &signalFence); dawnTexture.Destroy(); - // Now that Dawn (via D3D12) has finished writing to the texture, we should be + // Now that Dawn (via D3D) has finished writing to the texture, we should be // able to read it back by copying it to a staging texture and verifying the // color matches the D3D12 clear color. - ExpectPixelRGBA8EQ(d3d11Texture.Get(), d3d12ClearColor, &signalFence); + ExpectPixelRGBA8EQ(d3d11Texture.Get(), d3dClearColor, &signalFence); } // 1. Create and clear a D3D11 texture // 2. Wrap it in a Dawn texture and clear the texture to two different colors. // 3. Readback the texture with D3D11. // 4. Verify the readback color was the final color cleared. -TEST_P(D3D12SharedHandleUsageTests, ClearTwiceInD3D12ReadbackInD3D11) { +TEST_P(D3DSharedHandleUsageTests, ClearTwiceInD3DReadbackInD3D11) { // TODO(crbug.com/dawn/735): This test appears to hang for // D3D12_Microsoft_Basic_Render_Driver_CPU when validation is enabled. DAWN_SUPPRESS_TEST_IF(IsD3D12() && IsWARP() && IsBackendValidationEnabled()); @@ -663,26 +667,26 @@ TEST_P(D3D12SharedHandleUsageTests, ClearTwiceInD3D12ReadbackInD3D11) { &d3d11Texture, &externalImage, /*isInitialized=*/true); ASSERT_NE(dawnTexture.Get(), nullptr); - const wgpu::Color d3d12ClearColor1{0.0f, 0.0f, 1.0f, 1.0f}; - ClearImage(dawnTexture, d3d12ClearColor1, device); + const wgpu::Color d3dClearColor1{0.0f, 0.0f, 1.0f, 1.0f}; + ClearImage(dawnTexture, d3dClearColor1, device); - const wgpu::Color d3d12ClearColor2{0.0f, 1.0f, 1.0f, 1.0f}; - ClearImage(dawnTexture, d3d12ClearColor2, device); + const wgpu::Color d3dClearColor2{0.0f, 1.0f, 1.0f, 1.0f}; + ClearImage(dawnTexture, d3dClearColor2, device); dawn::native::d3d::ExternalImageDXGIFenceDescriptor signalFence; externalImage->EndAccess(dawnTexture.Get(), &signalFence); dawnTexture.Destroy(); - // Now that Dawn (via D3D12) has finished writing to the texture, we should be + // Now that Dawn (via D3D) has finished writing to the texture, we should be // able to read it back by copying it to a staging texture and verifying the // color matches the last D3D12 clear color. - ExpectPixelRGBA8EQ(d3d11Texture.Get(), d3d12ClearColor2, &signalFence); + ExpectPixelRGBA8EQ(d3d11Texture.Get(), d3dClearColor2, &signalFence); } // 1. Create and clear a D3D11 texture with clearColor // 2. Import the texture with isInitialized = false // 3. Verify clearColor is not visible in wrapped texture -TEST_P(D3D12SharedHandleUsageTests, UninitializedTextureIsCleared) { +TEST_P(D3DSharedHandleUsageTests, UninitializedTextureIsCleared) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); const wgpu::Color clearColor{1.0f, 0.0f, 0.0f, 1.0f}; @@ -705,7 +709,7 @@ TEST_P(D3D12SharedHandleUsageTests, UninitializedTextureIsCleared) { // 1. Create an external image from the DX11 texture. // 2. Produce two Dawn textures from the external image. // 3. Clear each Dawn texture and verify the texture was cleared to a unique color. -TEST_P(D3D12SharedHandleUsageTests, ReuseExternalImage) { +TEST_P(D3DSharedHandleUsageTests, ReuseExternalImage) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); // Create the first Dawn texture then clear it to red. @@ -752,7 +756,7 @@ TEST_P(D3D12SharedHandleUsageTests, ReuseExternalImage) { texture.Destroy(); } -TEST_P(D3D12SharedHandleUsageTests, ConcurrentExternalImageReadAccess) { +TEST_P(D3DSharedHandleUsageTests, ConcurrentExternalImageReadAccess) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::Device device2 = CreateDevice(); @@ -905,7 +909,7 @@ TEST_P(D3D12SharedHandleUsageTests, ConcurrentExternalImageReadAccess) { } // Produce a new texture with a usage not specified in the external image. -TEST_P(D3D12SharedHandleUsageTests, ExternalImageUsage) { +TEST_P(D3DSharedHandleUsageTests, ExternalImageUsage) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::Texture texture; @@ -934,7 +938,7 @@ TEST_P(D3D12SharedHandleUsageTests, ExternalImageUsage) { } // Verify external image cannot be used after its creating device is destroyed. -TEST_P(D3D12SharedHandleUsageTests, InvalidateExternalImageOnDestroyDevice) { +TEST_P(D3DSharedHandleUsageTests, InvalidateExternalImageOnDestroyDevice) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::Texture texture; @@ -963,7 +967,7 @@ TEST_P(D3D12SharedHandleUsageTests, InvalidateExternalImageOnDestroyDevice) { } // Verify external image cannot be created after the target device is destroyed. -TEST_P(D3D12SharedHandleUsageTests, DisallowExternalImageAfterDestroyDevice) { +TEST_P(D3DSharedHandleUsageTests, DisallowExternalImageAfterDestroyDevice) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::Texture texture; @@ -981,7 +985,7 @@ TEST_P(D3D12SharedHandleUsageTests, DisallowExternalImageAfterDestroyDevice) { // Verify there is no error generated when we destroy an external image with CommandRecordingContext // open. -TEST_P(D3D12SharedHandleUsageTests, CallWriteBufferBeforeDestroyingExternalImage) { +TEST_P(D3DSharedHandleUsageTests, CallWriteBufferBeforeDestroyingExternalImage) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::Texture texture; @@ -1006,7 +1010,7 @@ TEST_P(D3D12SharedHandleUsageTests, CallWriteBufferBeforeDestroyingExternalImage // Test that texture descriptor view formats are passed to the backend for wrapped external // textures, and that contents may be reinterpreted as sRGB. -TEST_P(D3D12SharedHandleUsageTests, SRGBReinterpretation) { +TEST_P(D3DSharedHandleUsageTests, SRGBReinterpretation) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); wgpu::Texture texture; @@ -1045,7 +1049,7 @@ TEST_P(D3D12SharedHandleUsageTests, SRGBReinterpretation) { utils::RGBA8(247, 125, 105, 255), texture, 0, 0); } -class D3D12SharedHandleMultithreadTests : public D3D12SharedHandleUsageTests { +class D3DSharedHandleMultithreadTests : public D3DSharedHandleUsageTests { protected: std::vector GetRequiredFeatures() override { std::vector features; @@ -1057,14 +1061,14 @@ class D3D12SharedHandleMultithreadTests : public D3D12SharedHandleUsageTests { } void SetUp() override { - D3D12SharedHandleUsageTests::SetUp(); + D3DSharedHandleUsageTests::SetUp(); // TODO(crbug.com/dawn/1678): DawnWire doesn't support thread safe API yet. DAWN_TEST_UNSUPPORTED_IF(UsesWire()); } }; // Test the destroy device before destroying the external image won't cause deadlock. -TEST_P(D3D12SharedHandleMultithreadTests, DestroyDeviceBeforeImageNoDeadLock) { +TEST_P(D3DSharedHandleMultithreadTests, DestroyDeviceBeforeImageNoDeadLock) { wgpu::Texture texture; ComPtr d3d11Texture; std::unique_ptr externalImage; @@ -1084,7 +1088,7 @@ TEST_P(D3D12SharedHandleMultithreadTests, DestroyDeviceBeforeImageNoDeadLock) { // Test that using the external image and destroying the device simultaneously on different threads // won't race. -TEST_P(D3D12SharedHandleMultithreadTests, DestroyDeviceAndUseImageInParallel) { +TEST_P(D3DSharedHandleMultithreadTests, DestroyDeviceAndUseImageInParallel) { wgpu::Texture texture; ComPtr d3d11Texture; std::unique_ptr externalImage; @@ -1112,13 +1116,13 @@ TEST_P(D3D12SharedHandleMultithreadTests, DestroyDeviceAndUseImageInParallel) { // 1. Create and clear a D3D11 texture // 2. On 2nd thread: Wrap it in a Dawn texture and clear it to a different color // 3. Readback the texture with D3D11 and ensure we receive the color we cleared with Dawn. -TEST_P(D3D12SharedHandleMultithreadTests, ClearInD3D12ReadbackInD3D11_TwoThreads) { +TEST_P(D3DSharedHandleMultithreadTests, ClearInD3D12ReadbackInD3D11_TwoThreads) { // TODO(crbug.com/dawn/735): This test appears to hang for // D3D12_Microsoft_Basic_Render_Driver_CPU when validation is enabled. DAWN_SUPPRESS_TEST_IF(IsD3D12() && IsWARP() && IsBackendValidationEnabled()); const wgpu::Color d3d11ClearColor{1.0f, 1.0f, 0.0f, 1.0f}; - const wgpu::Color d3d12ClearColor{0.0f, 0.0f, 1.0f, 1.0f}; + const wgpu::Color d3dClearColor{0.0f, 0.0f, 1.0f, 1.0f}; constexpr uint64_t kD3D11FenceSignalValue = 1; @@ -1129,9 +1133,9 @@ TEST_P(D3D12SharedHandleMultithreadTests, ClearInD3D12ReadbackInD3D11_TwoThreads CreateSharedD3D11Texture(baseD3dDescriptor, &d3d11Texture, &d3d11Fence, &sharedHandle, &fenceSharedHandle); - dawn::native::d3d::ExternalImageDXGIFenceDescriptor d3d12SignalFence; + dawn::native::d3d::ExternalImageDXGIFenceDescriptor d3dSignalFence; - std::thread d3d12Thread([=, &d3d12SignalFence] { + std::thread d3dThread([=, &d3dSignalFence] { wgpu::Texture dawnTexture; std::unique_ptr externalImage; WaitAndWrapD3D11Texture(baseDawnDescriptor, sharedHandle, fenceSharedHandle, @@ -1144,9 +1148,9 @@ TEST_P(D3D12SharedHandleMultithreadTests, ClearInD3D12ReadbackInD3D11_TwoThreads d3d11ClearColor.b * 255, d3d11ClearColor.a * 255), dawnTexture, 0, 0); - ClearImage(dawnTexture, d3d12ClearColor, device); + ClearImage(dawnTexture, d3dClearColor, device); - externalImage->EndAccess(dawnTexture.Get(), &d3d12SignalFence); + externalImage->EndAccess(dawnTexture.Get(), &d3dSignalFence); dawnTexture.Destroy(); }); @@ -1154,11 +1158,11 @@ TEST_P(D3D12SharedHandleMultithreadTests, ClearInD3D12ReadbackInD3D11_TwoThreads ClearD3D11Texture(d3d11ClearColor, d3d11Texture.Get(), d3d11Fence.Get(), /*fenceSignalValue=*/kD3D11FenceSignalValue); - d3d12Thread.join(); + d3dThread.join(); // Now that Dawn (via D3D12) has finished writing to the texture, we should be // able to read it back by copying it to a staging texture and verifying the // color matches the D3D12 clear color. - ExpectPixelRGBA8EQ(d3d11Texture.Get(), d3d12ClearColor, &d3d12SignalFence); + ExpectPixelRGBA8EQ(d3d11Texture.Get(), d3dClearColor, &d3dSignalFence); if (sharedHandle != nullptr) { ::CloseHandle(sharedHandle); @@ -1169,6 +1173,6 @@ TEST_P(D3D12SharedHandleMultithreadTests, ClearInD3D12ReadbackInD3D11_TwoThreads } } -DAWN_INSTANTIATE_TEST(D3D12SharedHandleValidation, D3D12Backend()); -DAWN_INSTANTIATE_TEST(D3D12SharedHandleUsageTests, D3D12Backend()); -DAWN_INSTANTIATE_TEST(D3D12SharedHandleMultithreadTests, D3D12Backend()); +DAWN_INSTANTIATE_TEST(D3DSharedHandleValidation, D3D11Backend(), D3D12Backend()); +DAWN_INSTANTIATE_TEST(D3DSharedHandleUsageTests, D3D11Backend(), D3D12Backend()); +DAWN_INSTANTIATE_TEST(D3DSharedHandleMultithreadTests, D3D11Backend(), D3D12Backend()); diff --git a/src/dawn/tests/end2end/VideoViewsTests_win.cpp b/src/dawn/tests/end2end/VideoViewsTests_win.cpp index c5e983c84c..cf06ce4ff8 100644 --- a/src/dawn/tests/end2end/VideoViewsTests_win.cpp +++ b/src/dawn/tests/end2end/VideoViewsTests_win.cpp @@ -44,21 +44,13 @@ class VideoViewsTestBackendWin : public VideoViewsTestBackend { mWGPUDevice = device; // Create the D3D11 device/contexts that will be used in subsequent tests - ComPtr d3d12Device = dawn::native::d3d12::GetD3D12Device(device); - - const LUID adapterLuid = d3d12Device->GetAdapterLuid(); - - ComPtr dxgiFactory; - HRESULT hr = ::CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgiFactory)); - ASSERT_EQ(hr, S_OK); - - ComPtr dxgiAdapter; - hr = dxgiFactory->EnumAdapterByLuid(adapterLuid, IID_PPV_ARGS(&dxgiAdapter)); - ASSERT_EQ(hr, S_OK); + ComPtr dxgiAdapter = + dawn::native::d3d::GetDXGIAdapter(wgpuDeviceGetAdapter(device)); ComPtr d3d11Device; D3D_FEATURE_LEVEL d3dFeatureLevel; ComPtr d3d11DeviceContext; + HRESULT hr; hr = ::D3D11CreateDevice(dxgiAdapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &d3d11Device, &d3dFeatureLevel, &d3d11DeviceContext);