From a7de1fb3c21cfc95fac235baa7615aedd8f3d0f3 Mon Sep 17 00:00:00 2001 From: Maciej Plewka Date: Wed, 27 Oct 2021 09:55:40 +0000 Subject: [PATCH] Lock d3d sharing before accessing device context Related-To: NEO-5987 With this change D3D device context will not be accessed from parallel threads. Signed-off-by: Maciej Plewka --- opencl/source/sharings/d3d/d3d_sharing.cpp | 2 + opencl/source/sharings/d3d/d3d_sharing.h | 1 + .../unit_test/mt_tests/sharing/CMakeLists.txt | 15 ++++ .../mt_tests/sharing/d3d_sharing_mt_tests.cpp | 86 +++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 opencl/test/unit_test/mt_tests/sharing/CMakeLists.txt create mode 100644 opencl/test/unit_test/mt_tests/sharing/d3d_sharing_mt_tests.cpp diff --git a/opencl/source/sharings/d3d/d3d_sharing.cpp b/opencl/source/sharings/d3d/d3d_sharing.cpp index d299a45776..033ec052cc 100644 --- a/opencl/source/sharings/d3d/d3d_sharing.cpp +++ b/opencl/source/sharings/d3d/d3d_sharing.cpp @@ -43,6 +43,7 @@ D3DSharing::~D3DSharing() { template void D3DSharing::synchronizeObject(UpdateData &updateData) { + std::unique_lock lock(this->mtx); sharingFunctions->getDeviceContext(d3dQuery); if (!sharedResource) { sharingFunctions->copySubresourceRegion(resourceStaging, 0, resource, subresource); @@ -58,6 +59,7 @@ void D3DSharing::synchronizeObject(UpdateData &updateData) { template void D3DSharing::releaseResource(MemObj *memObject, uint32_t rootDeviceIndex) { if (!sharedResource) { + std::unique_lock lock(this->mtx); sharingFunctions->getDeviceContext(d3dQuery); sharingFunctions->copySubresourceRegion(resource, subresource, resourceStaging, 0); if (!context->getInteropUserSyncEnabled()) { diff --git a/opencl/source/sharings/d3d/d3d_sharing.h b/opencl/source/sharings/d3d/d3d_sharing.h index 03e5b39e1b..3e4348f816 100644 --- a/opencl/source/sharings/d3d/d3d_sharing.h +++ b/opencl/source/sharings/d3d/d3d_sharing.h @@ -47,5 +47,6 @@ class D3DSharing : public SharingHandler { D3DQuery *d3dQuery = nullptr; bool sharedResource = false; unsigned int subresource = 0; + std::mutex mtx; }; } // namespace NEO diff --git a/opencl/test/unit_test/mt_tests/sharing/CMakeLists.txt b/opencl/test/unit_test/mt_tests/sharing/CMakeLists.txt new file mode 100644 index 0000000000..44d3cd5060 --- /dev/null +++ b/opencl/test/unit_test/mt_tests/sharing/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright (C) 2021 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(IGDRCL_SRCS_mt_tests_sharing + # local files + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/d3d_sharing_mt_tests.cpp +) +if(WIN32) + target_sources(igdrcl_mt_tests PRIVATE ${IGDRCL_SRCS_mt_tests_sharing}) +endif() + diff --git a/opencl/test/unit_test/mt_tests/sharing/d3d_sharing_mt_tests.cpp b/opencl/test/unit_test/mt_tests/sharing/d3d_sharing_mt_tests.cpp new file mode 100644 index 0000000000..bab52ecb11 --- /dev/null +++ b/opencl/test/unit_test/mt_tests/sharing/d3d_sharing_mt_tests.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/common/test_macros/test.h" + +#include "opencl/source/os_interface/windows/d3d_sharing_functions.h" +#include "opencl/source/sharings/d3d/d3d_sharing.h" +#include "opencl/test/unit_test/mocks/mock_context.h" + +using namespace NEO; + +template +class MockD3DSharingFunctions : public D3DSharingFunctions { + public: + typedef typename D3D::D3DDevice D3DDevice; + typedef typename D3D::D3DQuery D3DQuery; + typedef typename D3D::D3DResource D3DResource; + MockD3DSharingFunctions() : D3DSharingFunctions((D3DDevice *)1) { + } + void getDeviceContext(D3DQuery *query) override { + signalDeviceContextCalled = true; + while (!signalLockChecked) + ; + } + void copySubresourceRegion(D3DResource *dst, cl_uint dstSubresource, + D3DResource *src, cl_uint srcSubresource) override { + } + void flushAndWait(D3DQuery *query) override { + } + void releaseDeviceContext(D3DQuery *query) override { + } + void addRef(D3DResource *resource) override { + } + void createQuery(D3DQuery **query) override { + } + void release(IUnknown *resource) override { + } + + std::atomic_bool signalDeviceContextCalled = false; + std::atomic_bool signalLockChecked = false; +}; + +template +class MockD3DSharingBase : public D3DSharing { + public: + using D3DSharing::sharingFunctions; + MockD3DSharingBase(Context *ctx) : D3DSharing(ctx, nullptr, nullptr, 0, false) { + } + void checkIfMutexWasLocked() { + isLocked = !this->mtx.try_lock(); + reinterpret_cast *>(this->sharingFunctions)->signalLockChecked = true; + } + bool isLocked = false; +}; + +TEST(SharingD3DMT, givenD3DSharingWhenSynchroniceObjectIsCalledThenMtxIsLockedBeforeAccessingDevice) { + auto mockCtx = std::make_unique(); + mockCtx->sharingFunctions[MockD3DSharingFunctions::sharingId] = std::make_unique>(); + auto mockD3DSharing = std::make_unique>(mockCtx.get()); + UpdateData updateData(0); + std::thread t1(&MockD3DSharingBase::synchronizeObject, mockD3DSharing.get(), updateData); + while (!reinterpret_cast *>(mockD3DSharing->sharingFunctions)->signalDeviceContextCalled) + ; + std::thread t2(&MockD3DSharingBase::checkIfMutexWasLocked, mockD3DSharing.get()); + t1.join(); + t2.join(); + EXPECT_TRUE(mockD3DSharing->isLocked); +} + +TEST(SharingD3DMT, givenD3DSharingWhenReleaseResourceIsCalledThenMtxIsLockedBeforeAccessingDevice) { + auto mockCtx = std::make_unique(); + mockCtx->sharingFunctions[MockD3DSharingFunctions::sharingId] = std::make_unique>(); + auto mockD3DSharing = std::make_unique>(mockCtx.get()); + UpdateData updateData(0); + std::thread t1(&MockD3DSharingBase::releaseResource, mockD3DSharing.get(), nullptr, 0); + while (!reinterpret_cast *>(mockD3DSharing->sharingFunctions)->signalDeviceContextCalled) + ; + std::thread t2(&MockD3DSharingBase::checkIfMutexWasLocked, mockD3DSharing.get()); + t1.join(); + t2.join(); + EXPECT_TRUE(mockD3DSharing->isLocked); +}