diff --git a/src/dawn_native/d3d12/D3D12Backend.cpp b/src/dawn_native/d3d12/D3D12Backend.cpp index 8d992f4aa4..22d13dd9f1 100644 --- a/src/dawn_native/d3d12/D3D12Backend.cpp +++ b/src/dawn_native/d3d12/D3D12Backend.cpp @@ -17,6 +17,8 @@ #include "dawn_native/D3D12Backend.h" +#include "common/Log.h" +#include "common/Math.h" #include "common/SwapChainUtils.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/NativeSwapChainImplD3D12.h" @@ -68,8 +70,14 @@ namespace dawn_native { namespace d3d12 { const ExternalImageAccessDescriptorDXGIKeyedMutex* descriptor) { Device* backendDevice = reinterpret_cast(device); + // Ensure the texture usage is allowed + if (!IsSubset(descriptor->usage, mUsage)) { + dawn::ErrorLog() << "Texture usage is not valid for external image"; + return nullptr; + } + TextureDescriptor textureDescriptor = {}; - textureDescriptor.usage = static_cast(mUsage); + textureDescriptor.usage = static_cast(descriptor->usage); textureDescriptor.dimension = static_cast(mDimension); textureDescriptor.size = {mSize.width, mSize.height, mSize.depth}; textureDescriptor.format = static_cast(mFormat); @@ -149,6 +157,7 @@ namespace dawn_native { namespace d3d12 { externalAccessDesc.isInitialized = descriptor->isInitialized; externalAccessDesc.isSwapChainTexture = descriptor->isSwapChainTexture; externalAccessDesc.acquireMutexKey = descriptor->acquireMutexKey; + externalAccessDesc.usage = descriptor->cTextureDescriptor->usage; return externalImage->ProduceTexture(device, &externalAccessDesc); } diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h index 68e2feb870..6e1b830cb1 100644 --- a/src/include/dawn_native/DawnNative.h +++ b/src/include/dawn_native/DawnNative.h @@ -231,6 +231,7 @@ namespace dawn_native { struct DAWN_NATIVE_EXPORT ExternalImageAccessDescriptor { public: bool isInitialized; // Whether the texture is initialized on import + WGPUTextureUsageFlags usage; }; struct DAWN_NATIVE_EXPORT ExternalImageExportInfo { diff --git a/src/tests/end2end/D3D12ResourceWrappingTests.cpp b/src/tests/end2end/D3D12ResourceWrappingTests.cpp index 12e0aebf77..47f311bee9 100644 --- a/src/tests/end2end/D3D12ResourceWrappingTests.cpp +++ b/src/tests/end2end/D3D12ResourceWrappingTests.cpp @@ -122,6 +122,7 @@ namespace { dawn_native::d3d12::ExternalImageAccessDescriptorDXGIKeyedMutex externalAccessDesc; externalAccessDesc.acquireMutexKey = 0; + externalAccessDesc.usage = static_cast(dawnDesc->usage); *dawnTexture = wgpu::Texture::Acquire( externalImage->ProduceTexture(device.Get(), &externalAccessDesc)); @@ -361,6 +362,7 @@ class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase { dawn_native::d3d12::ExternalImageAccessDescriptorDXGIKeyedMutex externalAccessDesc; externalAccessDesc.acquireMutexKey = 1; externalAccessDesc.isInitialized = isInitialized; + externalAccessDesc.usage = static_cast(dawnDescriptor->usage); *dawnTextureOut = wgpu::Texture::Acquire( externalImage->ProduceTexture(device.Get(), &externalAccessDesc)); @@ -573,6 +575,7 @@ TEST_P(D3D12SharedHandleUsageTests, ReuseExternalImage) { dawn_native::d3d12::ExternalImageAccessDescriptorDXGIKeyedMutex externalAccessDesc; externalAccessDesc.acquireMutexKey = 1; externalAccessDesc.isInitialized = true; + externalAccessDesc.usage = static_cast(baseDawnDescriptor.usage); texture = wgpu::Texture::Acquire(externalImage->ProduceTexture(device.Get(), &externalAccessDesc)); @@ -590,5 +593,31 @@ TEST_P(D3D12SharedHandleUsageTests, ReuseExternalImage) { } } +// Produce a new texture with a usage not specified in the external image. +TEST_P(D3D12SharedHandleUsageTests, ExternalImageUsage) { + DAWN_SKIP_TEST_IF(UsesWire()); + + dawn_native::d3d12::ExternalImageAccessDescriptorDXGIKeyedMutex externalAccessDesc; + externalAccessDesc.acquireMutexKey = 1; + externalAccessDesc.isInitialized = true; + + wgpu::Texture texture; + ComPtr d3d11Texture; + std::unique_ptr externalImage; + WrapSharedHandle(&baseDawnDescriptor, &baseD3dDescriptor, &texture, &d3d11Texture, + &externalImage); + ASSERT_NE(texture.Get(), nullptr); + + externalAccessDesc.usage = WGPUTextureUsage_Storage; + texture = + wgpu::Texture::Acquire(externalImage->ProduceTexture(device.Get(), &externalAccessDesc)); + ASSERT_EQ(texture.Get(), nullptr); + + externalAccessDesc.usage = WGPUTextureUsage_Sampled; + texture = + wgpu::Texture::Acquire(externalImage->ProduceTexture(device.Get(), &externalAccessDesc)); + ASSERT_NE(texture.Get(), nullptr); +} + DAWN_INSTANTIATE_TEST(D3D12SharedHandleValidation, D3D12Backend()); DAWN_INSTANTIATE_TEST(D3D12SharedHandleUsageTests, D3D12Backend()); diff --git a/src/tests/end2end/D3D12VideoViewsTests.cpp b/src/tests/end2end/D3D12VideoViewsTests.cpp index d460433c27..05af61b23a 100644 --- a/src/tests/end2end/D3D12VideoViewsTests.cpp +++ b/src/tests/end2end/D3D12VideoViewsTests.cpp @@ -213,6 +213,7 @@ namespace { dawn_native::d3d12::ExternalImageAccessDescriptorDXGIKeyedMutex externalAccessDesc; externalAccessDesc.acquireMutexKey = 1; externalAccessDesc.isInitialized = true; + externalAccessDesc.usage = static_cast(textureDesc.usage); *dawnTextureOut = wgpu::Texture::Acquire( externalImage->ProduceTexture(device.Get(), &externalAccessDesc));