d3d11: support external image
This CL implements external image for d3d11 backend and enables related tests. Bug: dawn:1705 Bug: dawn:1724 Change-Id: Ib95e024fdc1837e3edb198dcf9255ebde8fa9fe7 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131201 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Peng Huang <penghuang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
5e7807f02b
commit
49db496a51
|
@ -29,8 +29,6 @@ namespace dawn::native::d3d12 {
|
|||
|
||||
class Device;
|
||||
|
||||
DAWN_NATIVE_EXPORT Microsoft::WRL::ComPtr<ID3D12Device> GetD3D12Device(WGPUDevice device);
|
||||
|
||||
enum MemorySegment {
|
||||
Local,
|
||||
NonLocal,
|
||||
|
|
|
@ -28,6 +28,8 @@ namespace dawn::native::d3d {
|
|||
|
||||
class ExternalImageDXGIImpl;
|
||||
|
||||
DAWN_NATIVE_EXPORT Microsoft::WRL::ComPtr<IDXGIAdapter> GetDXGIAdapter(WGPUAdapter adapter);
|
||||
|
||||
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
|
||||
AdapterDiscoveryOptions(WGPUBackendType type, Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -21,12 +21,18 @@
|
|||
#include <utility>
|
||||
|
||||
#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<IDXGIAdapter> GetDXGIAdapter(WGPUAdapter adapter) {
|
||||
return ToBackend(FromAPI(adapter)->GetPhysicalDevice())->GetHardwareAdapter();
|
||||
}
|
||||
|
||||
AdapterDiscoveryOptions::AdapterDiscoveryOptions(WGPUBackendType type,
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter> adapter)
|
||||
: AdapterDiscoveryOptionsBase(type), dxgiAdapter(std::move(adapter)) {}
|
||||
|
|
|
@ -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<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
|
||||
const Surface* surface) const {
|
||||
|
@ -54,4 +73,18 @@ ComPtr<IDxcValidator> Device::GetDxcValidator() const {
|
|||
return ToBackend(GetPhysicalDevice())->GetBackend()->GetDxcValidator();
|
||||
}
|
||||
|
||||
HANDLE Device::GetFenceHandle() const {
|
||||
return mFenceHandle;
|
||||
}
|
||||
|
||||
std::unique_ptr<ExternalImageDXGIImpl> Device::CreateExternalImageDXGIImpl(
|
||||
const ExternalImageDescriptorDXGISharedHandle* descriptor) {
|
||||
std::unique_ptr<ExternalImageDXGIImpl> externalImage;
|
||||
if (!ConsumedError(CreateExternalImageDXGIImplImpl(descriptor), &externalImage)) {
|
||||
mExternalImageList.Append(externalImage.get());
|
||||
return externalImage;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace dawn::native::d3d
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define SRC_DAWN_NATIVE_D3D_DEVICED3D_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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<IDxcCompiler> GetDxcCompiler() const;
|
||||
ComPtr<IDxcValidator> GetDxcValidator() const;
|
||||
|
||||
virtual std::unique_ptr<ExternalImageDXGIImpl> CreateExternalImageDXGIImpl(
|
||||
HANDLE GetFenceHandle() const;
|
||||
|
||||
std::unique_ptr<ExternalImageDXGIImpl> CreateExternalImageDXGIImpl(
|
||||
const ExternalImageDescriptorDXGISharedHandle* descriptor);
|
||||
|
||||
virtual ResultOrError<Ref<Fence>> CreateFence(
|
||||
const ExternalImageDXGIFenceDescriptor* descriptor) = 0;
|
||||
virtual Ref<TextureBase> CreateD3DExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized) = 0;
|
||||
|
||||
protected:
|
||||
void DestroyImpl() override;
|
||||
|
||||
virtual ResultOrError<std::unique_ptr<ExternalImageDXGIImpl>> CreateExternalImageDXGIImplImpl(
|
||||
const ExternalImageDescriptorDXGISharedHandle* descriptor) = 0;
|
||||
|
||||
HANDLE mFenceHandle = nullptr;
|
||||
|
||||
private:
|
||||
// List of external image resources opened using this device.
|
||||
LinkedList<d3d::ExternalImageDXGIImpl> mExternalImageList;
|
||||
};
|
||||
|
||||
} // namespace dawn::native::d3d
|
||||
|
|
|
@ -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<IUnknown> 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<WGPUTextureUsageFlags>(mUsage))) {
|
||||
dawn::ErrorLog() << "Texture usage is not valid for external image";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ASSERT(mBackendDevice != nullptr);
|
||||
|
||||
TextureDescriptor textureDescriptor = {};
|
||||
textureDescriptor.usage = static_cast<wgpu::TextureUsage>(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<uint32_t>(mViewFormats.size());
|
||||
|
||||
DawnTextureInternalUsageDescriptor internalDesc = {};
|
||||
if (mUsageInternal != wgpu::TextureUsage::None) {
|
||||
textureDescriptor.nextInChain = &internalDesc;
|
||||
internalDesc.internalUsage = mUsageInternal;
|
||||
}
|
||||
|
||||
std::vector<Ref<Fence>> waitFences;
|
||||
for (const d3d::ExternalImageDXGIFenceDescriptor& fenceDescriptor : descriptor->waitFences) {
|
||||
Ref<Fence> 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<TextureBase> 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<uint64_t>(fenceValue);
|
||||
}
|
||||
|
||||
} // namespace dawn::native::d3d
|
||||
|
|
|
@ -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<ExternalImageDXGIImpl> {
|
||||
public:
|
||||
ExternalImageDXGIImpl(Device* backendDevice, const TextureDescriptor* textureDescriptor);
|
||||
virtual ~ExternalImageDXGIImpl();
|
||||
ExternalImageDXGIImpl(Device* backendDevice,
|
||||
ComPtr<IUnknown> 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<DeviceBase> mBackendDevice;
|
||||
|
||||
ComPtr<IUnknown> mD3DResource;
|
||||
wgpu::TextureUsage mUsage;
|
||||
wgpu::TextureUsage mUsageInternal = wgpu::TextureUsage::None;
|
||||
wgpu::TextureDimension mDimension;
|
||||
|
|
|
@ -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 <utility>
|
||||
|
||||
#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
|
|
@ -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_
|
|
@ -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 <typename T>
|
||||
|
|
|
@ -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
|
|
@ -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<ExecutionSerial> EndAccess() = 0;
|
||||
|
||||
protected:
|
||||
using TextureBase::TextureBase;
|
||||
~Texture() override;
|
||||
};
|
||||
|
||||
} // namespace dawn::native::d3d
|
||||
|
||||
#endif // SRC_DAWN_NATIVE_D3D_TEXTURED3D_H_
|
|
@ -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<d3d::ExternalImageDXGIImpl> Device::CreateExternalImageDXGIImpl(
|
||||
ResultOrError<Ref<d3d::Fence>> Device::CreateFence(
|
||||
const d3d::ExternalImageDXGIFenceDescriptor* descriptor) {
|
||||
return Fence::CreateFromHandle(mD3d11Device5.Get(), descriptor->fenceHandle,
|
||||
descriptor->fenceValue);
|
||||
}
|
||||
|
||||
ResultOrError<std::unique_ptr<d3d::ExternalImageDXGIImpl>> 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<ID3D11Resource> 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<d3d::ExternalImageDXGIImpl>(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<TextureBase> Device::CreateD3DExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized) {
|
||||
Ref<Texture> dawnTexture;
|
||||
if (ConsumedError(
|
||||
Texture::CreateExternalImage(this, descriptor, std::move(d3dTexture),
|
||||
std::move(waitFences), isSwapChainTexture, isInitialized),
|
||||
&dawnTexture)) {
|
||||
return nullptr;
|
||||
}
|
||||
return {dawnTexture};
|
||||
}
|
||||
|
||||
} // namespace dawn::native::d3d11
|
||||
|
|
|
@ -51,12 +51,11 @@ class Device final : public d3d::Device {
|
|||
|
||||
void ReferenceUntilUnused(ComPtr<IUnknown> object);
|
||||
MaybeError ExecutePendingCommandContext();
|
||||
HANDLE GetFenceHandle() const;
|
||||
Ref<TextureBase> CreateD3D11ExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<ID3D11Resource> d3d11Texture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
Ref<TextureBase> CreateD3DExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized);
|
||||
bool isInitialized) override;
|
||||
|
||||
ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer(
|
||||
CommandEncoder* encoder,
|
||||
|
@ -79,7 +78,9 @@ class Device final : public d3d::Device {
|
|||
uint64_t GetBufferCopyOffsetAlignmentForDepthStencil() const override;
|
||||
void SetLabelImpl() override;
|
||||
|
||||
std::unique_ptr<d3d::ExternalImageDXGIImpl> CreateExternalImageDXGIImpl(
|
||||
ResultOrError<Ref<d3d::Fence>> CreateFence(
|
||||
const d3d::ExternalImageDXGIFenceDescriptor* descriptor) override;
|
||||
ResultOrError<std::unique_ptr<d3d::ExternalImageDXGIImpl>> CreateExternalImageDXGIImplImpl(
|
||||
const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) override;
|
||||
|
||||
private:
|
||||
|
@ -127,7 +128,6 @@ class Device final : public d3d::Device {
|
|||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||
|
||||
ComPtr<ID3D11Fence> mFence;
|
||||
HANDLE mFenceHandle = nullptr;
|
||||
HANDLE mFenceEvent = nullptr;
|
||||
|
||||
ComPtr<ID3D11Device> mD3d11Device;
|
||||
|
|
|
@ -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 <utility>
|
||||
|
||||
#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<Ref<Fence>> 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<ID3D11Fence> 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<ID3D11Fence> 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
|
|
@ -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<Ref<Fence>> CreateFromHandle(ID3D11Device5* device,
|
||||
HANDLE unownedHandle,
|
||||
UINT64 fenceValue);
|
||||
|
||||
ID3D11Fence* GetD3D11Fence() const;
|
||||
|
||||
private:
|
||||
using Base = d3d::Fence;
|
||||
|
||||
Fence(ComPtr<ID3D11Fence> d3d11Fence, UINT64 fenceValue, HANDLE sharedHandle);
|
||||
~Fence() override;
|
||||
|
||||
ComPtr<ID3D11Fence> mD3D11Fence;
|
||||
};
|
||||
|
||||
} // namespace dawn::native::d3d11
|
||||
|
||||
#endif // SRC_DAWN_NATIVE_D3D11_FENCED3D11_H_
|
|
@ -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<ID3D11Texture2D> 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<Ref<Texture>> Texture::Create(Device* device, const TextureDescriptor* descriptor) {
|
||||
Ref<Texture> texture = AcquireRef(
|
||||
|
@ -89,6 +131,31 @@ ResultOrError<Ref<Texture>> Texture::CreateStaging(Device* device,
|
|||
return std::move(texture);
|
||||
}
|
||||
|
||||
// static
|
||||
ResultOrError<Ref<Texture>> Texture::CreateExternalImage(Device* device,
|
||||
const TextureDescriptor* descriptor,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized) {
|
||||
Ref<Texture> 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 <typename T>
|
||||
T Texture::GetD3D11TextureDesc() const {
|
||||
T desc;
|
||||
|
@ -182,11 +249,30 @@ MaybeError Texture::InitializeAsSwapChainTexture(ComPtr<ID3D11Resource> d3d11Tex
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError Texture::InitializeAsExternalTexture(ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture) {
|
||||
ComPtr<ID3D11Resource> d3d11Texture;
|
||||
DAWN_TRY(CheckHRESULT(d3dTexture.As(&d3d11Texture), "Query ID3D11Resource from IUnknown"));
|
||||
|
||||
CommandRecordingContext* commandContext = ToBackend(GetDevice())->GetPendingCommandContext();
|
||||
ID3D11DeviceContext4* d3d11DeviceContext4 = commandContext->GetD3D11DeviceContext4();
|
||||
for (Ref<d3d::Fence>& fence : waitFences) {
|
||||
DAWN_TRY(CheckHRESULT(
|
||||
d3d11DeviceContext4->Wait(static_cast<Fence*>(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<ExecutionSerial> Texture::EndAccess() {
|
||||
// TODO(dawn:1705): submit pending commands if deferred context is used.
|
||||
return GetDevice()->GetLastSubmittedCommandSerial();
|
||||
}
|
||||
|
||||
// static
|
||||
Ref<TextureView> TextureView::Create(TextureBase* texture,
|
||||
const TextureViewDescriptor* descriptor) {
|
||||
|
|
|
@ -15,29 +15,44 @@
|
|||
#ifndef SRC_DAWN_NATIVE_D3D11_TEXTURED3D11_H_
|
||||
#define SRC_DAWN_NATIVE_D3D11_TEXTURED3D11_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#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<Ref<Texture>> Create(Device* device, const TextureDescriptor* descriptor);
|
||||
static ResultOrError<Ref<Texture>> Create(Device* device,
|
||||
const TextureDescriptor* descriptor,
|
||||
ComPtr<ID3D11Resource> d3d11Texture);
|
||||
|
||||
static ResultOrError<Ref<Texture>> CreateExternalImage(Device* device,
|
||||
const TextureDescriptor* descriptor,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> 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<ExecutionSerial> EndAccess() override;
|
||||
|
||||
private:
|
||||
using Base = d3d::Texture;
|
||||
|
||||
static ResultOrError<Ref<Texture>> CreateStaging(Device* device,
|
||||
const TextureDescriptor* descriptor);
|
||||
|
||||
|
@ -82,7 +101,9 @@ class Texture final : public TextureBase {
|
|||
|
||||
MaybeError InitializeAsInternalTexture();
|
||||
MaybeError InitializeAsSwapChainTexture(ComPtr<ID3D11Resource> d3d11Texture);
|
||||
|
||||
MaybeError InitializeAsExternalTexture(ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture);
|
||||
void SetLabelHelper(const char* prefix);
|
||||
|
||||
// Dawn API
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
|
||||
namespace dawn::native::d3d12 {
|
||||
|
||||
ComPtr<ID3D12Device> GetD3D12Device(WGPUDevice device) {
|
||||
return ToBackend(FromAPI(device))->GetD3D12Device();
|
||||
}
|
||||
|
||||
uint64_t SetExternalMemoryReservation(WGPUDevice device,
|
||||
uint64_t requestedReservationSize,
|
||||
MemorySegment memorySegment) {
|
||||
|
|
|
@ -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<ID3D12CommandSignature> Device::GetDispatchIndirectSignature() const {
|
||||
return mDispatchIndirectSignature;
|
||||
}
|
||||
|
@ -545,61 +533,54 @@ ResultOrError<ResourceHeapAllocation> Device::AllocateMemory(
|
|||
forceAllocateAsCommittedResource);
|
||||
}
|
||||
|
||||
std::unique_ptr<d3d::ExternalImageDXGIImpl> Device::CreateExternalImageDXGIImpl(
|
||||
ResultOrError<Ref<d3d::Fence>> Device::CreateFence(
|
||||
const d3d::ExternalImageDXGIFenceDescriptor* descriptor) {
|
||||
return Fence::CreateFromHandle(mD3d12Device.Get(), descriptor->fenceHandle,
|
||||
descriptor->fenceValue);
|
||||
}
|
||||
|
||||
ResultOrError<std::unique_ptr<d3d::ExternalImageDXGIImpl>> 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<ID3D12Resource> 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),
|
||||
DAWN_TRY_CONTEXT(d3d::ValidateTextureDescriptorCanBeWrapped(textureDescriptor),
|
||||
"validating that a D3D12 external image can be wrapped with %s",
|
||||
textureDescriptor)) {
|
||||
return nullptr;
|
||||
}
|
||||
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<ExternalImageDXGIImpl>(this, std::move(d3d12Resource), textureDescriptor);
|
||||
mExternalImageList.Append(impl.get());
|
||||
return impl;
|
||||
return std::make_unique<d3d::ExternalImageDXGIImpl>(this, std::move(d3d12Resource),
|
||||
textureDescriptor);
|
||||
}
|
||||
|
||||
Ref<TextureBase> Device::CreateD3D12ExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<ID3D12Resource> d3d12Texture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
Ref<TextureBase> Device::CreateD3DExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized) {
|
||||
Ref<Texture> 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;
|
||||
|
||||
|
|
|
@ -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<ID3D12CommandQueue> GetCommandQueue() const;
|
||||
ID3D12SharingContract* GetSharingContract() const;
|
||||
HANDLE GetFenceHandle() const;
|
||||
|
||||
ComPtr<ID3D12CommandSignature> GetDispatchIndirectSignature() const;
|
||||
ComPtr<ID3D12CommandSignature> GetDrawIndirectSignature() const;
|
||||
|
@ -137,14 +135,16 @@ class Device final : public d3d::Device {
|
|||
|
||||
StagingDescriptorAllocator* GetDepthStencilViewAllocator() const;
|
||||
|
||||
std::unique_ptr<d3d::ExternalImageDXGIImpl> CreateExternalImageDXGIImpl(
|
||||
ResultOrError<Ref<d3d::Fence>> CreateFence(
|
||||
const d3d::ExternalImageDXGIFenceDescriptor* descriptor) override;
|
||||
ResultOrError<std::unique_ptr<d3d::ExternalImageDXGIImpl>> CreateExternalImageDXGIImplImpl(
|
||||
const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) override;
|
||||
|
||||
Ref<TextureBase> CreateD3D12ExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<ID3D12Resource> d3d12Texture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
Ref<TextureBase> CreateD3DExternalTexture(const TextureDescriptor* descriptor,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized);
|
||||
bool isInitialized) override;
|
||||
|
||||
uint32_t GetOptimalBytesPerRowAlignment() const override;
|
||||
uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
|
||||
|
@ -218,7 +218,6 @@ class Device final : public d3d::Device {
|
|||
|
||||
ComPtr<ID3D12Fence> mFence;
|
||||
HANDLE mFenceEvent = nullptr;
|
||||
HANDLE mFenceHandle = nullptr;
|
||||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||
|
||||
ComPtr<ID3D12Device> 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<d3d::ExternalImageDXGIImpl> mExternalImageList;
|
||||
};
|
||||
|
||||
} // namespace dawn::native::d3d12
|
||||
|
|
|
@ -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 <utility>
|
||||
#include <vector>
|
||||
|
||||
#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<ID3D12Resource> 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<WGPUTextureUsageFlags>(mUsage))) {
|
||||
dawn::ErrorLog() << "Texture usage is not valid for external image";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ASSERT(mBackendDevice != nullptr);
|
||||
|
||||
TextureDescriptor textureDescriptor = {};
|
||||
textureDescriptor.usage = static_cast<wgpu::TextureUsage>(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<uint32_t>(mViewFormats.size());
|
||||
|
||||
DawnTextureInternalUsageDescriptor internalDesc = {};
|
||||
if (mUsageInternal != wgpu::TextureUsage::None) {
|
||||
textureDescriptor.nextInChain = &internalDesc;
|
||||
internalDesc.internalUsage = mUsageInternal;
|
||||
internalDesc.sType = wgpu::SType::DawnTextureInternalUsageDescriptor;
|
||||
}
|
||||
|
||||
std::vector<Ref<Fence>> 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> 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<TextureBase> 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<uint64_t>(fenceValue);
|
||||
}
|
||||
|
||||
} // namespace dawn::native::d3d12
|
|
@ -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 <wrl/client.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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<ID3D12Resource> 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<ID3D12Resource> mD3D12Resource;
|
||||
};
|
||||
|
||||
} // namespace dawn::native::d3d12
|
||||
|
||||
#endif // SRC_DAWN_NATIVE_D3D12_EXTERNALIMAGEDXGIIMPLD3D12_H_
|
|
@ -42,20 +42,12 @@ ResultOrError<Ref<Fence>> Fence::CreateFromHandle(ID3D12Device* device,
|
|||
}
|
||||
|
||||
Fence::Fence(ComPtr<ID3D12Fence> 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
|
||||
|
|
|
@ -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<Ref<Fence>> CreateFromHandle(ID3D12Device* device,
|
||||
HANDLE unownedHandle,
|
||||
UINT64 fenceValue);
|
||||
|
||||
ID3D12Fence* GetD3D12Fence() const;
|
||||
UINT64 GetFenceValue() const;
|
||||
|
||||
private:
|
||||
using Base = d3d::Fence;
|
||||
|
||||
Fence(ComPtr<ID3D12Fence> d3d12Fence, UINT64 fenceValue, HANDLE sharedHandle);
|
||||
~Fence() override;
|
||||
|
||||
ComPtr<ID3D12Fence> mD3D12Fence;
|
||||
const UINT64 mFenceValue;
|
||||
const HANDLE mSharedHandle;
|
||||
};
|
||||
|
||||
} // namespace dawn::native::d3d12
|
||||
|
|
|
@ -112,24 +112,7 @@ 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,
|
||||
MaybeError ValidateTextureCanBeWrapped(ID3D12Resource* d3d12Resource,
|
||||
const TextureDescriptor* dawnDescriptor) {
|
||||
const D3D12_RESOURCE_DESC d3dDescriptor = d3d12Resource->GetDesc();
|
||||
DAWN_INVALID_IF(
|
||||
|
@ -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<Ref<Texture>> Texture::Create(Device* device, const TextureDescrip
|
|||
// static
|
||||
ResultOrError<Ref<Texture>> Texture::CreateExternalImage(Device* device,
|
||||
const TextureDescriptor* descriptor,
|
||||
ComPtr<ID3D12Resource> d3d12Texture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized) {
|
||||
Ref<Texture> 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<Ref<Texture>> Texture::Create(Device* device,
|
|||
return std::move(dawnTexture);
|
||||
}
|
||||
|
||||
MaybeError Texture::InitializeAsExternalTexture(ComPtr<ID3D12Resource> d3d12Texture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
MaybeError Texture::InitializeAsExternalTexture(ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture) {
|
||||
ComPtr<ID3D12Resource> 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<ID3D12Resource> 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>& fence : mWaitFences) {
|
||||
DAWN_TRY(CheckHRESULT(device->GetCommandQueue()->Wait(fence->GetD3D12Fence(),
|
||||
fence->GetFenceValue()),
|
||||
for (Ref<d3d::Fence>& fence : mWaitFences) {
|
||||
DAWN_TRY(CheckHRESULT(
|
||||
device->GetCommandQueue()->Wait(
|
||||
static_cast<Fence*>(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*>(fence.Get())->GetD3D12Fence());
|
||||
}
|
||||
mWaitFences.clear();
|
||||
return {};
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <vector>
|
||||
|
||||
#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,
|
||||
MaybeError ValidateTextureCanBeWrapped(ID3D12Resource* d3d12Resource,
|
||||
const TextureDescriptor* descriptor);
|
||||
MaybeError ValidateTextureDescriptorCanBeWrapped(const TextureDescriptor* descriptor);
|
||||
MaybeError ValidateD3D12VideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat);
|
||||
MaybeError ValidateVideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat);
|
||||
|
||||
class Texture final : public TextureBase {
|
||||
class Texture final : public d3d::Texture {
|
||||
public:
|
||||
static ResultOrError<Ref<Texture>> Create(Device* device, const TextureDescriptor* descriptor);
|
||||
static ResultOrError<Ref<Texture>> CreateExternalImage(Device* device,
|
||||
const TextureDescriptor* descriptor,
|
||||
ComPtr<ID3D12Resource> d3d12Texture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture,
|
||||
bool isInitialized);
|
||||
static ResultOrError<Ref<Texture>> 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<ExecutionSerial> EndAccess();
|
||||
ResultOrError<ExecutionSerial> 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<ID3D12Resource> d3d12Texture,
|
||||
std::vector<Ref<Fence>> waitFences,
|
||||
MaybeError InitializeAsExternalTexture(ComPtr<IUnknown> d3dTexture,
|
||||
std::vector<Ref<d3d::Fence>> waitFences,
|
||||
bool isSwapChainTexture);
|
||||
MaybeError InitializeAsSwapChainTexture(ComPtr<ID3D12Resource> d3d12Texture);
|
||||
|
||||
|
@ -140,7 +140,7 @@ class Texture final : public TextureBase {
|
|||
ResourceHeapAllocation mResourceAllocation;
|
||||
|
||||
// TODO(dawn:1460): Encapsulate imported image fields e.g. std::unique_ptr<ExternalImportInfo>.
|
||||
std::vector<Ref<Fence>> mWaitFences;
|
||||
std::vector<Ref<d3d::Fence>> mWaitFences;
|
||||
std::optional<ExecutionSerial> mSignalFenceValue;
|
||||
bool mSwapChainTexture = false;
|
||||
|
||||
|
|
|
@ -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",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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<wgpu::FeatureName> 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<ID3D12Device> d3d12Device = dawn::native::d3d12::GetD3D12Device(device.Get());
|
||||
ComPtr<IDXGIAdapter> dxgiAdapter =
|
||||
dawn::native::d3d::GetDXGIAdapter(device.GetAdapter().Get());
|
||||
DXGI_ADAPTER_DESC adapterDesc;
|
||||
|
||||
const LUID adapterLuid = d3d12Device->GetAdapterLuid();
|
||||
|
||||
ComPtr<IDXGIFactory4> dxgiFactory;
|
||||
HRESULT hr = ::CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgiFactory));
|
||||
HRESULT hr = dxgiAdapter->GetDesc(&adapterDesc);
|
||||
ASSERT_EQ(hr, S_OK);
|
||||
|
||||
ComPtr<IDXGIAdapter> dxgiAdapter;
|
||||
hr = dxgiFactory->EnumAdapterByLuid(adapterLuid, IID_PPV_ARGS(&dxgiAdapter));
|
||||
ComPtr<IDXGIFactory4> 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<ID3D11Device> 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<wgpu::FeatureName> GetRequiredFeatures() override {
|
||||
std::vector<wgpu::FeatureName> 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<ID3D11Texture2D> d3d11Texture;
|
||||
std::unique_ptr<dawn::native::d3d::ExternalImageDXGI> 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<ID3D11Texture2D> d3d11Texture;
|
||||
std::unique_ptr<dawn::native::d3d::ExternalImageDXGI> 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<dawn::native::d3d::ExternalImageDXGI> 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());
|
|
@ -44,21 +44,13 @@ class VideoViewsTestBackendWin : public VideoViewsTestBackend {
|
|||
mWGPUDevice = device;
|
||||
|
||||
// Create the D3D11 device/contexts that will be used in subsequent tests
|
||||
ComPtr<ID3D12Device> d3d12Device = dawn::native::d3d12::GetD3D12Device(device);
|
||||
|
||||
const LUID adapterLuid = d3d12Device->GetAdapterLuid();
|
||||
|
||||
ComPtr<IDXGIFactory4> dxgiFactory;
|
||||
HRESULT hr = ::CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgiFactory));
|
||||
ASSERT_EQ(hr, S_OK);
|
||||
|
||||
ComPtr<IDXGIAdapter> dxgiAdapter;
|
||||
hr = dxgiFactory->EnumAdapterByLuid(adapterLuid, IID_PPV_ARGS(&dxgiAdapter));
|
||||
ASSERT_EQ(hr, S_OK);
|
||||
ComPtr<IDXGIAdapter> dxgiAdapter =
|
||||
dawn::native::d3d::GetDXGIAdapter(wgpuDeviceGetAdapter(device));
|
||||
|
||||
ComPtr<ID3D11Device> d3d11Device;
|
||||
D3D_FEATURE_LEVEL d3dFeatureLevel;
|
||||
ComPtr<ID3D11DeviceContext> d3d11DeviceContext;
|
||||
HRESULT hr;
|
||||
hr = ::D3D11CreateDevice(dxgiAdapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, nullptr, 0,
|
||||
D3D11_SDK_VERSION, &d3d11Device, &d3dFeatureLevel,
|
||||
&d3d11DeviceContext);
|
||||
|
|
Loading…
Reference in New Issue