D3D12: Use std::thread for worker thread

Using CreateThread can create issues if any CRT calls are made, as
thread-specific data may not be initialized. Additionally, TerminateThread
is not a good idea for similar reasons, and may not free CRT resources.
This commit is contained in:
Stenzek 2016-02-17 14:25:42 +10:00
parent ffe0e326d2
commit 759b77474d
2 changed files with 11 additions and 8 deletions

View File

@ -14,9 +14,8 @@ constexpr size_t BufferOffsetForQueueItemType()
return sizeof(T) + sizeof(D3DQueueItemType) * 2; return sizeof(T) + sizeof(D3DQueueItemType) * 2;
} }
DWORD WINAPI ID3D12QueuedCommandList::BackgroundThreadFunction(LPVOID param) void ID3D12QueuedCommandList::BackgroundThreadFunction(ID3D12QueuedCommandList* parent_queued_command_list)
{ {
ID3D12QueuedCommandList* parent_queued_command_list = static_cast<ID3D12QueuedCommandList*>(param);
ID3D12GraphicsCommandList* command_list = parent_queued_command_list->m_command_list; ID3D12GraphicsCommandList* command_list = parent_queued_command_list->m_command_list;
byte* queue_array = parent_queued_command_list->m_queue_array; byte* queue_array = parent_queued_command_list->m_queue_array;
@ -26,6 +25,8 @@ DWORD WINAPI ID3D12QueuedCommandList::BackgroundThreadFunction(LPVOID param)
while (true) while (true)
{ {
WaitForSingleObject(parent_queued_command_list->m_begin_execution_event, INFINITE); WaitForSingleObject(parent_queued_command_list->m_begin_execution_event, INFINITE);
if (parent_queued_command_list->m_background_thread_exit.load())
break;
byte* item = &queue_array[queue_array_front]; byte* item = &queue_array[queue_array_front];
@ -374,13 +375,14 @@ ID3D12QueuedCommandList::ID3D12QueuedCommandList(ID3D12GraphicsCommandList* back
m_begin_execution_event = CreateSemaphore(nullptr, 0, 256, nullptr); m_begin_execution_event = CreateSemaphore(nullptr, 0, 256, nullptr);
m_stop_execution_event = CreateEvent(nullptr, FALSE, FALSE, nullptr); m_stop_execution_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
m_background_thread = CreateThread(nullptr, 0, BackgroundThreadFunction, this, 0, &m_background_thread_id); m_background_thread = std::thread(BackgroundThreadFunction, this);
} }
ID3D12QueuedCommandList::~ID3D12QueuedCommandList() ID3D12QueuedCommandList::~ID3D12QueuedCommandList()
{ {
TerminateThread(m_background_thread, 0); m_background_thread_exit.store(true);
CloseHandle(m_background_thread); ReleaseSemaphore(m_begin_execution_event, 1, nullptr);
m_background_thread.join();
CloseHandle(m_begin_execution_event); CloseHandle(m_begin_execution_event);
CloseHandle(m_stop_execution_event); CloseHandle(m_stop_execution_event);

View File

@ -6,6 +6,7 @@
#include <atomic> #include <atomic>
#include <d3d12.h> #include <d3d12.h>
#include <thread>
namespace DX12 namespace DX12
{ {
@ -612,15 +613,15 @@ private:
void ResetQueueOverflowTracking(); void ResetQueueOverflowTracking();
void CheckForOverflow(); void CheckForOverflow();
static DWORD WINAPI BackgroundThreadFunction(LPVOID param); static void BackgroundThreadFunction(ID3D12QueuedCommandList* parent_queued_command_list);
byte m_queue_array[QUEUE_ARRAY_SIZE]; byte m_queue_array[QUEUE_ARRAY_SIZE];
byte* m_queue_array_back = m_queue_array; byte* m_queue_array_back = m_queue_array;
byte* m_queue_array_back_at_start_of_frame = m_queue_array_back; byte* m_queue_array_back_at_start_of_frame = m_queue_array_back;
DWORD m_background_thread_id; std::thread m_background_thread;
HANDLE m_background_thread; std::atomic_bool m_background_thread_exit;
HANDLE m_begin_execution_event; HANDLE m_begin_execution_event;
HANDLE m_stop_execution_event; HANDLE m_stop_execution_event;