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 <maciej.plewka@intel.com>
This commit is contained in:
Maciej Plewka 2021-10-27 09:55:40 +00:00 committed by Compute-Runtime-Automation
parent 7aebfc3293
commit a7de1fb3c2
4 changed files with 104 additions and 0 deletions

View File

@ -43,6 +43,7 @@ D3DSharing<D3D>::~D3DSharing() {
template <typename D3D>
void D3DSharing<D3D>::synchronizeObject(UpdateData &updateData) {
std::unique_lock<std::mutex> lock(this->mtx);
sharingFunctions->getDeviceContext(d3dQuery);
if (!sharedResource) {
sharingFunctions->copySubresourceRegion(resourceStaging, 0, resource, subresource);
@ -58,6 +59,7 @@ void D3DSharing<D3D>::synchronizeObject(UpdateData &updateData) {
template <typename D3D>
void D3DSharing<D3D>::releaseResource(MemObj *memObject, uint32_t rootDeviceIndex) {
if (!sharedResource) {
std::unique_lock<std::mutex> lock(this->mtx);
sharingFunctions->getDeviceContext(d3dQuery);
sharingFunctions->copySubresourceRegion(resource, subresource, resourceStaging, 0);
if (!context->getInteropUserSyncEnabled()) {

View File

@ -47,5 +47,6 @@ class D3DSharing : public SharingHandler {
D3DQuery *d3dQuery = nullptr;
bool sharedResource = false;
unsigned int subresource = 0;
std::mutex mtx;
};
} // namespace NEO

View File

@ -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()

View File

@ -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 <typename D3D>
class MockD3DSharingFunctions : public D3DSharingFunctions<D3D> {
public:
typedef typename D3D::D3DDevice D3DDevice;
typedef typename D3D::D3DQuery D3DQuery;
typedef typename D3D::D3DResource D3DResource;
MockD3DSharingFunctions() : D3DSharingFunctions<D3D>((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 <typename D3D>
class MockD3DSharingBase : public D3DSharing<D3D> {
public:
using D3DSharing<D3D>::sharingFunctions;
MockD3DSharingBase(Context *ctx) : D3DSharing<D3D>(ctx, nullptr, nullptr, 0, false) {
}
void checkIfMutexWasLocked() {
isLocked = !this->mtx.try_lock();
reinterpret_cast<MockD3DSharingFunctions<D3D> *>(this->sharingFunctions)->signalLockChecked = true;
}
bool isLocked = false;
};
TEST(SharingD3DMT, givenD3DSharingWhenSynchroniceObjectIsCalledThenMtxIsLockedBeforeAccessingDevice) {
auto mockCtx = std::make_unique<MockContext>();
mockCtx->sharingFunctions[MockD3DSharingFunctions<D3DTypesHelper::D3D11>::sharingId] = std::make_unique<MockD3DSharingFunctions<D3DTypesHelper::D3D11>>();
auto mockD3DSharing = std::make_unique<MockD3DSharingBase<D3DTypesHelper::D3D11>>(mockCtx.get());
UpdateData updateData(0);
std::thread t1(&MockD3DSharingBase<D3DTypesHelper::D3D11>::synchronizeObject, mockD3DSharing.get(), updateData);
while (!reinterpret_cast<MockD3DSharingFunctions<D3DTypesHelper::D3D11> *>(mockD3DSharing->sharingFunctions)->signalDeviceContextCalled)
;
std::thread t2(&MockD3DSharingBase<D3DTypesHelper::D3D11>::checkIfMutexWasLocked, mockD3DSharing.get());
t1.join();
t2.join();
EXPECT_TRUE(mockD3DSharing->isLocked);
}
TEST(SharingD3DMT, givenD3DSharingWhenReleaseResourceIsCalledThenMtxIsLockedBeforeAccessingDevice) {
auto mockCtx = std::make_unique<MockContext>();
mockCtx->sharingFunctions[MockD3DSharingFunctions<D3DTypesHelper::D3D11>::sharingId] = std::make_unique<MockD3DSharingFunctions<D3DTypesHelper::D3D11>>();
auto mockD3DSharing = std::make_unique<MockD3DSharingBase<D3DTypesHelper::D3D11>>(mockCtx.get());
UpdateData updateData(0);
std::thread t1(&MockD3DSharingBase<D3DTypesHelper::D3D11>::releaseResource, mockD3DSharing.get(), nullptr, 0);
while (!reinterpret_cast<MockD3DSharingFunctions<D3DTypesHelper::D3D11> *>(mockD3DSharing->sharingFunctions)->signalDeviceContextCalled)
;
std::thread t2(&MockD3DSharingBase<D3DTypesHelper::D3D11>::checkIfMutexWasLocked, mockD3DSharing.get());
t1.join();
t2.join();
EXPECT_TRUE(mockD3DSharing->isLocked);
}