mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
d3d10, d3d12: the window is kept across a restart
The window is left up across a video driver restart, and taken back by the driver that comes next, for Vulkan, GDI and Direct3D 11. These are the other two Direct3D drivers anyone uses. They join by the same means as d3d11: a tag on the window, so that only a driver of the same kind takes it; win32_window_keep() in place of destroying it; and, should a swap chain not be had on a window that was taken, a new window and a second attempt (win32_window_remake()). d3d10 needs no more than that. Its swap chain is released with its device, and is of the kind - not the flip model - that a window may have another of. d3d12 needs its swap chain gone, and it never went: the Release() in d3d12_gfx_free() has been compiled out for years under a note that it crashes eventually. DXGI makes no second flip-model swap chain on a window that still has one, so as it stood every restart on a kept window would have fallen back to a new one. When the window is kept the swap chain is now released, in the order that should be safe: the queue is drained at the top of the function, the back buffers are let go of just before, the swap chain is told it is windowed (releasing one that is not is an error), and it is released while the queue it was made on is still there. When the window is not kept - RETROARCH_WINDOW_KEEP=0, or the program is closing - none of that runs and the driver frees as it always did. Why the old Release() crashed is not known, so whether this one is safe is not known either until it has been run: none of it could be here. Wine starts neither driver. Both compile for Windows. If d3d12 misbehaves, RETROARCH_WINDOW_KEEP=0 is the way back.
This commit is contained in:
1 parent
afff14a917
commit
c66a7ce8f4
2 files changed
+78
-7
No files matched your search
+27
-3
@@ -2442,12 +2442,20 @@ static void d3d10_gfx_free(void* data)
|
||||
}
|
||||
}
|
||||
|
||||
/* Left up for the next D3D10 driver, where it can be. The swap
|
||||
* chain went with the device above, and it is of the kind (not the
|
||||
* flip model) that a window can have another of in any case. */
|
||||
#if defined(HAVE_WINDOW) && defined(HAVE_MONITOR)
|
||||
if (!win32_window_keep())
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_MONITOR
|
||||
win32_monitor_from_window();
|
||||
win32_monitor_from_window();
|
||||
#endif
|
||||
#ifdef HAVE_WINDOW
|
||||
win32_destroy_window();
|
||||
win32_destroy_window();
|
||||
#endif
|
||||
}
|
||||
free(d3d10);
|
||||
}
|
||||
|
||||
@@ -2509,6 +2517,9 @@ static void *d3d10_gfx_init(const video_info_t* video,
|
||||
wndclass.lpfnWndProc = win32_window_proc;
|
||||
win32_window_proc_setup(WIN32_WINDOW_D3D);
|
||||
#ifdef HAVE_WINDOW
|
||||
/* the window may be left up for the next D3D10 driver, and taken
|
||||
* from the last (win32_window_keep()) */
|
||||
win32_window_tag("d3d10");
|
||||
win32_window_init(&wndclass, true, NULL);
|
||||
#endif
|
||||
|
||||
@@ -2546,7 +2557,20 @@ static void *d3d10_gfx_init(const video_info_t* video,
|
||||
NULL
|
||||
#endif
|
||||
))
|
||||
goto error;
|
||||
{
|
||||
#if defined(HAVE_WINDOW) && defined(HAVE_MONITOR)
|
||||
/* On a window the last driver left up: if a device and swap
|
||||
* chain cannot be made on it, a new window, and once more. */
|
||||
if ( !win32_window_was_taken()
|
||||
|| !win32_window_remake(d3d10, d3d10->vp.full_dims,
|
||||
video->fullscreen)
|
||||
|| !d3d10_init_swapchain(d3d10,
|
||||
VIDEO_SCALE_W(d3d10->vp.full_dims),
|
||||
VIDEO_SCALE_H(d3d10->vp.full_dims),
|
||||
main_window.hwnd))
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
{
|
||||
D3D10Texture2D backBuffer;
|
||||
|
||||
+51
-4
@@ -4313,6 +4313,7 @@ static void d3d12_hw_ring_free(d3d12_video_t *d3d12);
|
||||
static void d3d12_gfx_free(void* data)
|
||||
{
|
||||
unsigned i;
|
||||
bool window_kept = false;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
if (!d3d12)
|
||||
@@ -4426,6 +4427,29 @@ static void d3d12_gfx_free(void* data)
|
||||
Release(d3d12->chain.renderTargets[0]);
|
||||
Release(d3d12->chain.renderTargets[1]);
|
||||
|
||||
#if defined(HAVE_WINDOW) && defined(HAVE_MONITOR)
|
||||
/* The window is left up for the next D3D12 driver, where it can be
|
||||
* (win32_window_keep()). DXGI makes no second flip-model swap chain
|
||||
* on a window that still has one, so then this one has to go - and
|
||||
* it never did: the Release() further down has been compiled out
|
||||
* for years with a note that it crashes eventually. It is done
|
||||
* here instead, in the order that should be safe: the queue was
|
||||
* drained at the top, the back buffers were let go of just above,
|
||||
* the swap chain is told it is windowed (it always is; releasing
|
||||
* one that is not is an error), and it is released while the
|
||||
* queue it was made on is still there. Only when the window is
|
||||
* kept: with RETROARCH_WINDOW_KEEP=0, or on the way out of the
|
||||
* program, nothing here runs and the driver frees as it did. */
|
||||
window_kept = win32_window_keep();
|
||||
if (window_kept && d3d12->chain.handle)
|
||||
{
|
||||
d3d12->chain.handle->lpVtbl->SetFullscreenState(
|
||||
d3d12->chain.handle, FALSE, NULL);
|
||||
Release(d3d12->chain.handle);
|
||||
d3d12->chain.handle = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
Release(d3d12->queue.fence);
|
||||
Release(d3d12->queue.cmd);
|
||||
Release(d3d12->queue.allocator);
|
||||
@@ -4435,7 +4459,9 @@ static void d3d12_gfx_free(void* data)
|
||||
CloseHandle(d3d12->queue.fenceEvent);
|
||||
|
||||
#if 0
|
||||
/* Releasing this will crash eventually (?!) */
|
||||
/* Releasing this will crash eventually (?!)
|
||||
* (It is released above, before the queue, when the window is
|
||||
* kept for the next driver - which needs it gone.) */
|
||||
Release(d3d12->chain.handle);
|
||||
#endif
|
||||
|
||||
@@ -4460,12 +4486,15 @@ static void d3d12_gfx_free(void* data)
|
||||
video_driver_modify_disp_flags(0, VIDEO_FLAG_HDR_SUPPORT | VIDEO_FLAG_HDR10_SUPPORT | VIDEO_FLAG_SCRGB_SUPPORT);
|
||||
#endif
|
||||
|
||||
if (!window_kept)
|
||||
{
|
||||
#ifdef HAVE_MONITOR
|
||||
win32_monitor_from_window();
|
||||
win32_monitor_from_window();
|
||||
#endif
|
||||
#ifdef HAVE_WINDOW
|
||||
win32_destroy_window();
|
||||
win32_destroy_window();
|
||||
#endif
|
||||
}
|
||||
|
||||
free(d3d12);
|
||||
}
|
||||
@@ -5226,6 +5255,10 @@ static void *d3d12_gfx_init(const video_info_t* video,
|
||||
wndclass.lpfnWndProc = win32_window_proc;
|
||||
win32_window_proc_setup(WIN32_WINDOW_D3D);
|
||||
#ifdef HAVE_WINDOW
|
||||
/* the window may be left up for the next D3D12 driver, and taken
|
||||
* from the last: d3d12_gfx_free() and the swap chain's creation
|
||||
* below do what that needs */
|
||||
win32_window_tag("d3d12");
|
||||
win32_window_init(&wndclass, true, NULL);
|
||||
#endif
|
||||
|
||||
@@ -5289,7 +5322,21 @@ static void *d3d12_gfx_init(const video_info_t* video,
|
||||
goto error;
|
||||
#else
|
||||
if (!d3d12_init_swapchain(d3d12, VIDEO_SCALE_W(d3d12->vp.full_dims), VIDEO_SCALE_H(d3d12->vp.full_dims), main_window.hwnd))
|
||||
goto error;
|
||||
{
|
||||
#if defined(HAVE_WINDOW) && defined(HAVE_MONITOR)
|
||||
/* On a window the last driver left up, DXGI may refuse a swap
|
||||
* chain - something of the old one is still alive on it. Then
|
||||
* the window is not worth having: a new one, and once more. */
|
||||
if ( !win32_window_was_taken()
|
||||
|| !win32_window_remake(d3d12, d3d12->vp.full_dims,
|
||||
video->fullscreen)
|
||||
|| !d3d12_init_swapchain(d3d12,
|
||||
VIDEO_SCALE_W(d3d12->vp.full_dims),
|
||||
VIDEO_SCALE_H(d3d12->vp.full_dims),
|
||||
main_window.hwnd))
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DXGI_HDR
|
||||
|
||||
Reference in new issue
Block a user