diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 8a469d060d..6d4c97a906 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -465,7 +465,8 @@ static void d3d11_gfx_set_rotation(void* data, unsigned rotation) static void d3d11_update_viewport(d3d11_video_t *d3d11, bool force_full) { - video_driver_update_viewport(&d3d11->vp, force_full, d3d11->flags & D3D11_ST_FLAG_KEEP_ASPECT); + video_driver_update_viewport(&d3d11->vp, force_full, + d3d11->flags & D3D11_ST_FLAG_KEEP_ASPECT); d3d11->frame.viewport.TopLeftX = d3d11->vp.x; d3d11->frame.viewport.TopLeftY = d3d11->vp.y; @@ -474,8 +475,9 @@ static void d3d11_update_viewport(d3d11_video_t *d3d11, bool force_full) d3d11->frame.viewport.MaxDepth = 0.0f; d3d11->frame.viewport.MaxDepth = 1.0f; - if (d3d11->shader_preset && (d3d11->frame.output_size.x != d3d11->vp.width || - d3d11->frame.output_size.y != d3d11->vp.height)) + if (d3d11->shader_preset + && ( d3d11->frame.output_size.x != d3d11->vp.width + || d3d11->frame.output_size.y != d3d11->vp.height)) d3d11->flags |= D3D11_ST_FLAG_RESIZE_RTS; d3d11->frame.output_size.x = d3d11->vp.width; @@ -489,6 +491,7 @@ static void d3d11_update_viewport(d3d11_video_t *d3d11, bool force_full) static void d3d11_free_shader_preset(d3d11_video_t* d3d11) { int i; + if (!d3d11->shader_preset) return; @@ -531,8 +534,9 @@ static void d3d11_free_shader_preset(d3d11_video_t* d3d11) free(d3d11->shader_preset); d3d11->shader_preset = NULL; - d3d11->flags &= ~( D3D11_ST_FLAG_INIT_HISTORY - | D3D11_ST_FLAG_RESIZE_RTS); + d3d11->flags &= ~(D3D11_ST_FLAG_INIT_HISTORY + | D3D11_ST_FLAG_RESIZE_RTS + ); } static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path) @@ -692,6 +696,7 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const } } +#ifdef HAVE_DXGI_HDR if (d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) { if (d3d11->shader_preset && d3d11->shader_preset->passes && (d3d11->pass[d3d11->shader_preset->passes - 1].semantics.format == SLANG_FORMAT_A2B10G10R10_UNORM_PACK32)) @@ -699,14 +704,14 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const /* If the last shader pass uses a RGB10A2 back buffer and hdr has been enabled assume we want to skip the inverse tonemapper and hdr10 conversion */ d3d11_set_hdr_inverse_tonemap(d3d11, false); d3d11_set_hdr10(d3d11, false); - d3d11->flags |= D3D11_ST_FLAG_RESIZE_CHAIN; + d3d11->flags |= D3D11_ST_FLAG_RESIZE_CHAIN; } else if (d3d11->shader_preset && d3d11->shader_preset->passes && (d3d11->pass[d3d11->shader_preset->passes - 1].semantics.format == SLANG_FORMAT_R16G16B16A16_SFLOAT)) { /* If the last shader pass uses a RGBA16 back buffer and hdr has been enabled assume we want to skip the inverse tonemapper */ d3d11_set_hdr_inverse_tonemap(d3d11, false); d3d11_set_hdr10(d3d11, true); - d3d11->flags |= D3D11_ST_FLAG_RESIZE_CHAIN; + d3d11->flags |= D3D11_ST_FLAG_RESIZE_CHAIN; } else { @@ -714,6 +719,7 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const d3d11_set_hdr10(d3d11, true); } } +#endif /* HAVE_DXGI_HDR */ for (i = 0; i < d3d11->shader_preset->luts; i++) { @@ -741,7 +747,7 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const image_texture_free(&image); } - d3d11->flags|= D3D11_ST_FLAG_RESIZE_RTS | D3D11_ST_FLAG_INIT_HISTORY; + d3d11->flags |= D3D11_ST_FLAG_INIT_HISTORY | D3D11_ST_FLAG_RESIZE_RTS; return true; @@ -760,6 +766,11 @@ static void d3d11_gfx_free(void* data) if (!d3d11) return; + if (d3d11->flags & D3D11_ST_FLAG_WAITABLE_SWAPCHAINS) + CloseHandle(d3d11->frameLatencyWaitableObject); + + font_driver_free_osd(); + #ifdef HAVE_OVERLAY d3d11_free_overlays(d3d11); #endif @@ -806,8 +817,6 @@ static void d3d11_gfx_free(void* data) Release(d3d11->scissor_disabled); Release(d3d11->swapChain); - font_driver_free_osd(); - video_st_flags = video_driver_get_st_flags(); if (video_st_flags & VIDEO_FLAG_CACHE_CONTEXT) { @@ -849,7 +858,7 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11, D3D11DeviceContext *cached_context, void *corewindow) { - HWND hwnd; + HWND hwnd = (HWND)corewindow; #ifdef __WINRT__ IDXGIFactory2* dxgiFactory = NULL; #else @@ -882,8 +891,6 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11, d3d11->chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_16] = DXGI_FORMAT_R16G16B16A16_UNORM; #endif - hwnd = (HWND)corewindow; - #ifdef HAVE_DXGI_HDR if (dxgi_check_display_hdr_support(d3d11->factory, hwnd)) d3d11->flags |= D3D11_ST_FLAG_HDR_SUPPORT; @@ -929,7 +936,7 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11, #endif desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; #ifdef HAVE_WINDOW - desc.OutputWindow = (HWND)corewindow; + desc.OutputWindow = hwnd; #endif desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; @@ -941,7 +948,6 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11, flags |= D3D11_CREATE_DEVICE_DEBUG; #endif - if (*cached_device && *cached_context) { d3d11->device = *cached_device; @@ -1062,8 +1068,9 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11, /* Failed to create swapchain, try non-flip model */ desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; desc.Flags &= ~DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; - d3d11->flags &= ~( D3D11_ST_FLAG_HAS_FLIP_MODEL - | D3D11_ST_FLAG_HAS_ALLOW_TEARING); + d3d11->flags &= ~(D3D11_ST_FLAG_HAS_FLIP_MODEL + | D3D11_ST_FLAG_HAS_ALLOW_TEARING + ); if (FAILED(dxgiFactory->lpVtbl->CreateSwapChain( dxgiFactory, (IUnknown*)d3d11->device, @@ -1104,7 +1111,6 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11, RARCH_LOG("[D3D11]: Requesting %u maximum frame latency, using %u.\n", max_latency, cur_latency); } - #ifdef HAVE_DXGI_HDR /* Check display HDR support and initialize ST.2084 support to match @@ -1244,13 +1250,21 @@ static void *d3d11_gfx_init(const video_info_t* video, d3d11->viewport.Height = d3d11->vp.full_height; d3d11->scissor.right = d3d11->vp.full_width; d3d11->scissor.bottom = d3d11->vp.full_height; - d3d11->flags |= D3D11_ST_FLAG_RESIZE_VIEWPORT; + + d3d11->flags |= D3D11_ST_FLAG_RESIZE_VIEWPORT; + if (video->force_aspect) - d3d11->flags |= D3D11_ST_FLAG_KEEP_ASPECT; + d3d11->flags |= D3D11_ST_FLAG_KEEP_ASPECT; + else + d3d11->flags &= ~D3D11_ST_FLAG_KEEP_ASPECT; + if (video->vsync) - d3d11->flags |= D3D11_ST_FLAG_VSYNC; - d3d11->format = video->rgb32 ? - DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; + d3d11->flags |= D3D11_ST_FLAG_VSYNC; + else + d3d11->flags &= ~D3D11_ST_FLAG_VSYNC; + + d3d11->format = (video->rgb32) + ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; d3d11->frame.texture[0].desc.Format = d3d11->format; d3d11->frame.texture[0].desc.Usage = D3D11_USAGE_DEFAULT; @@ -1807,8 +1821,9 @@ static void d3d11_init_render_targets(d3d11_video_t* d3d11, unsigned width, unsi RARCH_LOG("[D3D11]: Updating framebuffer size %ux%u.\n", width, height); - if ((i != (d3d11->shader_preset->passes - 1)) || (width != d3d11->vp.width) || - (height != d3d11->vp.height)) + if ( (i != (d3d11->shader_preset->passes - 1)) + || (width != d3d11->vp.width) + || (height != d3d11->vp.height)) { d3d11->pass[i].viewport.Width = width; d3d11->pass[i].viewport.Height = height; @@ -1853,15 +1868,15 @@ static bool d3d11_gfx_frame( const char* msg, video_frame_info_t* video_info) { - unsigned i; + unsigned i; d3d11_texture_t* texture = NULL; D3D11RenderTargetView rtv = NULL; d3d11_video_t* d3d11 = (d3d11_video_t*)data; D3D11DeviceContext context = d3d11->context; bool vsync = d3d11->flags & D3D11_ST_FLAG_VSYNC; bool wait_for_vblank = d3d11->flags & D3D11_ST_FLAG_WAIT_FOR_VBLANK; - unsigned present_flags = (vsync || !(d3d11->flags & -D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; + unsigned present_flags = (vsync || !(d3d11->flags & D3D11_ST_FLAG_HAS_ALLOW_TEARING)) + ? 0 : DXGI_PRESENT_ALLOW_TEARING; const char *stat_text = video_info->stat_text; unsigned video_width = video_info->width; unsigned video_height = video_info->height; @@ -1873,21 +1888,31 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; bool widgets_active = video_info->widgets_active; #endif #ifdef HAVE_DXGI_HDR + bool d3d11_hdr_enable = d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE; bool video_hdr_enable = video_info->hdr_enable; DXGI_FORMAT back_buffer_format = d3d11->shader_preset && d3d11->shader_preset->passes ? glslang_format_to_dxgi(d3d11->pass[d3d11->shader_preset->passes - 1].semantics.format) : DXGI_FORMAT_R8G8B8A8_UNORM; bool use_back_buffer = back_buffer_format != d3d11->chain_formats[d3d11->chain_bit_depth]; - bool hdr_enable = d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE; +#endif + + if (d3d11->flags & D3D11_ST_FLAG_WAITABLE_SWAPCHAINS) + WaitForSingleObjectEx( + d3d11->frameLatencyWaitableObject, + 1000, + true); + +#ifdef HAVE_DXGI_HDR if ( (d3d11->flags & D3D11_ST_FLAG_RESIZE_CHAIN) - || (hdr_enable != video_hdr_enable)) + || (d3d11_hdr_enable != video_hdr_enable)) #else - if (d3d11->resize_chain) + if (d3d11->flags & D3D11_ST_FLAG_RESIZE_CHAIN) #endif { - UINT swapchain_flags = (d3d11->flags & - D3D11_ST_FLAG_HAS_ALLOW_TEARING) - ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; + UINT swapchain_flags = (d3d11->flags & D3D11_ST_FLAG_HAS_ALLOW_TEARING) + ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; + if (d3d11->flags & D3D11_ST_FLAG_WAITABLE_SWAPCHAINS) swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + #ifdef HAVE_DXGI_HDR if (video_hdr_enable) d3d11->flags |= D3D11_ST_FLAG_HDR_ENABLE; @@ -1896,6 +1921,7 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; if (d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) d3d11_release_texture(&d3d11->back_buffer); + DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0, d3d11->chain_formats[d3d11->chain_bit_depth], swapchain_flags); @@ -1905,16 +1931,17 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; swapchain_flags); #endif - d3d11->viewport.Width = video_width; - d3d11->viewport.Height = video_height; - d3d11->scissor.right = video_width; - d3d11->scissor.bottom = video_height; + d3d11->viewport.Width = video_width; + d3d11->viewport.Height = video_height; + d3d11->scissor.right = video_width; + d3d11->scissor.bottom = video_height; d3d11->ubo_values.OutputSize.width = d3d11->viewport.Width; d3d11->ubo_values.OutputSize.height = d3d11->viewport.Height; - d3d11->flags &= ~D3D11_ST_FLAG_RESIZE_CHAIN; - d3d11->flags |= D3D11_ST_FLAG_RESIZE_VIEWPORT; + d3d11->flags &= ~D3D11_ST_FLAG_RESIZE_CHAIN; + d3d11->flags |= D3D11_ST_FLAG_RESIZE_VIEWPORT; + video_driver_set_size(video_width, video_height); #ifdef HAVE_DXGI_HDR @@ -1970,11 +1997,6 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; d3d11->hdr.max_fall); #endif } - else if (d3d11->flags & D3D11_ST_FLAG_WAITABLE_SWAPCHAINS) - WaitForSingleObjectEx( - d3d11->frameLatencyWaitableObject, - 1000, - true); { D3D11Texture2D back_buffer; @@ -1985,8 +2007,8 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; Release(back_buffer); } - /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ #if 0 + /* Custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ if (d3d11->resize_viewport) #endif d3d11_update_viewport(d3d11, false); @@ -2018,8 +2040,8 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; if (d3d11->shader_preset) { - if (d3d11->frame.texture[0].desc.Width != width || - d3d11->frame.texture[0].desc.Height != height) + if ( (d3d11->frame.texture[0].desc.Width != width) + || (d3d11->frame.texture[0].desc.Height != height)) d3d11->flags |= D3D11_ST_FLAG_RESIZE_RTS; if (d3d11->flags & D3D11_ST_FLAG_RESIZE_RTS) @@ -2049,7 +2071,7 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; } } - /* either no history, or we moved a texture of a different size in the front slot */ + /* Either no history, or we moved a texture of a different size in the front slot */ if ( d3d11->frame.texture[0].desc.Width != width || d3d11->frame.texture[0].desc.Height != height) { @@ -2144,15 +2166,15 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; D3D11_MAPPED_SUBRESOURCE res; uniform_sem_t* uniform = buffer_sem->uniforms; - d3d11->context->lpVtbl->Map( - d3d11->context, (D3D11Resource)buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + d3d11->context->lpVtbl->Map( + d3d11->context, (D3D11Resource)buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &res); while (uniform->size) { if (uniform->data) memcpy((uint8_t*)res.pData + uniform->offset, uniform->data, uniform->size); uniform++; } - context->lpVtbl->Unmap(context, (D3D11Resource)buffer, 0); + context->lpVtbl->Unmap(context, (D3D11Resource)buffer, 0); if (buffer_sem->stage_mask & SLANG_STAGE_VERTEX_MASK) context->lpVtbl->VSSetConstantBuffers(context, @@ -2439,6 +2461,7 @@ D3D11_ST_FLAG_HAS_ALLOW_TEARING)) ? 0 : DXGI_PRESENT_ALLOW_TEARING; IDXGIOutput *pOutput; DXGIGetContainingOutput(d3d11->swapChain, &pOutput); DXGIWaitForVBlank(pOutput); + Release(pOutput); } Release(rtv); @@ -2460,22 +2483,23 @@ static void d3d11_gfx_set_nonblock_state(void* data, d3d11->flags &= ~D3D11_ST_FLAG_VSYNC; else d3d11->flags |= D3D11_ST_FLAG_VSYNC; + d3d11->swap_interval = (!toggle) ? swap_interval : 0; } static bool d3d11_gfx_alive(void* data) { - bool quit; - bool d3d11_resize_chain = false; - d3d11_video_t* d3d11 = (d3d11_video_t*)data; + bool quit; + bool resize_chain = false; + d3d11_video_t* d3d11 = (d3d11_video_t*)data; win32_check_window(NULL, &quit, - &d3d11_resize_chain, + &resize_chain, &d3d11->vp.full_width, &d3d11->vp.full_height); - if (d3d11_resize_chain) + if (resize_chain) d3d11->flags |= D3D11_ST_FLAG_RESIZE_CHAIN; else d3d11->flags &= ~D3D11_ST_FLAG_RESIZE_CHAIN; @@ -2509,7 +2533,8 @@ static void d3d11_gfx_viewport_info(void* data, struct video_viewport* vp) } static void d3d11_set_menu_texture_frame( - void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha) + void* data, const void* frame, bool rgb32, + unsigned width, unsigned height, float alpha) { d3d11_video_t* d3d11 = (d3d11_video_t*)data; settings_t* settings = config_get_ptr(); @@ -2545,13 +2570,14 @@ static void d3d11_set_menu_texture_enable(void* data, bool state, bool full_scre return; if (state) - d3d11->flags |= D3D11_ST_FLAG_MENU_ENABLE; + d3d11->flags |= D3D11_ST_FLAG_MENU_ENABLE; else - d3d11->flags &= ~D3D11_ST_FLAG_MENU_ENABLE; + d3d11->flags &= ~D3D11_ST_FLAG_MENU_ENABLE; + if (full_screen) - d3d11->flags |= D3D11_ST_FLAG_MENU_FULLSCREEN; + d3d11->flags |= D3D11_ST_FLAG_MENU_FULLSCREEN; else - d3d11->flags &= ~D3D11_ST_FLAG_MENU_FULLSCREEN; + d3d11->flags &= ~D3D11_ST_FLAG_MENU_FULLSCREEN; } static void d3d11_gfx_set_aspect_ratio(void* data, unsigned aspect_ratio_idx) @@ -2566,7 +2592,7 @@ static void d3d11_gfx_apply_state_changes(void* data) { d3d11_video_t* d3d11 = (d3d11_video_t*)data; if (d3d11) - d3d11->flags |= D3D11_ST_FLAG_RESIZE_VIEWPORT; + d3d11->flags |= D3D11_ST_FLAG_RESIZE_VIEWPORT; } static void d3d11_gfx_set_osd_msg( @@ -2632,6 +2658,7 @@ static uintptr_t d3d11_gfx_load_texture( return (uintptr_t)texture; } + static void d3d11_gfx_unload_texture(void* data, bool threaded, uintptr_t handle) { diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 58db14a32e..57343d759f 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -93,7 +93,6 @@ static D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc = { /* Temporary workaround for d3d12 not being able to poll flags during init */ static gfx_ctx_driver_t d3d12_fake_context; -static uint32_t d3d12_get_flags(void *data); static void d3d12_gfx_sync(d3d12_video_t* d3d12) { @@ -106,6 +105,20 @@ static void d3d12_gfx_sync(d3d12_video_t* d3d12) } } +static uint32_t d3d12_get_flags(void *data) +{ + uint32_t flags = 0; + + BIT32_SET(flags, GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY); + BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); + BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED); +#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) + BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG); +#endif + + return flags; +} + #ifdef HAVE_OVERLAY static void d3d12_free_overlays(d3d12_video_t* d3d12) { @@ -490,15 +503,10 @@ static void d3d12_update_viewport(d3d12_video_t *d3d12, bool force_full) d3d12->frame.viewport.MaxDepth = 0.0f; d3d12->frame.viewport.MaxDepth = 1.0f; - /* having to add vp.x and vp.y here doesn't make any sense */ - d3d12->frame.scissorRect.top = d3d12->vp.y; - d3d12->frame.scissorRect.left = d3d12->vp.x; - d3d12->frame.scissorRect.right = d3d12->vp.x + d3d12->vp.width; - d3d12->frame.scissorRect.bottom = d3d12->vp.y + d3d12->vp.height; - - if (d3d12->shader_preset && (d3d12->frame.output_size.x != d3d12->vp.width || - d3d12->frame.output_size.y != d3d12->vp.height)) - d3d12->flags |= D3D12_ST_FLAG_RESIZE_RTS; + if (d3d12->shader_preset + && ( d3d12->frame.output_size.x != d3d12->vp.width + || d3d12->frame.output_size.y != d3d12->vp.height)) + d3d12->flags |= D3D12_ST_FLAG_RESIZE_RTS; d3d12->frame.output_size.x = d3d12->vp.width; d3d12->frame.output_size.y = d3d12->vp.height; @@ -511,6 +519,7 @@ static void d3d12_update_viewport(d3d12_video_t *d3d12, bool force_full) static void d3d12_free_shader_preset(d3d12_video_t* d3d12) { size_t i; + if (!d3d12->shader_preset) return; @@ -555,7 +564,8 @@ static void d3d12_free_shader_preset(d3d12_video_t* d3d12) free(d3d12->shader_preset); d3d12->shader_preset = NULL; d3d12->flags &= ~(D3D12_ST_FLAG_INIT_HISTORY - | D3D12_ST_FLAG_RESIZE_RTS); + | D3D12_ST_FLAG_RESIZE_RTS + ); } static void d3d12_init_pipeline( @@ -813,8 +823,8 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const image_texture_free(&image); } - d3d12->flags |= (D3D12_ST_FLAG_INIT_HISTORY - | D3D12_ST_FLAG_RESIZE_RTS); + d3d12->flags |= D3D12_ST_FLAG_INIT_HISTORY | D3D12_ST_FLAG_RESIZE_RTS; + return true; error: @@ -1125,14 +1135,17 @@ static void d3d12_gfx_free(void* data) d3d12_gfx_sync(d3d12); + if (d3d12->flags & D3D12_ST_FLAG_WAITABLE_SWAPCHAINS) + CloseHandle(d3d12->chain.frameLatencyWaitableObject); + + font_driver_free_osd(); + #ifdef HAVE_OVERLAY d3d12_free_overlays(d3d12); #endif d3d12_free_shader_preset(d3d12); - font_driver_free_osd(); - Release(d3d12->sprites.vbo); Release(d3d12->menu_pipeline_vbo); @@ -1174,14 +1187,18 @@ static void d3d12_gfx_free(void* data) Release(d3d12->sprites.pipe_font); Release(d3d12->queue.fence); - Release(d3d12->chain.renderTargets[0]); - Release(d3d12->chain.renderTargets[1]); - Release(d3d12->chain.handle); - Release(d3d12->queue.cmd); Release(d3d12->queue.allocator); Release(d3d12->queue.handle); + Release(d3d12->chain.renderTargets[0]); + Release(d3d12->chain.renderTargets[1]); + +#if 0 + /* Releasing this will crash eventually (?!) */ + Release(d3d12->chain.handle); +#endif + Release(d3d12->factory); Release(d3d12->device); Release(d3d12->adapter); @@ -1309,7 +1326,6 @@ static bool d3d12_init_swapchain(d3d12_video_t* d3d12, RARCH_LOG("[D3D12]: Requesting %u maximum frame latency, using %u.\n", max_latency, cur_latency); } - #ifdef HAVE_WINDOW DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER); #endif @@ -1366,6 +1382,7 @@ static bool d3d12_init_swapchain(d3d12_video_t* d3d12, d3d12->chain.viewport.Width = width; d3d12->chain.viewport.Height = height; + d3d12->chain.scissorRect.left = d3d12->vp.x; d3d12->chain.scissorRect.top = d3d12->vp.y; d3d12->chain.scissorRect.right = d3d12->vp.x + width; @@ -1920,16 +1937,22 @@ static void *d3d12_gfx_init(const video_info_t* video, video_driver_set_size(d3d12->vp.full_width, d3d12->vp.full_height); d3d12->chain.viewport.Width = d3d12->vp.full_width; d3d12->chain.viewport.Height = d3d12->vp.full_height; + d3d12->flags |= D3D12_ST_FLAG_RESIZE_VIEWPORT; + if (video->force_aspect) d3d12->flags |= D3D12_ST_FLAG_KEEP_ASPECT; else d3d12->flags &= ~D3D12_ST_FLAG_KEEP_ASPECT; + if (video->vsync) d3d12->flags |= D3D12_ST_FLAG_VSYNC; else d3d12->flags &= ~D3D12_ST_FLAG_VSYNC; - d3d12->format = (video->rgb32) ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; + + d3d12->format = (video->rgb32) + ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; + d3d12->frame.texture[0].desc.Format = d3d12->format; d3d12->frame.texture[0].desc.Width = 4; d3d12->frame.texture[0].desc.Height = 4; @@ -1983,13 +2006,13 @@ static void d3d12_init_history(d3d12_video_t* d3d12, unsigned width, unsigned he static void d3d12_init_render_targets(d3d12_video_t* d3d12, unsigned width, unsigned height) { size_t i; + for (i = 0; i < d3d12->shader_preset->passes; i++) { struct video_shader_pass* pass = &d3d12->shader_preset->pass[i]; if (pass->fbo.flags & FBO_SCALE_FLAG_VALID) { - switch (pass->fbo.type_x) { case RARCH_SCALE_INPUT: @@ -2067,8 +2090,9 @@ static void d3d12_init_render_targets(d3d12_video_t* d3d12, unsigned width, unsi d3d12->pass[i].scissorRect.bottom = height; } - if ((i != (d3d12->shader_preset->passes - 1)) || (width != d3d12->vp.width) || - (height != d3d12->vp.height)) + if ( (i != (d3d12->shader_preset->passes - 1)) + || (width != d3d12->vp.width) + || (height != d3d12->vp.height)) { d3d12->pass[i].rt.desc.Width = width; d3d12->pass[i].rt.desc.Height = height; @@ -2114,12 +2138,11 @@ static bool d3d12_gfx_frame( const char* msg, video_frame_info_t* video_info) { - unsigned i; + unsigned i; d3d12_texture_t* texture = NULL; d3d12_video_t* d3d12 = (d3d12_video_t*)data; bool vsync = d3d12->flags & D3D12_ST_FLAG_VSYNC; bool wait_for_vblank = d3d12->flags & D3D12_ST_FLAG_WAIT_FOR_VBLANK; - unsigned sync_interval = (vsync) ? d3d12->chain.swap_interval : 0; unsigned present_flags = (vsync) ? 0 : DXGI_PRESENT_ALLOW_TEARING; const char *stat_text = video_info->stat_text; bool statistics_show = video_info->statistics_show; @@ -2139,15 +2162,27 @@ static bool d3d12_gfx_frame( bool use_back_buffer = back_buffer_format != d3d12->chain.formats[d3d12->chain.bit_depth]; #endif + if (d3d12->flags & D3D12_ST_FLAG_WAITABLE_SWAPCHAINS) + WaitForSingleObjectEx( + d3d12->chain.frameLatencyWaitableObject, + 1000, + true); + d3d12_gfx_sync(d3d12); #ifdef HAVE_DXGI_HDR d3d12_hdr_enable = d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE; - if ((d3d12->flags & D3D12_ST_FLAG_RESIZE_CHAIN) || (d3d12_hdr_enable != video_hdr_enable)) + if ( (d3d12->flags & D3D12_ST_FLAG_RESIZE_CHAIN) + || (d3d12_hdr_enable != video_hdr_enable)) #else if (d3d12->flags & D3D12_ST_FLAG_RESIZE_CHAIN) #endif { + UINT swapchain_flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + + if (d3d12->flags & D3D12_ST_FLAG_WAITABLE_SWAPCHAINS) + swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + #ifdef HAVE_DXGI_HDR if (video_hdr_enable) d3d12->flags |= D3D12_ST_FLAG_HDR_ENABLE; @@ -2164,19 +2199,20 @@ static bool d3d12_gfx_frame( d3d12_release_texture(&d3d12->chain.back_buffer); d3d12->chain.back_buffer.handle = NULL; } + DXGIResizeBuffers(d3d12->chain.handle, countof(d3d12->chain.renderTargets), video_width, video_height, d3d12->chain.formats[d3d12->chain.bit_depth], - DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING); + swapchain_flags); #else DXGIResizeBuffers(d3d12->chain.handle, 0, 0, 0, DXGI_FORMAT_UNKNOWN, - DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING); + swapchain_flags); #endif for (i = 0; i < countof(d3d12->chain.renderTargets); i++) @@ -2190,16 +2226,18 @@ static bool d3d12_gfx_frame( d3d12->chain.viewport.Width = video_width; d3d12->chain.viewport.Height = video_height; - d3d12->chain.scissorRect.left = d3d12->vp.x; - d3d12->chain.scissorRect.top = d3d12->vp.y; - d3d12->chain.scissorRect.right = d3d12->vp.x + video_width; - d3d12->chain.scissorRect.bottom = d3d12->vp.y + video_height; - d3d12->flags &= ~D3D12_ST_FLAG_RESIZE_CHAIN; - d3d12->flags |= D3D12_ST_FLAG_RESIZE_VIEWPORT; + + d3d12->chain.scissorRect.left = 0; + d3d12->chain.scissorRect.top = 0; + d3d12->chain.scissorRect.right = d3d12->vp.full_width; + d3d12->chain.scissorRect.bottom = d3d12->vp.full_height; d3d12->ubo_values.OutputSize.width = d3d12->chain.viewport.Width; d3d12->ubo_values.OutputSize.height = d3d12->chain.viewport.Height; + d3d12->flags &= ~D3D12_ST_FLAG_RESIZE_CHAIN; + d3d12->flags |= D3D12_ST_FLAG_RESIZE_VIEWPORT; + video_driver_set_size(video_width, video_height); #ifdef HAVE_DXGI_HDR @@ -2262,13 +2300,6 @@ static bool d3d12_gfx_frame( d3d12->hdr.max_fall); #endif } - else if (d3d12->flags & D3D12_ST_FLAG_WAITABLE_SWAPCHAINS) - { - WaitForSingleObjectEx( - d3d12->chain.frameLatencyWaitableObject, - 1000, - true); - } D3D12ResetCommandAllocator(d3d12->queue.allocator); @@ -2284,11 +2315,10 @@ static bool d3d12_gfx_frame( } #if 0 - /* Custom viewport doesn't call apply_state_changes, - so we can't rely on this for now */ + /* Custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ if (d3d12->resize_viewport) #endif - d3d12_update_viewport(d3d12, false); + d3d12_update_viewport(d3d12, false); D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); @@ -2302,14 +2332,13 @@ static bool d3d12_gfx_frame( d3d12_upload_texture(d3d12->queue.cmd, &d3d12->luts[i], d3d12); - if ( (d3d12->frame.texture[0].desc.Width != width) - || (d3d12->frame.texture[0].desc.Height != height)) - d3d12->flags |= D3D12_ST_FLAG_RESIZE_RTS; + if ( (d3d12->frame.texture[0].desc.Width != width) + || (d3d12->frame.texture[0].desc.Height != height)) + d3d12->flags |= D3D12_ST_FLAG_RESIZE_RTS; if (d3d12->flags & D3D12_ST_FLAG_RESIZE_RTS) { - /* Release all render targets first - to avoid memory fragmentation */ + /* Release all Render Targets (RT) first to avoid memory fragmentation */ for (i = 0; i < d3d12->shader_preset->passes; i++) { d3d12_release_texture(&d3d12->pass[i].rt); @@ -2337,10 +2366,9 @@ static bool d3d12_gfx_frame( } } - /* Either no history, or we moved a texture - of a different size in the front slot */ - if (d3d12->frame.texture[0].desc.Width != width || - d3d12->frame.texture[0].desc.Height != height) + /* Either no history, or we moved a texture of a different size in the front slot */ + if ( d3d12->frame.texture[0].desc.Width != width + || d3d12->frame.texture[0].desc.Height != height) { d3d12->frame.texture[0].desc.Width = width; d3d12->frame.texture[0].desc.Height = height; @@ -2514,7 +2542,7 @@ static bool d3d12_gfx_frame( { D3D12_RESOURCE_TRANSITION( d3d12->queue.cmd, - d3d12->pass[i].rt.handle, + d3d12->pass[i].rt.handle, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); @@ -2537,7 +2565,7 @@ static bool d3d12_gfx_frame( D3D12_RESOURCE_TRANSITION( d3d12->queue.cmd, - d3d12->pass[i].rt.handle, + d3d12->pass[i].rt.handle, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); texture = &d3d12->pass[i].rt; @@ -2557,12 +2585,11 @@ static bool d3d12_gfx_frame( D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature); D3D12SetGraphicsRootDescriptorTable(d3d12->queue.cmd, - ROOT_ID_TEXTURE_T, - d3d12->frame.texture[0].gpu_descriptor[0]); + ROOT_ID_TEXTURE_T, + d3d12->frame.texture[0].gpu_descriptor[0]); D3D12SetGraphicsRootDescriptorTable(d3d12->queue.cmd, - ROOT_ID_SAMPLER_T, - d3d12->samplers[ - RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); + ROOT_ID_SAMPLER_T, + d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); D3D12SetGraphicsRootConstantBufferView( d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation); @@ -2576,13 +2603,14 @@ static bool d3d12_gfx_frame( { D3D12_RESOURCE_TRANSITION( d3d12->queue.cmd, - d3d12->chain.back_buffer.handle, + d3d12->chain.back_buffer.handle, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); D3D12OMSetRenderTargets( d3d12->queue.cmd, 1, - &d3d12->chain.back_buffer.rt_view, FALSE, NULL); + &d3d12->chain.back_buffer.rt_view, + FALSE, NULL); /* TODO/FIXME - fix this warning that shows up with Debug logging * EXECUTIONWARNING #820: CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE * We need to set clear value during resource creation to NULL for @@ -2590,8 +2618,10 @@ static bool d3d12_gfx_frame( * warning */ D3D12ClearRenderTargetView( - d3d12->queue.cmd, d3d12->chain.back_buffer.rt_view, - d3d12->chain.clearcolor, 0, NULL); + d3d12->queue.cmd, + d3d12->chain.back_buffer.rt_view, + d3d12->chain.clearcolor, + 0, NULL); } else #endif @@ -2609,7 +2639,8 @@ static bool d3d12_gfx_frame( D3D12ClearRenderTargetView( d3d12->queue.cmd, d3d12->chain.desc_handles[d3d12->chain.frame_index], - d3d12->chain.clearcolor, 0, NULL); + d3d12->chain.clearcolor, + 0, NULL); } D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport); @@ -2638,11 +2669,11 @@ static bool d3d12_gfx_frame( } D3D12SetGraphicsRootDescriptorTable(d3d12->queue.cmd, - ROOT_ID_TEXTURE_T, - d3d12->menu.texture.gpu_descriptor[0]); + ROOT_ID_TEXTURE_T, + d3d12->menu.texture.gpu_descriptor[0]); D3D12SetGraphicsRootDescriptorTable(d3d12->queue.cmd, - ROOT_ID_SAMPLER_T, - d3d12->menu.texture.sampler); + ROOT_ID_SAMPLER_T, + d3d12->menu.texture.sampler); D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->menu.vbo_view); D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0); } @@ -2719,45 +2750,48 @@ static bool d3d12_gfx_frame( } d3d12->flags &= ~D3D12_ST_FLAG_SPRITES_ENABLE; +#if defined(_WIN32) && !defined(__WINRT__) + win32_update_title(); +#endif + #ifdef HAVE_DXGI_HDR /* Copy over back buffer to swap chain render targets */ if ((d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE) && use_back_buffer) { D3D12_RESOURCE_TRANSITION( - d3d12->queue.cmd, - d3d12->chain.renderTargets[d3d12->chain.frame_index], - D3D12_RESOURCE_STATE_PRESENT, - D3D12_RESOURCE_STATE_RENDER_TARGET); + d3d12->queue.cmd, + d3d12->chain.renderTargets[d3d12->chain.frame_index], + D3D12_RESOURCE_STATE_PRESENT, + D3D12_RESOURCE_STATE_RENDER_TARGET); D3D12_RESOURCE_TRANSITION( - d3d12->queue.cmd, - d3d12->chain.back_buffer.handle, - D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + d3d12->queue.cmd, + d3d12->chain.back_buffer.handle, + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[VIDEO_SHADER_STOCK_HDR]); D3D12OMSetRenderTargets( - d3d12->queue.cmd, 1, - &d3d12->chain.desc_handles[d3d12->chain.frame_index], - FALSE, NULL); + d3d12->queue.cmd, 1, + &d3d12->chain.desc_handles[d3d12->chain.frame_index], + FALSE, NULL); D3D12ClearRenderTargetView( - d3d12->queue.cmd, - d3d12->chain.desc_handles[d3d12->chain.frame_index], - d3d12->chain.clearcolor, 0, NULL); + d3d12->queue.cmd, + d3d12->chain.desc_handles[d3d12->chain.frame_index], + d3d12->chain.clearcolor, 0, NULL); D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature); D3D12SetGraphicsRootDescriptorTable(d3d12->queue.cmd, - ROOT_ID_TEXTURE_T, - d3d12->chain.back_buffer.gpu_descriptor[0]); + ROOT_ID_TEXTURE_T, + d3d12->chain.back_buffer.gpu_descriptor[0]); D3D12SetGraphicsRootDescriptorTable(d3d12->queue.cmd, - ROOT_ID_SAMPLER_T, - d3d12->samplers[ - RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); + ROOT_ID_SAMPLER_T, + d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); D3D12SetGraphicsRootConstantBufferView( - d3d12->queue.cmd, ROOT_ID_UBO, - d3d12->hdr.ubo_view.BufferLocation); + d3d12->queue.cmd, ROOT_ID_UBO, + d3d12->hdr.ubo_view.BufferLocation); D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->frame.vbo_view); @@ -2784,36 +2818,40 @@ static bool d3d12_gfx_frame( D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1, &d3d12->queue.cmd); -#if defined(_WIN32) && !defined(__WINRT__) - win32_update_title(); -#endif - DXGIPresent(d3d12->chain.handle, sync_interval, present_flags); + DXGIPresent(d3d12->chain.handle, d3d12->chain.swap_interval, present_flags); if (vsync && wait_for_vblank) { IDXGIOutput *pOutput; DXGIGetContainingOutput(d3d12->chain.handle, &pOutput); DXGIWaitForVBlank(pOutput); + Release(pOutput); } return true; } -static void d3d12_gfx_set_nonblock_state(void* data, bool toggle, +static void d3d12_gfx_set_nonblock_state(void* data, + bool toggle, bool adaptive_vsync_enabled, unsigned swap_interval) { d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + if (!d3d12) + return; + if (toggle) d3d12->flags &= ~D3D12_ST_FLAG_VSYNC; else d3d12->flags |= D3D12_ST_FLAG_VSYNC; - d3d12->chain.swap_interval = swap_interval; + + d3d12->chain.swap_interval = (!toggle) ? swap_interval : 0; } static bool d3d12_gfx_alive(void* data) { - bool quit; + bool quit; bool resize_chain = false; d3d12_video_t* d3d12 = (d3d12_video_t*)data; @@ -2906,7 +2944,7 @@ static void d3d12_set_menu_texture_frame( static void d3d12_set_menu_texture_enable(void* data, bool state, bool fullscreen) { - d3d12_video_t* d3d12 = (d3d12_video_t*)data; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; if (!d3d12) return; @@ -2925,6 +2963,7 @@ static void d3d12_gfx_set_aspect_ratio( void* data, unsigned aspect_ratio_idx) { d3d12_video_t* d3d12 = (d3d12_video_t*)data; + if (d3d12) d3d12->flags |= D3D12_ST_FLAG_KEEP_ASPECT | D3D12_ST_FLAG_RESIZE_VIEWPORT; } @@ -2943,8 +2982,10 @@ static void d3d12_gfx_set_osd_msg( void* font) { d3d12_video_t* d3d12 = (d3d12_video_t*)data; + if (d3d12 && (d3d12->flags & D3D12_ST_FLAG_SPRITES_ENABLE)) - font_driver_render_msg(d3d12, msg, + font_driver_render_msg(d3d12, + msg, (const struct font_params*)params, font); } @@ -2994,6 +3035,7 @@ static uintptr_t d3d12_gfx_load_texture( return (uintptr_t)texture; } + static void d3d12_gfx_unload_texture(void* data, bool threaded, uintptr_t handle) { @@ -3007,20 +3049,6 @@ static void d3d12_gfx_unload_texture(void* data, free(texture); } -static uint32_t d3d12_get_flags(void *data) -{ - uint32_t flags = 0; - - BIT32_SET(flags, GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY); - BIT32_SET(flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING); - BIT32_SET(flags, GFX_CTX_FLAGS_OVERLAY_BEHIND_MENU_SUPPORTED); -#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) - BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG); -#endif - - return flags; -} - #ifndef __WINRT__ static void d3d12_get_video_output_size(void *data, unsigned *width, unsigned *height, char *desc, size_t desc_len) @@ -3080,7 +3108,7 @@ static const video_poke_interface_t d3d12_poke_interface = { d3d12_set_hdr_max_nits, d3d12_set_hdr_paper_white_nits, d3d12_set_hdr_contrast, - d3d12_set_hdr_expand_gamut, + d3d12_set_hdr_expand_gamut #else NULL, /* set_hdr_max_nits */ NULL, /* set_hdr_paper_white_nits */