Commit 30c36970 authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

wined3d: Block in wined3d_cs_emit_present() when we reach the latency limit.

Avoid busy spinning for a potentially long time.
parent 203cbab6
......@@ -724,6 +724,8 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
}
InterlockedDecrement(&cs->pending_presents);
if (InterlockedCompareExchange(&cs->waiting_for_present, FALSE, TRUE))
SetEvent(cs->present_event);
}
void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
......@@ -734,6 +736,8 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw
unsigned int i;
LONG pending;
wined3d_not_from_cs(cs);
op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
op->opcode = WINED3D_CS_OP_PRESENT;
op->dst_window_override = dst_window_override;
......@@ -757,8 +761,17 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw
* ahead of the worker thread. */
while (pending >= swapchain->max_frame_latency)
{
YieldProcessor();
InterlockedExchange(&cs->waiting_for_present, TRUE);
pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0);
if (pending >= swapchain->max_frame_latency || !InterlockedCompareExchange(&cs->waiting_for_present, FALSE, TRUE))
{
TRACE_(d3d_perf)("Reached latency limit (%u frames), blocking to wait.\n", swapchain->max_frame_latency);
wined3d_mutex_unlock();
WaitForSingleObject(cs->present_event, INFINITE);
wined3d_mutex_lock();
TRACE_(d3d_perf)("Woken up from the wait.\n");
}
}
}
......@@ -3472,11 +3485,18 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device,
heap_free(cs->data);
goto fail;
}
if (!(cs->present_event = CreateEventW(NULL, FALSE, FALSE, NULL)))
{
ERR("Failed to create command stream present event.\n");
heap_free(cs->data);
goto fail;
}
if (!(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(const WCHAR *)wined3d_cs_run, &cs->wined3d_module)))
{
ERR("Failed to get wined3d module handle.\n");
CloseHandle(cs->present_event);
CloseHandle(cs->event);
heap_free(cs->data);
goto fail;
......@@ -3486,6 +3506,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device,
{
ERR("Failed to create wined3d command stream thread.\n");
FreeLibrary(cs->wined3d_module);
CloseHandle(cs->present_event);
CloseHandle(cs->event);
heap_free(cs->data);
goto fail;
......@@ -3508,6 +3529,8 @@ void wined3d_cs_destroy(struct wined3d_cs *cs)
{
wined3d_cs_emit_stop(cs);
CloseHandle(cs->thread);
if (!CloseHandle(cs->present_event))
ERR("Closing present event failed.\n");
if (!CloseHandle(cs->event))
ERR("Closing event failed.\n");
}
......
......@@ -5131,8 +5131,9 @@ struct wined3d_cs
struct list query_poll_list;
BOOL queries_flushed;
HANDLE event;
HANDLE event, present_event;
LONG waiting_for_event;
LONG waiting_for_present;
LONG pending_presents;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment