From c7d0096356d525f2de7578e0955ef3877d51a882 Mon Sep 17 00:00:00 2001 From: MajorPainTheCactus Date: Sun, 25 Jan 2026 18:17:06 +0000 Subject: [PATCH 1/3] Fixed menu system displaying incorrectly in HDR on D3D11, D3D12 and Vulkan --- gfx/drivers/d3d11.c | 71 +++++---- gfx/drivers/d3d12.c | 199 +++++++++++-------------- gfx/drivers/d3d_shaders/hdr_sm5.hlsl.h | 1 - gfx/drivers/vulkan.c | 163 ++++++++++++++------ gfx/video_driver.h | 19 +-- 5 files changed, 258 insertions(+), 195 deletions(-) diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 6b208b721509..3e9f042da8e5 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -1630,7 +1630,7 @@ static void d3d11_set_hdr_paper_white_nits(void* data, float paper_white_nits) { for (unsigned i = 0; i < d3d11->shader_preset->passes; i++) { - d3d11->pass[i].paper_white_nits = paper_white_nits; + d3d11->pass[i].paper_white_nits = paper_white_nits; } } } @@ -3305,7 +3305,6 @@ static bool d3d11_gfx_frame( bool d3d11_hdr_enable = (d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) ? true : false; 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) : d3d11->chain_formats[d3d11->chain_bit_depth]; - bool use_back_buffer = back_buffer_format != d3d11->chain_formats[d3d11->chain_bit_depth]; #endif if (d3d11->flags & D3D11_ST_FLAG_WAITABLE_SWAPCHAINS) @@ -3736,30 +3735,15 @@ static bool d3d11_gfx_frame( } } - -#ifdef HAVE_DXGI_HDR - if ( (d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) - && use_back_buffer) - { - context->lpVtbl->OMSetRenderTargets(context, 1, - &d3d11->back_buffer.rt_view, NULL); - context->lpVtbl->ClearRenderTargetView(context, - d3d11->back_buffer.rt_view, d3d11->clearcolor); - } - else -#endif - { - context->lpVtbl->OMSetRenderTargets(context, 1, &rtv, NULL); - context->lpVtbl->ClearRenderTargetView(context, rtv, d3d11->clearcolor); - } + context->lpVtbl->OMSetRenderTargets(context, 1, &rtv, NULL); + context->lpVtbl->ClearRenderTargetView(context, rtv, d3d11->clearcolor); context->lpVtbl->RSSetViewports(context, 1, &d3d11->frame.viewport); if (texture) { #ifdef HAVE_DXGI_HDR - if ((d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) - && !use_back_buffer) + if (d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) { d3d11_shader_t *shader = &d3d11->shaders[VIDEO_SHADER_STOCK_HDR]; context->lpVtbl->IASetInputLayout(context, shader->layout); @@ -3767,8 +3751,6 @@ static bool d3d11_gfx_frame( context->lpVtbl->PSSetShader(context, shader->ps, NULL, 0); context->lpVtbl->GSSetShader(context, shader->gs, NULL, 0); - if( d3d11->hdr.ubo_values.source_size.width != width || d3d11->hdr.ubo_values.source_size.height != height || - d3d11->hdr.ubo_values.output_size.width != d3d11->frame.output_size.x || d3d11->hdr.ubo_values.output_size.height != d3d11->frame.output_size.y) { d3d11->hdr.ubo_values.source_size.width = width; d3d11->hdr.ubo_values.source_size.height = height; @@ -3776,10 +3758,13 @@ static bool d3d11_gfx_frame( d3d11->hdr.ubo_values.output_size.width = d3d11->frame.output_size.x; d3d11->hdr.ubo_values.output_size.height = d3d11->frame.output_size.y; + settings_t* settings = config_get_ptr(); + d3d11->hdr.ubo_values.scanlines = settings->bools.video_hdr_scanlines ? 1.0f : 0.0f; + D3D11_MAPPED_SUBRESOURCE mapped_ubo; d3d11->context->lpVtbl->Map( - d3d11->context, (D3D11Resource)d3d11->hdr.ubo, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_ubo); + d3d11->context, (D3D11Resource)d3d11->hdr.ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo); { dxgi_hdr_uniform_t *ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData; *ubo = d3d11->hdr.ubo_values; @@ -3837,6 +3822,19 @@ static bool d3d11_gfx_frame( context->lpVtbl->Draw(context, 4, 0); +#ifdef HAVE_DXGI_HDR + if((d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) && + (d3d11->flags & D3D11_ST_FLAG_MENU_ENABLE)) + { + context->lpVtbl->OMSetRenderTargets(context, 1, + &d3d11->back_buffer.rt_view, NULL); + + float clear_colour[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + context->lpVtbl->ClearRenderTargetView(context, + d3d11->back_buffer.rt_view, clear_colour); + } +#endif + context->lpVtbl->RSSetState(context, d3d11->scissor_enabled); d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1, &d3d11->scissor); context->lpVtbl->OMSetBlendState(context, d3d11->blend_enable, @@ -3973,12 +3971,11 @@ static bool d3d11_gfx_frame( #ifdef HAVE_DXGI_HDR /* Copy over back buffer to swap chain render targets */ - if ( (d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) - && use_back_buffer) + if((d3d11->flags & D3D11_ST_FLAG_HDR_ENABLE) && + (d3d11->flags & D3D11_ST_FLAG_MENU_ENABLE)) { ID3D11ShaderResourceView* nullSRV[1] = {NULL}; context->lpVtbl->OMSetRenderTargets(context, 1, &rtv, NULL); - context->lpVtbl->ClearRenderTargetView(context, rtv, d3d11->clearcolor); context->lpVtbl->RSSetViewports(context, 1, &d3d11->viewport); context->lpVtbl->RSSetScissorRects(context, 1, &d3d11->scissor); @@ -3989,15 +3986,29 @@ static bool d3d11_gfx_frame( context->lpVtbl->PSSetShader(context, shader->ps, NULL, 0); context->lpVtbl->GSSetShader(context, shader->gs, NULL, 0); } + + { + d3d11->hdr.ubo_values.scanlines = false; + + D3D11_MAPPED_SUBRESOURCE mapped_ubo; + + d3d11->context->lpVtbl->Map( + d3d11->context, (D3D11Resource)d3d11->hdr.ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo); + { + dxgi_hdr_uniform_t *ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData; + *ubo = d3d11->hdr.ubo_values; + } + d3d11->context->lpVtbl->Unmap(d3d11->context, (D3D11Resource)d3d11->hdr.ubo, 0); + } + context->lpVtbl->VSSetConstantBuffers(context, 0, 1, &d3d11->hdr.ubo); + context->lpVtbl->PSSetConstantBuffers(context, 0, 1, &d3d11->hdr.ubo); context->lpVtbl->PSSetShaderResources( context, 0, 1, &d3d11->back_buffer.view); context->lpVtbl->PSSetSamplers( context, 0, 1, &d3d11->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); - context->lpVtbl->PSSetConstantBuffers( - context, 0, 1, &d3d11->hdr.ubo); { UINT stride = sizeof(d3d11_vertex_t); UINT offset = 0; @@ -4006,7 +4017,7 @@ static bool d3d11_gfx_frame( } context->lpVtbl->RSSetState(context, d3d11->scissor_disabled); - d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_disable, + d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK); context->lpVtbl->IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); @@ -4016,8 +4027,6 @@ static bool d3d11_gfx_frame( context->lpVtbl->PSSetShaderResources( context, 0, 1, nullSRV); context->lpVtbl->RSSetState(context, d3d11->scissor_enabled); - d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_enable, - NULL, D3D11_DEFAULT_SAMPLE_MASK); context->lpVtbl->IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); } diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index a07f2de1d3bc..204f6dd5a951 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -335,6 +335,8 @@ typedef struct dxgi_hdr_uniform_t ubo_values; D3D12Resource ubo; D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view; + D3D12Resource ubo_post; + D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_post_view; float max_output_nits; float min_output_nits; float max_cll; @@ -1846,19 +1848,11 @@ static void d3d12_render_overlay(d3d12_video_t *d3d12) #ifdef HAVE_DXGI_HDR static void d3d12_set_hdr_max_nits(void* data, float max_nits) { - D3D12_RANGE read_range; - dxgi_hdr_uniform_t *mapped_ubo = NULL; d3d12_video_t *d3d12 = (d3d12_video_t*)data; d3d12->hdr.max_output_nits = max_nits; d3d12->hdr.ubo_values.max_nits = max_nits; - read_range.Begin = 0; - read_range.End = 0; - D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo); - *mapped_ubo = d3d12->hdr.ubo_values; - D3D12Unmap(d3d12->hdr.ubo, 0, NULL); - dxgi_set_hdr_metadata( d3d12->chain.handle, (d3d12->flags & D3D12_ST_FLAG_HDR_SUPPORT) ? true : false, @@ -1880,17 +1874,9 @@ static void d3d12_set_hdr_max_nits(void* data, float max_nits) static void d3d12_set_hdr_paper_white_nits(void* data, float paper_white_nits) { - D3D12_RANGE read_range; - dxgi_hdr_uniform_t *mapped_ubo = NULL; d3d12_video_t *d3d12 = (d3d12_video_t*)data; d3d12->hdr.ubo_values.paper_white_nits = paper_white_nits; - - read_range.Begin = 0; - read_range.End = 0; - D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo); - *mapped_ubo = d3d12->hdr.ubo_values; - D3D12Unmap(d3d12->hdr.ubo, 0, NULL); if(d3d12->shader_preset) { @@ -1903,17 +1889,9 @@ static void d3d12_set_hdr_paper_white_nits(void* data, float paper_white_nits) static void d3d12_set_hdr_expand_gamut(void* data, bool expand_gamut) { - D3D12_RANGE read_range; - dxgi_hdr_uniform_t *mapped_ubo = NULL; d3d12_video_t *d3d12 = (d3d12_video_t*)data; d3d12->hdr.ubo_values.expand_gamut = expand_gamut ? 1.0f : 0.0f; - - read_range.Begin = 0; - read_range.End = 0; - D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo); - *mapped_ubo = d3d12->hdr.ubo_values; - D3D12Unmap(d3d12->hdr.ubo, 0, NULL); if(d3d12->shader_preset) { @@ -1926,17 +1904,9 @@ static void d3d12_set_hdr_expand_gamut(void* data, bool expand_gamut) static void d3d12_set_hdr_scanlines(void* data, bool scanlines) { - D3D12_RANGE read_range; - dxgi_hdr_uniform_t *mapped_ubo = NULL; d3d12_video_t *d3d12 = (d3d12_video_t*)data; d3d12->hdr.ubo_values.scanlines = scanlines ? 1.0f : 0.0f; - - read_range.Begin = 0; - read_range.End = 0; - D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo); - *mapped_ubo = d3d12->hdr.ubo_values; - D3D12Unmap(d3d12->hdr.ubo, 0, NULL); if(d3d12->shader_preset) { @@ -1949,17 +1919,9 @@ static void d3d12_set_hdr_scanlines(void* data, bool scanlines) static void d3d12_set_hdr_subpixel_layout(void* data, unsigned subpixel_layout) { - D3D12_RANGE read_range; - dxgi_hdr_uniform_t *mapped_ubo = NULL; d3d12_video_t *d3d12 = (d3d12_video_t*)data; d3d12->hdr.ubo_values.subpixel_layout = subpixel_layout; - - read_range.Begin = 0; - read_range.End = 0; - D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo); - *mapped_ubo = d3d12->hdr.ubo_values; - D3D12Unmap(d3d12->hdr.ubo, 0, NULL); if(d3d12->shader_preset) { @@ -1972,16 +1934,7 @@ static void d3d12_set_hdr_subpixel_layout(void* data, unsigned subpixel_layout) static void d3d12_set_hdr_inverse_tonemap(d3d12_video_t* d3d12, bool inverse_tonemap) { - D3D12_RANGE read_range; - dxgi_hdr_uniform_t *mapped_ubo = NULL; - d3d12->hdr.ubo_values.inverse_tonemap = inverse_tonemap ? 1.0f : 0.0f; - - read_range.Begin = 0; - read_range.End = 0; - D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo); - *mapped_ubo = d3d12->hdr.ubo_values; - D3D12Unmap(d3d12->hdr.ubo, 0, NULL); if(d3d12->shader_preset) { @@ -1994,16 +1947,7 @@ static void d3d12_set_hdr_inverse_tonemap(d3d12_video_t* d3d12, bool inverse_ton static void d3d12_set_hdr10(d3d12_video_t* d3d12, bool hdr10) { - D3D12_RANGE read_range; - dxgi_hdr_uniform_t *mapped_ubo = NULL; - d3d12->hdr.ubo_values.hdr10 = hdr10 ? 1.0f : 0.0f; - - read_range.Begin = 0; - read_range.End = 0; - D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo); - *mapped_ubo = d3d12->hdr.ubo_values; - D3D12Unmap(d3d12->hdr.ubo, 0, NULL); if(d3d12->shader_preset) { @@ -2461,7 +2405,7 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) settings_t * settings = config_get_ptr(); D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { d3d12->desc.rootSignature }; - desc.BlendState.RenderTarget[0] = d3d12_blend_disable_desc; + desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc; #ifdef HAVE_DXGI_HDR desc.RTVFormats[0] = DXGI_FORMAT_R10G10B10A2_UNORM; @@ -2492,6 +2436,12 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_STOCK_HDR]); + desc.BlendState.RenderTarget[0] = d3d12_blend_disable_desc; + + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, + &d3d12->pipes[VIDEO_SHADER_STOCK_NOBLEND_HDR]); + Release(vs_code); Release(ps_code); vs_code = NULL; @@ -2777,6 +2727,7 @@ static void d3d12_gfx_free(void* data) #ifdef HAVE_DXGI_HDR Release(d3d12->hdr.ubo); + Release(d3d12->hdr.ubo_post); #endif Release(d3d12->frame.ubo); @@ -3536,13 +3487,16 @@ static void *d3d12_gfx_init(const video_info_t* video, } #ifdef HAVE_DXGI_HDR - d3d12->hdr.ubo_view.SizeInBytes = sizeof(dxgi_hdr_uniform_t); - d3d12->hdr.ubo_view.BufferLocation = + d3d12->hdr.ubo_view.SizeInBytes = sizeof(dxgi_hdr_uniform_t); + d3d12->hdr.ubo_view.BufferLocation = d3d12_create_buffer(d3d12->device, d3d12->hdr.ubo_view.SizeInBytes, &d3d12->hdr.ubo); + d3d12->hdr.ubo_post_view.SizeInBytes = sizeof(dxgi_hdr_uniform_t); + d3d12->hdr.ubo_post_view.BufferLocation = + d3d12_create_buffer(d3d12->device, d3d12->hdr.ubo_post_view.SizeInBytes, &d3d12->hdr.ubo_post); - d3d12->hdr.ubo_values.mvp = d3d12->mvp_no_rot; - d3d12->hdr.ubo_values.max_nits = settings->floats.video_hdr_max_nits; - d3d12->hdr.ubo_values.paper_white_nits = settings->floats.video_hdr_paper_white_nits; + d3d12->hdr.ubo_values.mvp = d3d12->mvp_no_rot; + d3d12->hdr.ubo_values.max_nits = settings->floats.video_hdr_max_nits; + d3d12->hdr.ubo_values.paper_white_nits = settings->floats.video_hdr_paper_white_nits; d3d12->hdr.ubo_values.source_size.width = 0.0f; d3d12->hdr.ubo_values.source_size.height = 0.0f; @@ -3553,8 +3507,8 @@ static void *d3d12_gfx_init(const video_info_t* video, d3d12->hdr.ubo_values.scanlines = settings->bools.video_hdr_scanlines; d3d12->hdr.ubo_values.expand_gamut = settings->bools.video_hdr_expand_gamut; - d3d12->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */ - d3d12->hdr.ubo_values.hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */ + d3d12->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */ + d3d12->hdr.ubo_values.hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */ { dxgi_hdr_uniform_t* mapped_ubo; @@ -3565,6 +3519,16 @@ static void *d3d12_gfx_init(const video_info_t* video, *mapped_ubo = d3d12->hdr.ubo_values; D3D12Unmap(d3d12->hdr.ubo, 0, NULL); } + + { + dxgi_hdr_uniform_t* mapped_ubo; + D3D12_RANGE read_range; + read_range.Begin = 0; + read_range.End = 0; + D3D12Map(d3d12->hdr.ubo_post, 0, &read_range, (void**)&mapped_ubo); + *mapped_ubo = d3d12->hdr.ubo_values; + D3D12Unmap(d3d12->hdr.ubo_post, 0, NULL); + } #endif matrix_4x4_identity(d3d12->identity); @@ -3868,7 +3832,6 @@ static bool d3d12_gfx_frame( bool d3d12_hdr_enable = false; bool video_hdr_enable = video_info->hdr_enable; DXGI_FORMAT back_buffer_format = d3d12->shader_preset && d3d12->shader_preset->passes ? glslang_format_to_dxgi(d3d12->pass[d3d12->shader_preset->passes - 1].semantics.format) : d3d12->chain.formats[d3d12->chain.bit_depth]; - bool use_back_buffer = back_buffer_format != d3d12->chain.formats[d3d12->chain.bit_depth]; #endif D3D12GraphicsCommandList cmd = d3d12->queue.cmd; @@ -4420,13 +4383,10 @@ static bool d3d12_gfx_frame( d3d12->desc.rootSignature); #ifdef HAVE_DXGI_HDR - if ((d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE) - && !use_back_buffer) + if (d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE) { - cmd->lpVtbl->SetPipelineState(cmd, d3d12->pipes[VIDEO_SHADER_STOCK_HDR]); + cmd->lpVtbl->SetPipelineState(cmd, d3d12->pipes[VIDEO_SHADER_STOCK_NOBLEND_HDR]); - if(d3d12->hdr.ubo_values.source_size.width != width || d3d12->hdr.ubo_values.source_size.height != height || - d3d12->hdr.ubo_values.output_size.width != d3d12->frame.output_size.x || d3d12->hdr.ubo_values.output_size.height != d3d12->frame.output_size.y) { d3d12->hdr.ubo_values.source_size.width = width; d3d12->hdr.ubo_values.source_size.height = height; @@ -4434,6 +4394,9 @@ static bool d3d12_gfx_frame( d3d12->hdr.ubo_values.output_size.width = d3d12->frame.output_size.x; d3d12->hdr.ubo_values.output_size.height = d3d12->frame.output_size.y; + settings_t* settings = config_get_ptr(); + d3d12->hdr.ubo_values.scanlines = settings->bools.video_hdr_scanlines ? 1.0f : 0.0f; + { dxgi_hdr_uniform_t* mapped_ubo; D3D12_RANGE read_range; @@ -4443,11 +4406,11 @@ static bool d3d12_gfx_frame( *mapped_ubo = d3d12->hdr.ubo_values; D3D12Unmap(d3d12->hdr.ubo, 0, NULL); } - } - cmd->lpVtbl->SetGraphicsRootConstantBufferView( - cmd, ROOT_ID_UBO, - d3d12->hdr.ubo_view.BufferLocation); + cmd->lpVtbl->SetGraphicsRootConstantBufferView( + cmd, ROOT_ID_UBO, + d3d12->hdr.ubo_view.BufferLocation); + } } else #endif @@ -4471,33 +4434,6 @@ static bool d3d12_gfx_frame( d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex( d3d12->chain.handle); -#ifdef HAVE_DXGI_HDR - if ((d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE) && use_back_buffer) - { - D3D12_RESOURCE_TRANSITION( - cmd, - d3d12->chain.back_buffer.handle, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_RENDER_TARGET); - - cmd->lpVtbl->OMSetRenderTargets( - cmd, 1, - &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 - * D3D12_RESOURCE_DIMENSION_BUFFER, yet we get spammed with this - * warning - */ - cmd->lpVtbl->ClearRenderTargetView( - cmd, - d3d12->chain.back_buffer.rt_view, - d3d12->chain.clearcolor, - 0, NULL); - } - else -#endif { D3D12_RESOURCE_TRANSITION( cmd, @@ -4549,6 +4485,36 @@ static bool d3d12_gfx_frame( cmd->lpVtbl->SetPipelineState(cmd, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]); cmd->lpVtbl->SetGraphicsRootSignature(cmd, d3d12->desc.rootSignature); +#ifdef HAVE_DXGI_HDR + if ((d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE) && + (d3d12->flags & D3D12_ST_FLAG_MENU_ENABLE)) + { + D3D12_RESOURCE_TRANSITION( + cmd, + d3d12->chain.back_buffer.handle, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + D3D12_RESOURCE_STATE_RENDER_TARGET); + + cmd->lpVtbl->OMSetRenderTargets( + cmd, 1, + &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 + * D3D12_RESOURCE_DIMENSION_BUFFER, yet we get spammed with this + * warning + */ + + float clear_colour[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + cmd->lpVtbl->ClearRenderTargetView( + cmd, + d3d12->chain.back_buffer.rt_view, + clear_colour, + 0, NULL); + } +#endif + if ( (d3d12->flags & D3D12_ST_FLAG_MENU_ENABLE) && d3d12->menu.texture.handle) { @@ -4638,7 +4604,8 @@ static bool d3d12_gfx_frame( #ifdef HAVE_DXGI_HDR /* Copy over back buffer to swap chain render targets */ - if ((d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE) && use_back_buffer) + if ((d3d12->flags & D3D12_ST_FLAG_HDR_ENABLE) && + (d3d12->flags & D3D12_ST_FLAG_MENU_ENABLE)) { D3D12_RESOURCE_TRANSITION( cmd, @@ -4656,17 +4623,31 @@ static bool d3d12_gfx_frame( cmd->lpVtbl->OMSetRenderTargets( cmd, 1, &d3d12->chain.desc_handles[d3d12->chain.frame_index], FALSE, NULL); - cmd->lpVtbl->ClearRenderTargetView( - cmd, d3d12->chain.desc_handles[d3d12->chain.frame_index], - d3d12->chain.clearcolor, 0, NULL); cmd->lpVtbl->SetGraphicsRootSignature(cmd, d3d12->desc.rootSignature); cmd->lpVtbl->SetGraphicsRootDescriptorTable(cmd, ROOT_ID_TEXTURE_T, d3d12->chain.back_buffer.gpu_descriptor[0]); cmd->lpVtbl->SetGraphicsRootDescriptorTable(cmd, ROOT_ID_SAMPLER_T, d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); - cmd->lpVtbl->SetGraphicsRootConstantBufferView(cmd, ROOT_ID_UBO, - d3d12->hdr.ubo_view.BufferLocation); + + { + d3d12->hdr.ubo_values.scanlines = false; + + { + dxgi_hdr_uniform_t* mapped_ubo; + D3D12_RANGE read_range; + read_range.Begin = 0; + read_range.End = 0; + D3D12Map(d3d12->hdr.ubo_post, 0, &read_range, (void**)&mapped_ubo); + *mapped_ubo = d3d12->hdr.ubo_values; + D3D12Unmap(d3d12->hdr.ubo_post, 0, NULL); + } + + cmd->lpVtbl->SetGraphicsRootConstantBufferView( + cmd, ROOT_ID_UBO, + d3d12->hdr.ubo_post_view.BufferLocation); + } + cmd->lpVtbl->IASetVertexBuffers(cmd, 0, 1, &d3d12->frame.vbo_view); cmd->lpVtbl->IASetPrimitiveTopology(cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); diff --git a/gfx/drivers/d3d_shaders/hdr_sm5.hlsl.h b/gfx/drivers/d3d_shaders/hdr_sm5.hlsl.h index d4a70953a1d0..8bd5abf3d4d7 100644 --- a/gfx/drivers/d3d_shaders/hdr_sm5.hlsl.h +++ b/gfx/drivers/d3d_shaders/hdr_sm5.hlsl.h @@ -89,7 +89,6 @@ static const float k_crt_green_scanline_max = 0.70f; static const float k_crt_green_scanline_attack = 0.30f; static const float k_crt_blue_scanline_min = 0.45f; static const float k_crt_blue_scanline_max = 0.70f; - static const float k_crt_blue_scanline_attack = 0.30f; static const float k_crt_red_beam_sharpness = 1.30f; diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 4f735acc02c6..73631c389d9a 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -179,6 +179,7 @@ typedef struct vk struct vk_image *backbuffer; #ifdef VULKAN_HDR_SWAPCHAIN VkRenderPass readback_render_pass; + struct vk_image main_buffer; struct vk_image readback_image; #endif /* VULKAN_HDR_SWAPCHAIN */ @@ -198,6 +199,7 @@ typedef struct vk math_matrix_4x4 mvp, mvp_no_rot, mvp_menu; /* float alignment */ VkViewport vk_vp; VkRenderPass render_pass; + VkRenderPass keep_render_pass; struct video_viewport vp; float translate_x; float translate_y; @@ -230,6 +232,7 @@ typedef struct vk VkPipeline font; VkPipeline rgb565_to_rgba8888; #ifdef VULKAN_HDR_SWAPCHAIN + VkPipeline hdr; VkPipeline hdr_to_sdr; /* for readback */ #endif /* VULKAN_HDR_SWAPCHAIN */ VkDescriptorSetLayout set_layout; @@ -246,11 +249,13 @@ typedef struct vk #ifdef VULKAN_HDR_SWAPCHAIN struct { - struct vk_buffer ubo; - float max_output_nits; - float min_output_nits; - float max_cll; - float max_fall; + vulkan_hdr_uniform_t ubo_values; + struct vk_buffer ubo; + struct vk_buffer ubo_post; + float max_output_nits; + float min_output_nits; + float max_cll; + float max_fall; } hdr; #endif /* VULKAN_HDR_SWAPCHAIN */ @@ -2241,6 +2246,12 @@ static void vulkan_init_render_pass( vkCreateRenderPass(vk->context->device, &rp_info, NULL, &vk->render_pass); + + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + vkCreateRenderPass(vk->context->device, + &rp_info, NULL, &vk->keep_render_pass); } @@ -2417,6 +2428,9 @@ static void vulkan_init_pipeline_layout( static void vulkan_init_pipelines(vk_t *vk) { #ifdef VULKAN_HDR_SWAPCHAIN + static const uint32_t hdr_frag[] = +#include "vulkan_shaders/hdr.frag.inc" + ; static const uint32_t hdr_tonemap_frag[] = #include "vulkan_shaders/hdr_tonemap.frag.inc" ; @@ -2641,9 +2655,33 @@ static void vulkan_init_pipelines(vk_t *vk) #ifdef VULKAN_HDR_SWAPCHAIN if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) { - blend_attachment.blendEnable = VK_FALSE; + /* HDR pipeline. */ + blend_attachment.blendEnable = VK_TRUE; + + /* HDR pipeline. */ + module_info.codeSize = sizeof(hdr_frag); + module_info.pCode = hdr_frag; + shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + shader_stages[1].pName = "main"; + vkCreateShaderModule(vk->context->device, + &module_info, NULL, &shader_stages[1].module); + + vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, + 1, &pipe, NULL, &vk->pipelines.hdr); + + /* Build display hdr pipelines. */ + for (i = 4; i < 6; i++) + { + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, + 1, &pipe, NULL, &vk->display.pipelines[i]); + } + + vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); /* HDR->SDR tonemapping readback pipeline. */ + blend_attachment.blendEnable = VK_FALSE; + module_info.codeSize = sizeof(hdr_tonemap_frag); module_info.pCode = hdr_tonemap_frag; shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; @@ -2948,6 +2986,8 @@ static void vulkan_deinit_pipelines(vk_t *vk) #ifdef VULKAN_HDR_SWAPCHAIN if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) { + vkDestroyPipeline(vk->context->device, + vk->pipelines.hdr, NULL); vkDestroyPipeline(vk->context->device, vk->pipelines.hdr_to_sdr, NULL); } @@ -2984,10 +3024,9 @@ static void vulkan_deinit_hdr_readback_render_pass(vk_t *vk) static void vulkan_set_hdr_max_nits(void* data, float max_nits) { vk_t *vk = (vk_t*)data; - vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; vk->hdr.max_output_nits = max_nits; - mapped_ubo->max_nits = max_nits; + vk->hdr.ubo_values.max_nits = max_nits; if(vk->filter_chain) { @@ -3004,9 +3043,8 @@ static void vulkan_set_hdr_max_nits(void* data, float max_nits) static void vulkan_set_hdr_paper_white_nits(void* data, float paper_white_nits) { vk_t *vk = (vk_t*)data; - vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; - mapped_ubo->paper_white_nits = paper_white_nits; + vk->hdr.ubo_values.paper_white_nits = paper_white_nits; if(vk->filter_chain) { @@ -3023,9 +3061,8 @@ static void vulkan_set_hdr_paper_white_nits(void* data, float paper_white_nits) static void vulkan_set_hdr_expand_gamut(void* data, bool expand_gamut) { vk_t *vk = (vk_t*)data; - vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; - mapped_ubo->expand_gamut = expand_gamut ? 1.0f : 0.0f; + vk->hdr.ubo_values.expand_gamut = expand_gamut ? 1.0f : 0.0f; if(vk->filter_chain) { @@ -3073,9 +3110,7 @@ static void vulkan_set_hdr_subpixel_layout(void* data, unsigned subpixel_layout) static void vulkan_set_hdr_inverse_tonemap(vk_t* vk, vulkan_filter_chain_t* filter_chain, bool inverse_tonemap) { - vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; - - mapped_ubo->inverse_tonemap = inverse_tonemap ? 1.0f : 0.0f; + vk->hdr.ubo_values.inverse_tonemap = inverse_tonemap ? 1.0f : 0.0f; vulkan_filter_chain_set_inverse_tonemap( filter_chain, inverse_tonemap ? 1.0f : 0.0f); @@ -3083,9 +3118,7 @@ static void vulkan_set_hdr_inverse_tonemap(vk_t* vk, vulkan_filter_chain_t* filt static void vulkan_set_hdr10(vk_t* vk, vulkan_filter_chain_t* filter_chain, bool hdr10) { - vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; - - mapped_ubo->hdr10 = hdr10 ? 1.0f : 0.0f; + vk->hdr.ubo_values.hdr10 = hdr10 ? 1.0f : 0.0f; vulkan_filter_chain_set_hdr10( filter_chain, hdr10 ? 1.0f : 0.0f); @@ -3445,6 +3478,8 @@ static void vulkan_free(void *data) if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) { vulkan_destroy_buffer(vk->context->device, &vk->hdr.ubo); + vulkan_destroy_buffer(vk->context->device, &vk->hdr.ubo_post); + vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer); vulkan_destroy_hdr_buffer(vk->context->device, &vk->readback_image); vulkan_deinit_hdr_readback_render_pass(vk); video_driver_unset_hdr_support(); @@ -3777,15 +3812,17 @@ static void *vulkan_init(const video_info_t *video, #ifdef VULKAN_HDR_SWAPCHAIN vk->hdr.ubo = vulkan_create_buffer(vk->context, sizeof(vulkan_hdr_uniform_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + vk->hdr.ubo_post = vulkan_create_buffer(vk->context, sizeof(vulkan_hdr_uniform_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + vk->hdr.ubo_values.mvp = vk->mvp_no_rot; + vk->hdr.ubo_values.max_nits = settings->floats.video_hdr_max_nits; + vk->hdr.ubo_values.paper_white_nits = settings->floats.video_hdr_paper_white_nits; + + vk->hdr.ubo_values.expand_gamut = settings->bools.video_hdr_expand_gamut; - mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + vk->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */ + vk->hdr.ubo_values.hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */ - mapped_ubo->mvp = vk->mvp_no_rot; - mapped_ubo->max_nits = settings->floats.video_hdr_max_nits; - mapped_ubo->paper_white_nits = settings->floats.video_hdr_paper_white_nits; - mapped_ubo->expand_gamut = settings->bools.video_hdr_expand_gamut; - mapped_ubo->inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */ - mapped_ubo->hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */ #endif /* VULKAN_HDR_SWAPCHAIN */ vulkan_init_hw_render(vk); @@ -4537,13 +4574,12 @@ static void vulkan_init_render_target(struct vk_image* image, uint32_t width, ui vkCreateFramebuffer(ctx->device, &info, NULL, &image->framebuffer); } -static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pass, const struct vk_image* source_image, struct vk_image* render_target, vk_t* vk) +static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pass, const struct vk_image* source_image, struct vk_image* render_target, vk_t* vk, struct vk_buffer* ubo) { - vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; VkRenderPassBeginInfo rp_info; VkClearValue clear_color; - mapped_ubo->mvp = vk->mvp_no_rot; + vk->hdr.ubo_values.mvp = vk->mvp_no_rot; rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rp_info.pNext = NULL; @@ -4582,12 +4618,16 @@ static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pas vk->context->device, &vk->chain->descriptor_manager); + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)ubo->mapped; + + *mapped_ubo = vk->hdr.ubo_values; + VULKAN_SET_UNIFORM_BUFFER(vk->context->device, set, 0, - vk->hdr.ubo.buffer, + ubo->buffer, 0, - vk->hdr.ubo.size); + ubo->size); image_info.sampler = vk->samplers.nearest; image_info.imageView = source_image->view; @@ -4699,7 +4739,6 @@ static bool vulkan_frame(void *data, const void *frame, unsigned swapchain_index = vk->context->current_swapchain_index; bool overlay_behind_menu = video_info->overlay_behind_menu; - bool use_main_buffer = true; /* Fast toggle shader filter chain logic */ filter_chain = vk->filter_chain; @@ -4718,12 +4757,6 @@ static bool vulkan_frame(void *data, const void *frame, if (!filter_chain && vk->filter_chain_default) filter_chain = vk->filter_chain_default; -#ifdef VULKAN_HDR_SWAPCHAIN - use_main_buffer = - ( vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) - && (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain)); -#endif /* VULKAN_HDR_SWAPCHAIN */ - /* Bookkeeping on start of frame. */ struct vk_per_frame *chain = &vk->swapchain[frame_index]; struct vk_image *backbuffer = &vk->backbuffers[swapchain_index]; @@ -5041,6 +5074,22 @@ static bool vulkan_frame(void *data, const void *frame, (vulkan_filter_chain_t*)filter_chain, vk->cmd, &vk->vk_vp, vk->mvp.data); +#ifdef VULKAN_HDR_SWAPCHAIN + if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) && + (vk->flags & VK_FLAG_MENU_ENABLE) && + (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain))) + { + vkCmdEndRenderPass(vk->cmd); + + backbuffer = &vk->main_buffer; + + rp_info.framebuffer = backbuffer->framebuffer; + + /* Begin render pass and set up viewport */ + vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE); + } +#endif /* VULKAN_HDR_SWAPCHAIN */ + #ifdef HAVE_OVERLAY if ((vk->flags & VK_FLAG_OVERLAY_ENABLE) && overlay_behind_menu) vulkan_render_overlay(vk, video_width, video_height); @@ -5107,6 +5156,24 @@ static bool vulkan_frame(void *data, const void *frame, /* End the render pass. We're done rendering to backbuffer now. */ vkCmdEndRenderPass(vk->cmd); + +#ifdef VULKAN_HDR_SWAPCHAIN + /* Copy over back buffer to swap chain render targets */ + if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) && + (vk->flags & VK_FLAG_MENU_ENABLE) && + (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain))) + { + backbuffer = &vk->backbuffers[swapchain_index]; + /* Prepare source buffer for reading */ + VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->main_buffer.image, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + vulkan_run_hdr_pipeline(vk->pipelines.hdr, vk->keep_render_pass, &vk->main_buffer, backbuffer, vk, &vk->hdr.ubo); + } +#endif /* VULKAN_HDR_SWAPCHAIN */ } /* End the filter chain frame. @@ -5124,15 +5191,17 @@ static bool vulkan_frame(void *data, const void *frame, { VkImageLayout backbuffer_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; #ifdef VULKAN_HDR_SWAPCHAIN - if (use_main_buffer) - { - backbuffer = &vk->backbuffers[swapchain_index]; - } - struct vk_image* readback_source = backbuffer; - if (vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) + if((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) && + (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain))) { - if (!use_main_buffer) + if (vk->flags & VK_FLAG_MENU_ENABLE) + { + /* Read directly from sdr main buffer instead of tonemapping */ + readback_source = &vk->main_buffer; + /* No need to transition layout, it's already read-only optimal */ + } + else { /* Prepare backbuffer for reading */ backbuffer_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -5142,7 +5211,7 @@ static bool vulkan_frame(void *data, const void *frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } - vulkan_run_hdr_pipeline(vk->pipelines.hdr_to_sdr, vk->readback_render_pass, readback_source, &vk->readback_image, vk); + vulkan_run_hdr_pipeline(vk->pipelines.hdr_to_sdr, vk->readback_render_pass, readback_source, &vk->readback_image, vk, &vk->hdr.ubo); readback_source = &vk->readback_image; } #endif /* VULKAN_HDR_SWAPCHAIN */ @@ -5326,6 +5395,7 @@ static bool vulkan_frame(void *data, const void *frame, #ifdef HAVE_THREADS slock_unlock(vk->context->queue_lock); #endif + vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer); vulkan_destroy_hdr_buffer(vk->context->device, &vk->readback_image); } else @@ -5343,6 +5413,9 @@ static bool vulkan_frame(void *data, const void *frame, #ifdef VULKAN_HDR_SWAPCHAIN if (vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) { + /* Create intermediary buffer to render filter chain output to */ + vulkan_init_render_target(&vk->main_buffer, video_width, video_height, + VK_FORMAT_B8G8R8A8_UNORM, vk->render_pass, vk->context); /* Create image for readback target in bgra8 format */ vulkan_init_render_target(&vk->readback_image, video_width, video_height, VK_FORMAT_B8G8R8A8_UNORM, vk->readback_render_pass, vk->context); diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 6c133d0b7594..5b81762f385d 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -51,15 +51,16 @@ #define MEASURE_FRAME_TIME_SAMPLES_COUNT (2 * 1024) -#define VIDEO_SHADER_STOCK_BLEND (GFX_MAX_SHADERS - 1) -#define VIDEO_SHADER_MENU (GFX_MAX_SHADERS - 2) -#define VIDEO_SHADER_MENU_2 (GFX_MAX_SHADERS - 3) -#define VIDEO_SHADER_MENU_3 (GFX_MAX_SHADERS - 4) -#define VIDEO_SHADER_MENU_4 (GFX_MAX_SHADERS - 5) -#define VIDEO_SHADER_MENU_5 (GFX_MAX_SHADERS - 6) -#define VIDEO_SHADER_MENU_6 (GFX_MAX_SHADERS - 7) -#define VIDEO_SHADER_STOCK_HDR (GFX_MAX_SHADERS - 8) -#define VIDEO_SHADER_STOCK_NOBLEND (GFX_MAX_SHADERS - 9) +#define VIDEO_SHADER_STOCK_BLEND (GFX_MAX_SHADERS - 1) +#define VIDEO_SHADER_MENU (GFX_MAX_SHADERS - 2) +#define VIDEO_SHADER_MENU_2 (GFX_MAX_SHADERS - 3) +#define VIDEO_SHADER_MENU_3 (GFX_MAX_SHADERS - 4) +#define VIDEO_SHADER_MENU_4 (GFX_MAX_SHADERS - 5) +#define VIDEO_SHADER_MENU_5 (GFX_MAX_SHADERS - 6) +#define VIDEO_SHADER_MENU_6 (GFX_MAX_SHADERS - 7) +#define VIDEO_SHADER_STOCK_HDR (GFX_MAX_SHADERS - 8) +#define VIDEO_SHADER_STOCK_NOBLEND_HDR (GFX_MAX_SHADERS - 9) +#define VIDEO_SHADER_STOCK_NOBLEND (GFX_MAX_SHADERS - 10) #if defined(_XBOX360) #define DEFAULT_SHADER_TYPE RARCH_SHADER_HLSL From 2e93d143109141e68ab30a4f0fe9b0c894426bc9 Mon Sep 17 00:00:00 2001 From: MajorPainTheCactus Date: Sun, 25 Jan 2026 19:02:21 +0000 Subject: [PATCH 2/3] Fixed the menu in D3D11 and D3D12 when using HDR native shader's Vulkan still has issues --- gfx/drivers/d3d11.c | 12 +++++++++++- gfx/drivers/d3d12.c | 13 ++++++++++++- gfx/drivers/vulkan.c | 20 ++++++++++++++------ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 3e9f042da8e5..107d44b8d04f 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -3988,7 +3988,13 @@ static bool d3d11_gfx_frame( } { - d3d11->hdr.ubo_values.scanlines = false; + const float prev_iscanlines = d3d11->hdr.ubo_values.scanlines; + const float prev_inverse_tonemap = d3d11->hdr.ubo_values.inverse_tonemap; + const float prev_hdr10 = d3d11->hdr.ubo_values.hdr10; + + d3d11->hdr.ubo_values.scanlines = 0.0f; + d3d11->hdr.ubo_values.inverse_tonemap = 1.0f; + d3d11->hdr.ubo_values.hdr10 = 1.0f; D3D11_MAPPED_SUBRESOURCE mapped_ubo; @@ -3999,6 +4005,10 @@ static bool d3d11_gfx_frame( *ubo = d3d11->hdr.ubo_values; } d3d11->context->lpVtbl->Unmap(d3d11->context, (D3D11Resource)d3d11->hdr.ubo, 0); + + d3d11->hdr.ubo_values.scanlines = prev_iscanlines; + d3d11->hdr.ubo_values.inverse_tonemap = prev_inverse_tonemap; + d3d11->hdr.ubo_values.hdr10 = prev_hdr10; } context->lpVtbl->VSSetConstantBuffers(context, 0, 1, &d3d11->hdr.ubo); diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 204f6dd5a951..0d2ad8e3ba1e 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -4631,7 +4631,13 @@ static bool d3d12_gfx_frame( d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); { - d3d12->hdr.ubo_values.scanlines = false; + const float prev_iscanlines = d3d12->hdr.ubo_values.scanlines; + const float prev_inverse_tonemap = d3d12->hdr.ubo_values.inverse_tonemap; + const float prev_hdr10 = d3d12->hdr.ubo_values.hdr10; + + d3d12->hdr.ubo_values.scanlines = 0.0f; + d3d12->hdr.ubo_values.inverse_tonemap = 1.0f; + d3d12->hdr.ubo_values.hdr10 = 1.0f; { dxgi_hdr_uniform_t* mapped_ubo; @@ -4646,6 +4652,11 @@ static bool d3d12_gfx_frame( cmd->lpVtbl->SetGraphicsRootConstantBufferView( cmd, ROOT_ID_UBO, d3d12->hdr.ubo_post_view.BufferLocation); + + + d3d12->hdr.ubo_values.scanlines = prev_iscanlines; + d3d12->hdr.ubo_values.inverse_tonemap = prev_inverse_tonemap; + d3d12->hdr.ubo_values.hdr10 = prev_hdr10; } cmd->lpVtbl->IASetVertexBuffers(cmd, 0, 1, &d3d12->frame.vbo_view); diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 73631c389d9a..efcf38848b20 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -4579,7 +4579,14 @@ static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pas VkRenderPassBeginInfo rp_info; VkClearValue clear_color; - vk->hdr.ubo_values.mvp = vk->mvp_no_rot; + //const bool prev_scanlines = vk->hdr.ubo_values.scanlines; + const float prev_inverse_tonemap = vk->hdr.ubo_values.inverse_tonemap; + const float prev_hdr10 = vk->hdr.ubo_values.hdr10; + + vk->hdr.ubo_values.mvp = vk->mvp_no_rot; + //vk->hdr.ubo_values.scanlines = false; + vk->hdr.ubo_values.inverse_tonemap = 1.0f; + vk->hdr.ubo_values.hdr10 = 1.0f; rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rp_info.pNext = NULL; @@ -4627,7 +4634,7 @@ static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pas 0, ubo->buffer, 0, - ubo->size); + ubo->size); image_info.sampler = vk->samplers.nearest; image_info.imageView = source_image->view; @@ -4698,6 +4705,9 @@ static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pas vkCmdDraw(vk->cmd, 6, 1, 0, 0); vkCmdEndRenderPass(vk->cmd); + + vk->hdr.ubo_values.inverse_tonemap = prev_inverse_tonemap; + vk->hdr.ubo_values.hdr10 = prev_hdr10; } static bool vulkan_frame(void *data, const void *frame, @@ -5160,8 +5170,7 @@ static bool vulkan_frame(void *data, const void *frame, #ifdef VULKAN_HDR_SWAPCHAIN /* Copy over back buffer to swap chain render targets */ if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) && - (vk->flags & VK_FLAG_MENU_ENABLE) && - (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain))) + (vk->flags & VK_FLAG_MENU_ENABLE)) { backbuffer = &vk->backbuffers[swapchain_index]; /* Prepare source buffer for reading */ @@ -5192,8 +5201,7 @@ static bool vulkan_frame(void *data, const void *frame, VkImageLayout backbuffer_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; #ifdef VULKAN_HDR_SWAPCHAIN struct vk_image* readback_source = backbuffer; - if((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) && - (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain))) + if((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE)) { if (vk->flags & VK_FLAG_MENU_ENABLE) { From 8e6b7e72fa176506244bbb9033c2c7668522a244 Mon Sep 17 00:00:00 2001 From: MajorPainTheCactus Date: Sun, 25 Jan 2026 20:22:20 +0000 Subject: [PATCH 3/3] Fixed Vulkan driver HDR menu when we're using a HDR native shader Removed redundant constant buffer --- gfx/drivers/vulkan.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index efcf38848b20..f4a8aa88ff4a 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -251,7 +251,6 @@ typedef struct vk { vulkan_hdr_uniform_t ubo_values; struct vk_buffer ubo; - struct vk_buffer ubo_post; float max_output_nits; float min_output_nits; float max_cll; @@ -3478,7 +3477,6 @@ static void vulkan_free(void *data) if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) { vulkan_destroy_buffer(vk->context->device, &vk->hdr.ubo); - vulkan_destroy_buffer(vk->context->device, &vk->hdr.ubo_post); vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer); vulkan_destroy_hdr_buffer(vk->context->device, &vk->readback_image); vulkan_deinit_hdr_readback_render_pass(vk); @@ -3811,8 +3809,7 @@ static void *vulkan_init(const video_info_t *video, vulkan_set_viewport(vk, temp_width, temp_height, false, true); #ifdef VULKAN_HDR_SWAPCHAIN - vk->hdr.ubo = vulkan_create_buffer(vk->context, sizeof(vulkan_hdr_uniform_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - vk->hdr.ubo_post = vulkan_create_buffer(vk->context, sizeof(vulkan_hdr_uniform_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + vk->hdr.ubo = vulkan_create_buffer(vk->context, sizeof(vulkan_hdr_uniform_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); vk->hdr.ubo_values.mvp = vk->mvp_no_rot; vk->hdr.ubo_values.max_nits = settings->floats.video_hdr_max_nits; @@ -3822,7 +3819,6 @@ static void *vulkan_init(const video_info_t *video, vk->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */ vk->hdr.ubo_values.hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */ - #endif /* VULKAN_HDR_SWAPCHAIN */ vulkan_init_hw_render(vk); @@ -5086,8 +5082,7 @@ static bool vulkan_frame(void *data, const void *frame, #ifdef VULKAN_HDR_SWAPCHAIN if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) && - (vk->flags & VK_FLAG_MENU_ENABLE) && - (!filter_chain || !vulkan_filter_chain_emits_hdr10(filter_chain))) + (vk->flags & VK_FLAG_MENU_ENABLE)) { vkCmdEndRenderPass(vk->cmd);