Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/wined3d/cs.c | 5 ++--- dlls/wined3d/device.c | 19 +++++++++++++++++++ dlls/wined3d/swapchain.c | 6 ++++++ dlls/wined3d/wined3d.spec | 2 ++ dlls/wined3d/wined3d_private.h | 4 ++++ include/wine/wined3d.h | 2 ++ 6 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index dc07f52723..11da1d4633 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -496,9 +496,8 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
/* Limit input latency by limiting the number of presents that we can get - * ahead of the worker thread. We have a constant limit here, but - * IDXGIDevice1 allows tuning this. */ - while (pending > 1) + * ahead of the worker thread. */ + while (pending > swapchain->max_frame_latency) { wined3d_pause(); pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index c04bd820f7..77b6fb21db 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3081,6 +3081,23 @@ struct wined3d_unordered_access_view * CDECL wined3d_device_get_unordered_access return wined3d_device_get_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx); }
+void CDECL wined3d_device_set_max_frame_latency(struct wined3d_device *device, unsigned int max_frame_latency) +{ + unsigned int i; + + if (!max_frame_latency) + max_frame_latency = 3; + + device->max_frame_latency = max_frame_latency; + for (i = 0; i < device->swapchain_count; ++i) + swapchain_set_max_frame_latency(device->swapchains[i], device); +} + +UINT CDECL wined3d_device_get_max_frame_latency(const struct wined3d_device *device) +{ + return device->max_frame_latency; +} + /* Context activation is done by the caller. */ #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount, @@ -5225,6 +5242,8 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT); device->update_state = &device->state;
+ device->max_frame_latency = 1; + if (!(device->cs = wined3d_cs_create(device))) { WARN("Failed to create command stream.\n"); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 2aec612018..9112e4264a 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -740,6 +740,11 @@ static void wined3d_swapchain_cs_init(void *object) context_release(swapchain->context[0]); }
+void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain, const struct wined3d_device *device) +{ + swapchain->max_frame_latency = device->max_frame_latency >= 2 ? device->max_frame_latency - 1 : 1; +} + static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device, struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) { @@ -777,6 +782,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 swapchain->win_handle = window; swapchain->device_window = window; swapchain->swap_interval = WINED3D_SWAP_INTERVAL_DEFAULT; + swapchain_set_max_frame_latency(swapchain, device);
if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, adapter->ordinal, &swapchain->original_mode, NULL))) diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 357b76ebac..bf29e206b5 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -86,6 +86,7 @@ @ cdecl wined3d_device_get_light(ptr long ptr) @ cdecl wined3d_device_get_light_enable(ptr long ptr) @ cdecl wined3d_device_get_material(ptr ptr) +@ cdecl wined3d_device_get_max_frame_latency(ptr) @ cdecl wined3d_device_get_npatch_mode(ptr) @ cdecl wined3d_device_get_pixel_shader(ptr) @ cdecl wined3d_device_get_predication(ptr ptr) @@ -161,6 +162,7 @@ @ cdecl wined3d_device_set_light(ptr long ptr) @ cdecl wined3d_device_set_light_enable(ptr long long) @ cdecl wined3d_device_set_material(ptr ptr) +@ cdecl wined3d_device_set_max_frame_latency(ptr long) @ cdecl wined3d_device_set_multithreaded(ptr) @ cdecl wined3d_device_set_npatch_mode(ptr float) @ cdecl wined3d_device_set_pixel_shader(ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index ab13a29530..b297799f82 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2957,6 +2957,7 @@ struct wined3d_device struct wined3d_rendertarget_view *back_buffer_view; struct wined3d_swapchain **swapchains; UINT swapchain_count; + unsigned int max_frame_latency;
struct list resources; /* a linked list to track resources created by the device */ struct list shaders; /* a linked list to track shaders (pixel and vertex) */ @@ -3821,6 +3822,7 @@ struct wined3d_swapchain struct wined3d_palette *palette; RECT front_buffer_update; unsigned int swap_interval; + unsigned int max_frame_latency;
LONG prev_time, frames; /* Performance tracking */
@@ -3841,6 +3843,8 @@ struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchai void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; +void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain, + const struct wined3d_device *device) DECLSPEC_HIDDEN;
/***************************************************************************** * Utility function prototypes diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 13e83da626..4d973ccdca 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2281,6 +2281,7 @@ HRESULT __cdecl wined3d_device_get_light(const struct wined3d_device *device, UINT light_idx, struct wined3d_light *light); HRESULT __cdecl wined3d_device_get_light_enable(const struct wined3d_device *device, UINT light_idx, BOOL *enable); void __cdecl wined3d_device_get_material(const struct wined3d_device *device, struct wined3d_material *material); +UINT __cdecl wined3d_device_get_max_frame_latency(const struct wined3d_device *device); float __cdecl wined3d_device_get_npatch_mode(const struct wined3d_device *device); struct wined3d_shader * __cdecl wined3d_device_get_pixel_shader(const struct wined3d_device *device); struct wined3d_query * __cdecl wined3d_device_get_predication(struct wined3d_device *device, BOOL *value); @@ -2402,6 +2403,7 @@ HRESULT __cdecl wined3d_device_set_light(struct wined3d_device *device, UINT light_idx, const struct wined3d_light *light); HRESULT __cdecl wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable); void __cdecl wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material); +void __cdecl wined3d_device_set_max_frame_latency(struct wined3d_device *device, unsigned int max_frame_latency); void __cdecl wined3d_device_set_multithreaded(struct wined3d_device *device); HRESULT __cdecl wined3d_device_set_npatch_mode(struct wined3d_device *device, float segments); void __cdecl wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader);