mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[d3d10] Implement D3D10Multithread
This commit is contained in:
parent
d1f179c5af
commit
28216909bd
@ -8,10 +8,9 @@ namespace dxvk {
|
|||||||
D3D10Device::D3D10Device(
|
D3D10Device::D3D10Device(
|
||||||
D3D11Device* pDevice,
|
D3D11Device* pDevice,
|
||||||
D3D11ImmediateContext* pContext)
|
D3D11ImmediateContext* pContext)
|
||||||
: m_device(pDevice), m_context(pContext) {
|
: m_device(pDevice), m_context(pContext),
|
||||||
// Respecting the single-threaded flag may improve performance
|
m_multithread(this, !(pDevice->GetCreationFlags() & D3D10_CREATE_DEVICE_SINGLETHREADED)) {
|
||||||
UINT flags = pDevice->GetCreationFlags();
|
|
||||||
m_threadSafe = !(flags & D3D10_CREATE_DEVICE_SINGLETHREADED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "d3d10_include.h"
|
#include "d3d10_multithread.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
using D3D10DeviceMutex = sync::Spinlock;
|
|
||||||
using D3D10DeviceLock = std::unique_lock<D3D10DeviceMutex>;
|
|
||||||
|
|
||||||
class D3D11Device;
|
class D3D11Device;
|
||||||
class D3D11ImmediateContext;
|
class D3D11ImmediateContext;
|
||||||
|
|
||||||
@ -474,18 +471,18 @@ namespace dxvk {
|
|||||||
UINT* pHeight);
|
UINT* pHeight);
|
||||||
|
|
||||||
D3D10DeviceLock LockDevice() {
|
D3D10DeviceLock LockDevice() {
|
||||||
return m_threadSafe
|
return m_multithread.AcquireLock();
|
||||||
? D3D10DeviceLock(m_mutex)
|
}
|
||||||
: D3D10DeviceLock();
|
|
||||||
|
D3D10Multithread* GetMultithread() {
|
||||||
|
return &m_multithread;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
D3D10DeviceMutex m_mutex;
|
|
||||||
D3D11Device* m_device;
|
D3D11Device* m_device;
|
||||||
D3D11ImmediateContext* m_context;
|
D3D11ImmediateContext* m_context;
|
||||||
|
D3D10Multithread m_multithread;
|
||||||
bool m_threadSafe = true;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
90
src/d3d10/d3d10_multithread.cpp
Normal file
90
src/d3d10/d3d10_multithread.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "d3d10_device.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
void D3D10DeviceMutex::lock() {
|
||||||
|
while (!try_lock())
|
||||||
|
dxvk::this_thread::yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D10DeviceMutex::unlock() {
|
||||||
|
if (likely(m_counter == 0))
|
||||||
|
m_owner.store(0, std::memory_order_release);
|
||||||
|
else
|
||||||
|
m_counter -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool D3D10DeviceMutex::try_lock() {
|
||||||
|
uint32_t threadId = GetCurrentThreadId();
|
||||||
|
uint32_t expected = 0;
|
||||||
|
|
||||||
|
bool status = m_owner.compare_exchange_weak(
|
||||||
|
expected, threadId, std::memory_order_acquire);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (expected != threadId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_counter += 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D10Multithread::D3D10Multithread(
|
||||||
|
IUnknown* pParent,
|
||||||
|
BOOL Protected)
|
||||||
|
: m_parent (pParent),
|
||||||
|
m_protected (Protected) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D10Multithread::~D3D10Multithread() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE D3D10Multithread::AddRef() {
|
||||||
|
return m_parent->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE D3D10Multithread::Release() {
|
||||||
|
return m_parent->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D10Multithread::QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject) {
|
||||||
|
return m_parent->QueryInterface(riid, ppvObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE D3D10Multithread::Enter() {
|
||||||
|
if (m_protected)
|
||||||
|
m_mutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE D3D10Multithread::Leave() {
|
||||||
|
if (m_protected)
|
||||||
|
m_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL STDMETHODCALLTYPE D3D10Multithread::SetMultithreadProtected(
|
||||||
|
BOOL bMTProtect) {
|
||||||
|
return std::exchange(m_protected, bMTProtect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL STDMETHODCALLTYPE D3D10Multithread::GetMultithreadProtected() {
|
||||||
|
return m_protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
127
src/d3d10/d3d10_multithread.h
Normal file
127
src/d3d10/d3d10_multithread.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "d3d10_include.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Device mutex
|
||||||
|
*
|
||||||
|
* Effectively implements a recursive spinlock
|
||||||
|
* which is used to lock the D3D10 device.
|
||||||
|
*/
|
||||||
|
class D3D10DeviceMutex {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
bool try_lock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::atomic<uint32_t> m_owner = { 0u };
|
||||||
|
uint32_t m_counter = { 0u };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Device lock
|
||||||
|
*
|
||||||
|
* Lightweight RAII wrapper that implements
|
||||||
|
* a subset of the functionality provided by
|
||||||
|
* \c std::unique_lock, with the goal of being
|
||||||
|
* cheaper to construct and destroy.
|
||||||
|
*/
|
||||||
|
class D3D10DeviceLock {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
D3D10DeviceLock()
|
||||||
|
: m_mutex(nullptr) { }
|
||||||
|
|
||||||
|
D3D10DeviceLock(D3D10DeviceMutex& mutex)
|
||||||
|
: m_mutex(&mutex) {
|
||||||
|
mutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D10DeviceLock(D3D10DeviceLock&& other)
|
||||||
|
: m_mutex(other.m_mutex) {
|
||||||
|
other.m_mutex = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D10DeviceLock& operator = (D3D10DeviceLock&& other) {
|
||||||
|
if (m_mutex)
|
||||||
|
m_mutex->unlock();
|
||||||
|
|
||||||
|
m_mutex = other.m_mutex;
|
||||||
|
other.m_mutex = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~D3D10DeviceLock() {
|
||||||
|
if (unlikely(m_mutex != nullptr))
|
||||||
|
m_mutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
D3D10DeviceMutex* m_mutex;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief D3D10 device and D3D11 context lock
|
||||||
|
*
|
||||||
|
* Can be queried from the D3D10 device or from
|
||||||
|
* any D3D11 context in order to make individual
|
||||||
|
* calls thread-safe. Provides methods to lock
|
||||||
|
* the device or context explicitly.
|
||||||
|
*/
|
||||||
|
class D3D10Multithread : public ID3D10Multithread {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
D3D10Multithread(
|
||||||
|
IUnknown* pParent,
|
||||||
|
BOOL Protected);
|
||||||
|
|
||||||
|
~D3D10Multithread();
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef() final;
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE Release() final;
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject) final;
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE Enter() final;
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE Leave() final;
|
||||||
|
|
||||||
|
BOOL STDMETHODCALLTYPE SetMultithreadProtected(
|
||||||
|
BOOL bMTProtect) final;
|
||||||
|
|
||||||
|
BOOL STDMETHODCALLTYPE GetMultithreadProtected() final;
|
||||||
|
|
||||||
|
D3D10DeviceLock AcquireLock() {
|
||||||
|
return unlikely(m_protected)
|
||||||
|
? D3D10DeviceLock(m_mutex)
|
||||||
|
: D3D10DeviceLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IUnknown* m_parent;
|
||||||
|
BOOL m_protected;
|
||||||
|
|
||||||
|
D3D10DeviceMutex m_mutex;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -72,6 +72,11 @@ namespace dxvk {
|
|||||||
*ppvObject = ref(m_d3d11Presenter);
|
*ppvObject = ref(m_d3d11Presenter);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (riid == __uuidof(ID3D10Multithread)) {
|
||||||
|
*ppvObject = ref(m_d3d11Device->GetD3D10Multithread());
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (riid == __uuidof(ID3D11Debug))
|
if (riid == __uuidof(ID3D11Debug))
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
|
@ -345,6 +345,10 @@ namespace dxvk {
|
|||||||
D3D10Device* GetD3D10Interface() const {
|
D3D10Device* GetD3D10Interface() const {
|
||||||
return m_d3d10Device;
|
return m_d3d10Device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3D10Multithread* GetD3D10Multithread() const {
|
||||||
|
return m_d3d10Device->GetMultithread();
|
||||||
|
}
|
||||||
|
|
||||||
DxvkBufferSlice AllocUavCounterSlice() { return m_uavCounters->AllocSlice(); }
|
DxvkBufferSlice AllocUavCounterSlice() { return m_uavCounters->AllocSlice(); }
|
||||||
DxvkBufferSlice AllocXfbCounterSlice() { return m_xfbCounters->AllocSlice(); }
|
DxvkBufferSlice AllocXfbCounterSlice() { return m_xfbCounters->AllocSlice(); }
|
||||||
|
@ -8,6 +8,7 @@ d3d10_src = [
|
|||||||
'../d3d10/d3d10_depth_stencil.cpp',
|
'../d3d10/d3d10_depth_stencil.cpp',
|
||||||
'../d3d10/d3d10_device.cpp',
|
'../d3d10/d3d10_device.cpp',
|
||||||
'../d3d10/d3d10_input_layout.cpp',
|
'../d3d10/d3d10_input_layout.cpp',
|
||||||
|
'../d3d10/d3d10_multithread.cpp',
|
||||||
'../d3d10/d3d10_query.cpp',
|
'../d3d10/d3d10_query.cpp',
|
||||||
'../d3d10/d3d10_rasterizer.cpp',
|
'../d3d10/d3d10_rasterizer.cpp',
|
||||||
'../d3d10/d3d10_sampler.cpp',
|
'../d3d10/d3d10_sampler.cpp',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user