Add HDR support for D3D12 (rebased PR from MajorPainTheCactus) (#12917)

* Add HDR support

* Attempt to fix Mingw build and Metal builds

* (D3D12) Fix relative header includes

* Add missing hdr_sm5.hlsl.h

* (d3d12_common.c) Some C89 build fixes

* Fix MSVC build

* - Attempt to fix build on mingw/msys unix with dirty hack
- Fix shader compilation of hdr_sm5.hlsl.h on MSVC/Visual Studio -
the define was seen as an error and was causing the first pipeline
to error out
- Make sure we manually set handle of backBuffer to NULL

* Moving the release of the texture above the freeing of desc.srv_heap
and desc.rtv_heap solves the hard crashes on teardown/setup in RA -
it was crashing hard in d3d12_release_texture before

* Add HAVE_D3D12_HDR ifdef - needs to be disabled for WinRT for now
because of several things that are Windows desktop-specific right now
(GetWindowRect)

* Add dirty GUID hack - should work for both mingw/msys on Windows/Linux
as well as MSVC/Visual Studio (hopefully)

* Change HAVE_D3D12_HDR to HAVE_DXGI_HDR

* Move away from camelcase named variables

* Fix RARCH_ERR logs - they need a newline at the end

* d3d12_check_display_hdr_support - make it return a bool on return
and set d3d12->hdr.support and d3d12->hdr.enable outside of the
function

* (DXGI) Remove D3D12 dependencies from dxgi_check_display_hdr_support and
move it to dxgi_common.c instead

* (DXGI) move d3d12_swapchain_color_space over to dxgi_common.c and
rename it dxgi_swapchain_color_space

* (DXGI) move d3d12_set_hdr_metadata to dxgi_common.c and
rename it dxgi_set_hdr_metadata

* (DXGI) dxgi_check_display_hdr_support - better error handling?

* Fix typo

* Remove video_force_resolution

* (D3D12) Address TODO/FIXME

* (D3D12) Backport
c1b6c0bff2
- Fixed resource transition for present when HDR is off
Fixed cel shader displaying all black as blending was enabled when the hdr shader was being applied - turned off blending during this shader

* Move d3d12_hdr_uniform_t to dxgi_common.h and
rename it dxgi_hdr_uniform_t

* (D3D11) Add HDR support

* Add TODO/FIXME notes

* Cache hdr_enable in video_frame_info_t

* Update comment
This commit is contained in:
Autechre 2021-09-03 06:15:25 +02:00 committed by GitHub
parent 868865c388
commit 7b9cbc08d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 2303 additions and 320 deletions

View File

@ -1,155 +1,156 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceRoot}/libretro-common/include"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceRoot}/libretro-common/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include",
"${workspaceRoot}/libretro-common/include"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include",
"${workspaceRoot}/libretro-common/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}"
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++17"
},
{
"name": "msys2-mingw32",
"includePath": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
"defines": [
"_DEBUG",
"UNICODE"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "msys2-mingw64",
"includePath": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++17",
"configurationProvider": "ms-vscode.makefile-tools"
},
{
"name": "msys2-mingw32",
"includePath": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Switch",
"includePath": [
"/opt/devkitpro/devkitA64/aarch64-none-elf/include",
"/opt/devkitpro/devkitA64/lib/gcc/aarch64-none-elf/8.3.0/include",
"/opt/devkitpro/libnx/include",
"/opt/devkitpro/portlibs/switch/include",
"/opt/devkitpro/portlibs/switch/include/freetype2",
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"__aarch64__",
"__SWITCH__",
"HAVE_LIBNX"
],
"windowsSdkVersion": "10.0.17763.0",
"compilerPath": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc",
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "msys2-mingw64",
"includePath": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Switch",
"includePath": [
"/opt/devkitpro/devkitA64/aarch64-none-elf/include",
"/opt/devkitpro/devkitA64/lib/gcc/aarch64-none-elf/8.3.0/include",
"/opt/devkitpro/libnx/include",
"/opt/devkitpro/portlibs/switch/include",
"/opt/devkitpro/portlibs/switch/include/freetype2",
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"__aarch64__",
"__SWITCH__",
"HAVE_LIBNX"
],
"windowsSdkVersion": "10.0.17763.0",
"compilerPath": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc",
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
}

View File

@ -412,6 +412,21 @@
#define DEFAULT_SHADER_ENABLE false
#endif
/* Should we enable hdr when its supported*/
#define DEFAULT_VIDEO_HDR_ENABLE false
/* The maximum nunmber of nits the actual display can show - needs to be calibrated */
#define DEFAULT_VIDEO_HDR_MAX_NITS 1000.0f
/* The number of nits that paper white is at */
#define DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS 200.0f
/* The contrast setting for hdr used to calculate the display gamma by dividing gamma 2.2 by this value */
#define DEFAULT_VIDEO_HDR_CONTRAST 1.0f
/* Should we expand the colour gamut when using hdr */
#define DEFAULT_VIDEO_HDR_EXPAND_GAMUT true
/* When presets are saved they will be saved using the #reference
* directive by default */
#define DEFAULT_VIDEO_SHADER_PRESET_SAVE_REFERENCE_ENABLE true

View File

@ -1656,7 +1656,7 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("video_scale_integer", &settings->bools.video_scale_integer, true, DEFAULT_SCALE_INTEGER, false);
SETTING_BOOL("video_scale_integer_overscale", &settings->bools.video_scale_integer_overscale, true, DEFAULT_SCALE_INTEGER_OVERSCALE, false);
SETTING_BOOL("video_smooth", &settings->bools.video_smooth, true, DEFAULT_VIDEO_SMOOTH, false);
SETTING_BOOL("video_ctx_scaling", &settings->bools.video_ctx_scaling, true, DEFAULT_VIDEO_CTX_SCALING, false);
SETTING_BOOL("video_ctx_scaling", &settings->bools.video_ctx_scaling, true, DEFAULT_VIDEO_CTX_SCALING, false);
SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, DEFAULT_FORCE_ASPECT, false);
#if defined(DINGUX)
SETTING_BOOL("video_dingux_ipu_keep_aspect", &settings->bools.video_dingux_ipu_keep_aspect, true, DEFAULT_DINGUX_IPU_KEEP_ASPECT, false);
@ -1666,6 +1666,8 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("auto_screenshot_filename", &settings->bools.auto_screenshot_filename, true, DEFAULT_AUTO_SCREENSHOT_FILENAME, false);
SETTING_BOOL("video_force_srgb_disable", &settings->bools.video_force_srgb_disable, true, false, false);
SETTING_BOOL("video_fullscreen", &settings->bools.video_fullscreen, true, DEFAULT_FULLSCREEN, false);
SETTING_BOOL("video_hdr_enable", &settings->bools.video_hdr_enable, true, DEFAULT_VIDEO_HDR_ENABLE, false);
SETTING_BOOL("video_hdr_expand_gamut", &settings->bools.video_hdr_expand_gamut, true, DEFAULT_VIDEO_HDR_EXPAND_GAMUT, false);
SETTING_BOOL("bundle_assets_extract_enable", &settings->bools.bundle_assets_extract_enable, true, DEFAULT_BUNDLE_ASSETS_EXTRACT_ENABLE, false);
SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, DEFAULT_VSYNC, false);
SETTING_BOOL("video_adaptive_vsync", &settings->bools.video_adaptive_vsync, true, DEFAULT_ADAPTIVE_VSYNC, false);
@ -2039,6 +2041,10 @@ static struct config_float_setting *populate_settings_float(
SETTING_FLOAT("input_analog_sensitivity", &settings->floats.input_analog_sensitivity, true, DEFAULT_ANALOG_SENSITIVITY, false);
SETTING_FLOAT("video_msg_bgcolor_opacity", &settings->floats.video_msg_bgcolor_opacity, true, message_bgcolor_opacity, false);
SETTING_FLOAT("video_hdr_max_nits", &settings->floats.video_hdr_max_nits, true, DEFAULT_VIDEO_HDR_MAX_NITS, false);
SETTING_FLOAT("video_hdr_paper_white_nits", &settings->floats.video_hdr_paper_white_nits, true, DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS, false);
SETTING_FLOAT("video_hdr_contrast", &settings->floats.video_hdr_contrast, true, DEFAULT_VIDEO_HDR_CONTRAST, false);
*size = count;
return tmp;

View File

@ -345,6 +345,9 @@ typedef struct settings
float video_msg_color_g;
float video_msg_color_b;
float video_msg_bgcolor_opacity;
float video_hdr_max_nits;
float video_hdr_paper_white_nits;
float video_hdr_contrast;
float menu_scale_factor;
float menu_widget_scale_factor;
@ -553,6 +556,8 @@ typedef struct settings
#ifdef HAVE_VIDEO_LAYOUT
bool video_layout_enable;
#endif
bool video_hdr_enable;
bool video_hdr_expand_gamut;
/* Accessibility */
bool accessibility_enable;

View File

@ -2529,6 +2529,9 @@ typedef struct
D3D11RasterizerState scissor_disabled;
D3D11Buffer ubo;
d3d11_uniform_t ubo_values;
#ifdef HAVE_DXGI_HDR
d3d11_texture_t back_buffer;
#endif
D3D11SamplerState samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX];
D3D11BlendState blend_enable;
D3D11BlendState blend_disable;
@ -2549,6 +2552,12 @@ typedef struct
bool has_flip_model;
bool has_allow_tearing;
d3d11_shader_t shaders[GFX_MAX_SHADERS];
#ifdef HAVE_DXGI_HDR
enum dxgi_swapchain_bit_depth
chain_bit_depth;
DXGI_COLOR_SPACE_TYPE chain_color_space;
DXGI_FORMAT chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_COUNT];
#endif
#ifdef __WINRT__
DXGIFactory2 factory;
#else
@ -2562,6 +2571,20 @@ typedef struct
struct retro_hw_render_interface_d3d11 iface;
} hw;
#ifdef HAVE_DXGI_HDR
struct
{
dxgi_hdr_uniform_t ubo_values;
D3D11Buffer ubo;
float max_output_nits;
float min_output_nits;
float max_cll;
float max_fall;
bool support;
bool enable;
} hdr;
#endif
struct
{
d3d11_shader_t shader;

View File

@ -174,7 +174,6 @@ bool d3d12_init_base(d3d12_video_t* d3d12)
#else
DXGICreateFactory(&d3d12->factory);
#endif
{
int i = 0;
settings_t *settings = config_get_ptr();
@ -200,7 +199,6 @@ bool d3d12_init_base(d3d12_video_t* d3d12)
if (FAILED(DXGIEnumAdapters(d3d12->factory, i, &adapter)))
break;
#endif
IDXGIAdapter_GetDesc(adapter, &desc);
utf16_to_char_string((const uint16_t*)desc.Description, str, sizeof(str));
@ -284,13 +282,30 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
{
unsigned i;
HRESULT hr;
HWND hwnd;
#ifdef __WINRT__
DXGI_SWAP_CHAIN_DESC1 desc;
memset(&desc, 0, sizeof(DXGI_SWAP_CHAIN_DESC1));
DXGI_SWAP_CHAIN_DESC1 desc = {{0}};
#else
DXGI_SWAP_CHAIN_DESC desc;
HWND hwnd = (HWND)corewindow;
memset(&desc, 0, sizeof(DXGI_SWAP_CHAIN_DESC));
DXGI_SWAP_CHAIN_DESC desc = {{0}};
#endif
#ifdef HAVE_DXGI_HDR
DXGI_COLOR_SPACE_TYPE color_space;
d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_8] = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_10] = DXGI_FORMAT_R10G10B10A2_UNORM;
d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_16] = DXGI_FORMAT_R16G16B16A16_UNORM;
#endif
hwnd = (HWND)corewindow;
#ifdef HAVE_DXGI_HDR
if (!(d3d12->hdr.support =
dxgi_check_display_hdr_support(d3d12->factory, hwnd)))
d3d12->hdr.enable = false;
d3d12->chain.bit_depth = d3d12->hdr.enable
? DXGI_SWAPCHAIN_BIT_DEPTH_10
: DXGI_SWAPCHAIN_BIT_DEPTH_8;
#endif
desc.BufferCount = countof(d3d12->chain.renderTargets);
@ -298,24 +313,37 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
#ifdef __WINRT__
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#else
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.RefreshRate.Numerator = 0;
desc.BufferDesc.RefreshRate.Denominator = 1;
#endif
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
desc.Format = d3d12->chain.formats[d3d12->chain.bit_depth];
#else
desc.BufferDesc.Format = d3d12->chain.formats[d3d12->chain.bit_depth];
#endif
#else
#ifdef __WINRT__
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#else
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#endif
#endif
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
#ifdef HAVE_WINDOW
desc.OutputWindow = hwnd;
desc.Windowed = TRUE;
desc.OutputWindow = hwnd;
desc.Windowed = TRUE;
#endif
#if 0
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
#else
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
#endif
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
@ -334,6 +362,34 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
#endif
#ifdef HAVE_DXGI_HDR
/* Check display HDR support and
initialize ST.2084 support to match
the display's support. */
#if 0
d3d12->hdr.max_output_nits = 300.0f;
d3d12->hdr.min_output_nits = 0.001f;
d3d12->hdr.max_cll = 0.0f;
d3d12->hdr.max_fall = 0.0f;
#endif
color_space =
d3d12->hdr.enable
? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
dxgi_swapchain_color_space(d3d12->chain.handle,
&d3d12->chain.color_space, color_space);
dxgi_set_hdr_metadata(
d3d12->chain.handle,
d3d12->hdr.support,
d3d12->chain.bit_depth,
d3d12->chain.color_space,
d3d12->hdr.max_output_nits,
d3d12->hdr.min_output_nits,
d3d12->hdr.max_cll,
d3d12->hdr.max_fall);
#endif
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
@ -343,10 +399,28 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]);
}
d3d12->chain.viewport.Width = width;
d3d12->chain.viewport.Height = height;
d3d12->chain.scissorRect.right = width;
d3d12->chain.scissorRect.bottom = height;
#ifdef HAVE_DXGI_HDR
memset(&d3d12->chain.back_buffer,
0, sizeof(d3d12->chain.back_buffer));
d3d12->chain.back_buffer.desc.Width = width;
d3d12->chain.back_buffer.desc.Height = height;
d3d12->chain.back_buffer.desc.Format =
DXGI_FORMAT_R8G8B8A8_UNORM;
d3d12->chain.back_buffer.desc.Flags =
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
d3d12->chain.back_buffer.srv_heap =
&d3d12->desc.srv_heap;
d3d12->chain.back_buffer.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr
+ (countof(d3d12->chain.renderTargets))
* d3d12->desc.rtv_heap.stride;
d3d12_init_texture(d3d12->device, &d3d12->chain.back_buffer);
#endif
d3d12->chain.viewport.Width = width;
d3d12->chain.viewport.Height = height;
d3d12->chain.scissorRect.right = width;
d3d12->chain.scissorRect.bottom = height;
return true;
}
@ -619,6 +693,19 @@ D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_enable_desc = {
D3D12_COLOR_WRITE_ENABLE_ALL,
};
D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc = {
FALSE,
FALSE,
D3D12_BLEND_SRC_ALPHA,
D3D12_BLEND_INV_SRC_ALPHA,
D3D12_BLEND_OP_ADD,
D3D12_BLEND_SRC_ALPHA,
D3D12_BLEND_INV_SRC_ALPHA,
D3D12_BLEND_OP_ADD,
D3D12_LOGIC_OP_NOOP,
D3D12_COLOR_WRITE_ENABLE_ALL,
};
bool d3d12_init_pipeline(
D3D12Device device,
D3DBlob vs_code,

View File

@ -1385,6 +1385,9 @@ typedef struct
{
DXGISwapChain handle;
D3D12Resource renderTargets[2];
#ifdef HAVE_DXGI_HDR
d3d12_texture_t back_buffer;
#endif
D3D12_CPU_DESCRIPTOR_HANDLE desc_handles[2];
D3D12_VIEWPORT viewport;
D3D12_RECT scissorRect;
@ -1392,6 +1395,11 @@ typedef struct
int frame_index;
bool vsync;
unsigned swap_interval;
#ifdef HAVE_DXGI_HDR
enum dxgi_swapchain_bit_depth bit_depth;
DXGI_COLOR_SPACE_TYPE color_space;
DXGI_FORMAT formats[DXGI_SWAPCHAIN_BIT_DEPTH_COUNT];
#endif
} chain;
struct
@ -1407,6 +1415,21 @@ typedef struct
int rotation;
} frame;
#ifdef HAVE_DXGI_HDR
struct
{
dxgi_hdr_uniform_t ubo_values;
D3D12Resource ubo;
D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view;
float max_output_nits;
float min_output_nits;
float max_cll;
float max_fall;
bool support;
bool enable;
} hdr;
#endif
struct
{
D3D12Resource vbo;
@ -1490,19 +1513,20 @@ typedef enum {
ROOT_ID_SAMPLER_T,
ROOT_ID_UBO,
ROOT_ID_PC,
ROOT_ID_MAX,
ROOT_ID_MAX
} root_signature_parameter_index_t;
typedef enum {
CS_ROOT_ID_TEXTURE_T = 0,
CS_ROOT_ID_UAV_T,
CS_ROOT_ID_CONSTANTS,
CS_ROOT_ID_MAX,
CS_ROOT_ID_MAX
} compute_root_index_t;
RETRO_BEGIN_DECLS
extern D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_enable_desc;
extern D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc;
bool d3d12_init_base(d3d12_video_t* d3d12);

View File

@ -140,7 +140,8 @@ bool d3d_compile(const char* src, size_t size, LPCSTR src_name, LPCSTR entrypoin
{
if (error_msg)
{
RARCH_ERR("D3DCompile failed :\n%s\n", (const char*)D3DGetBufferPointer(error_msg));
const char* msg = (const char*)D3DGetBufferPointer(error_msg);
RARCH_ERR("D3DCompile failed :\n%s\n", msg); /* Place a breakpoint here, if you want, to see shader compilation issues */
Release(error_msg);
}
return false;

View File

@ -31,6 +31,18 @@
#include "../frontend/frontend_driver.h"
#include "win32_common.h"
const GUID DECLSPEC_SELECTANY libretro_IID_IDXGIOutput6 = { 0x068346e8,0xaaec,
0x4b84, {0xad,0xd7,0x13,0x7f,0x51,0x3f,0x77,0xa1 } };
#ifdef HAVE_DXGI_HDR
typedef enum hdr_root_constants
{
HDR_ROOT_CONSTANTS_REFERENCE_WHITE_NITS = 0,
HDR_ROOT_CONSTANTS_DISPLAY_CURVE,
HDR_ROOT_CONSTANTS_COUNT
} hdr_root_constants_t;
#endif
#if defined(HAVE_DYNAMIC) && !defined(__WINRT__)
#include <dynamic/dylib.h>
@ -347,3 +359,260 @@ DXGI_FORMAT glslang_format_to_dxgi(glslang_format fmt)
return DXGI_FORMAT_UNKNOWN;
}
#ifdef HAVE_DXGI_HDR
typedef struct display_chromaticities
{
float red_x;
float red_y;
float green_x;
float green_y;
float blue_x;
float blue_y;
float white_x;
float white_y;
} display_chromaticities_t;
inline static int dxgi_compute_intersection_area(
int ax1, int ay1, int ax2, int ay2,
int bx1, int by1, int bx2, int by2)
{
return max(0, min(ax2, bx2) -
max(ax1, bx1))
* max(0, min(ay2, by2) - max(ay1, by1));
}
#ifdef __WINRT__
bool dxgi_check_display_hdr_support(DXGIFactory2 factory, HWND hwnd)
#else
bool dxgi_check_display_hdr_support(DXGIFactory factory, HWND hwnd)
#endif
{
DXGIOutput6 output6 = NULL;
DXGIOutput best_output = NULL;
DXGIOutput current_output = NULL;
DXGIAdapter dxgi_adapter = NULL;
UINT i = 0;
bool supported = false;
float best_intersect_area = -1;
if (!DXGIIsCurrent(factory))
{
if (FAILED(DXGICreateFactory(&factory)))
{
RARCH_ERR("[DXGI]: Failed to create DXGI factory\n");
return false;
}
}
if (FAILED(DXGIEnumAdapters(factory, 0, &dxgi_adapter)))
{
RARCH_ERR("[DXGI]: Failed to enumerate adapters\n");
return false;
}
while ( DXGIEnumOutputs(dxgi_adapter, i, &current_output)
!= DXGI_ERROR_NOT_FOUND)
{
RECT r, rect;
DXGI_OUTPUT_DESC desc;
int intersect_area;
int bx1, by1, bx2, by2;
int ax1 = 0;
int ay1 = 0;
int ax2 = 0;
int ay2 = 0;
if (GetWindowRect(hwnd, &rect)) /* TODO/FIXME - won't work for WinRT */
{
ax1 = rect.left;
ay1 = rect.top;
ax2 = rect.right;
ay2 = rect.bottom;
}
/* Get the rectangle bounds of current output */
if (FAILED(DXGIGetOutputDesc(current_output, &desc)))
{
RARCH_ERR("[DXGI]: Failed to get DXGI output description\n");
goto error;
}
/* TODO/FIXME - DesktopCoordinates won't work for WinRT */
r = desc.DesktopCoordinates;
bx1 = r.left;
by1 = r.top;
bx2 = r.right;
by2 = r.bottom;
/* Compute the intersection */
intersect_area = dxgi_compute_intersection_area(
ax1, ay1, ax2, ay2, bx1, by1, bx2, by2);
if (intersect_area > best_intersect_area)
{
best_output = current_output;
AddRef(best_output);
best_intersect_area = (float)intersect_area;
}
i++;
}
if (SUCCEEDED(best_output->lpVtbl->QueryInterface(
best_output,
&libretro_IID_IDXGIOutput6, (void**)&output6)))
{
DXGI_OUTPUT_DESC1 desc1;
if (SUCCEEDED(DXGIGetOutputDesc1(output6, &desc1)))
{
supported = (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
if (supported)
video_driver_set_hdr_support();
else
{
settings_t* settings = config_get_ptr();
settings->modified = true;
settings->bools.video_hdr_enable = false;
video_driver_unset_hdr_support();
}
}
else
{
RARCH_ERR("[DXGI]: Failed to get DXGI Output 6 description\n");
}
Release(output6);
}
else
{
RARCH_ERR("[DXGI]: Failed to get DXGI Output 6 from best output\n");
}
error:
Release(best_output);
Release(current_output);
Release(dxgi_adapter);
return supported;
}
void dxgi_swapchain_color_space(
DXGISwapChain chain_handle,
DXGI_COLOR_SPACE_TYPE *chain_color_space,
DXGI_COLOR_SPACE_TYPE color_space)
{
if (*chain_color_space != color_space)
{
UINT color_space_support = 0;
if (SUCCEEDED(DXGICheckColorSpaceSupport(
chain_handle, color_space,
&color_space_support))
&& ((color_space_support &
DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)
== DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT))
{
if (FAILED(DXGISetColorSpace1(chain_handle, color_space)))
{
RARCH_ERR("[DXGI]: Failed to set DXGI swapchain colour space\n");
/* TODO/FIXME/CLARIFICATION: Was this fall-through intentional?
* Should chain color space still be set even when this fails?
* Going to assume this was wrong and early return instead
*/
return;
}
*chain_color_space = color_space;
}
}
}
void dxgi_set_hdr_metadata(
DXGISwapChain handle,
bool hdr_supported,
enum dxgi_swapchain_bit_depth chain_bit_depth,
DXGI_COLOR_SPACE_TYPE chain_color_space,
float max_output_nits,
float min_output_nits,
float max_cll,
float max_fall
)
{
static const display_chromaticities_t
display_chromaticity_list[] =
{
{ 0.64000f, 0.33000f, 0.30000f, 0.60000f, 0.15000f, 0.06000f, 0.31270f, 0.32900f }, /* Rec709 */
{ 0.70800f, 0.29200f, 0.17000f, 0.79700f, 0.13100f, 0.04600f, 0.31270f, 0.32900f }, /* Rec2020 */
};
const display_chromaticities_t* chroma = NULL;
DXGI_HDR_METADATA_HDR10 hdr10_meta_data = {0};
int selected_chroma = 0;
if (!handle)
return;
/* Clear the hdr meta data if the monitor does not support HDR */
if (!hdr_supported)
{
if (FAILED(DXGISetHDRMetaData(handle,
DXGI_HDR_METADATA_TYPE_NONE, 0, NULL)))
{
RARCH_ERR("[DXGI]: Failed to set HDR meta data to none\n");
}
return;
}
/* Now select the chromacity based on colour space */
if ( chain_bit_depth == DXGI_SWAPCHAIN_BIT_DEPTH_10
&& chain_color_space ==
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
selected_chroma = 1;
else
{
if (FAILED(DXGISetHDRMetaData(handle,
DXGI_HDR_METADATA_TYPE_NONE, 0, NULL)))
{
RARCH_ERR("[DXGI]: Failed to set HDR meta data to none\n");
}
return;
}
/* Set the HDR meta data */
chroma =
&display_chromaticity_list[selected_chroma];
hdr10_meta_data.RedPrimary[0] =
(UINT16)(chroma->red_x * 50000.0f);
hdr10_meta_data.RedPrimary[1] =
(UINT16)(chroma->red_y * 50000.0f);
hdr10_meta_data.GreenPrimary[0] =
(UINT16)(chroma->green_x * 50000.0f);
hdr10_meta_data.GreenPrimary[1] =
(UINT16)(chroma->green_y * 50000.0f);
hdr10_meta_data.BluePrimary[0] =
(UINT16)(chroma->blue_x * 50000.0f);
hdr10_meta_data.BluePrimary[1] =
(UINT16)(chroma->blue_y * 50000.0f);
hdr10_meta_data.WhitePoint[0] =
(UINT16)(chroma->white_x * 50000.0f);
hdr10_meta_data.WhitePoint[1] =
(UINT16)(chroma->white_y * 50000.0f);
hdr10_meta_data.MaxMasteringLuminance =
(UINT)(max_output_nits * 10000.0f);
hdr10_meta_data.MinMasteringLuminance =
(UINT)(min_output_nits * 10000.0f);
hdr10_meta_data.MaxContentLightLevel =
(UINT16)(max_cll);
hdr10_meta_data.MaxFrameAverageLightLevel =
(UINT16)(max_fall);
if (FAILED(DXGISetHDRMetaData(handle,
DXGI_HDR_METADATA_TYPE_HDR10,
sizeof(DXGI_HDR_METADATA_HDR10), &hdr10_meta_data)))
{
RARCH_ERR("[DXGI]: Failed to set HDR meta data for HDR10\n");
}
}
#endif

View File

@ -2,6 +2,41 @@
#include <retro_inline.h>
#ifndef __WINRT__
#ifndef HAVE_DXGI_HDR
#define HAVE_DXGI_HDR
#endif
#endif
#ifdef HAVE_DXGI_HDR
#ifndef ALIGN
#ifdef _MSC_VER
#define ALIGN(x) __declspec(align(x))
#else
#define ALIGN(x) __attribute__((aligned(x)))
#endif
#endif
#include <gfx/math/matrix_4x4.h>
typedef struct ALIGN(16)
{
math_matrix_4x4 mvp;
float contrast; /* 2.0f */
float paperWhiteNits; /* 200.0f */
float maxNits; /* 1000.0f */
float expandGamut; /* 1.0f */
} dxgi_hdr_uniform_t;
enum dxgi_swapchain_bit_depth
{
DXGI_SWAPCHAIN_BIT_DEPTH_8 = 0,
DXGI_SWAPCHAIN_BIT_DEPTH_10,
DXGI_SWAPCHAIN_BIT_DEPTH_16,
DXGI_SWAPCHAIN_BIT_DEPTH_COUNT
};
#endif
#ifdef __MINGW32__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
/* Pointer parameters */
@ -233,7 +268,7 @@
#endif
#include <assert.h>
#include <dxgi1_5.h>
#include <dxgi1_6.h>
#ifndef countof
#define countof(a) (sizeof(a) / sizeof(*a))
@ -281,6 +316,7 @@ typedef IDXGIResource* DXGIResource;
typedef IDXGIKeyedMutex* DXGIKeyedMutex;
typedef IDXGISurface1* DXGISurface;
typedef IDXGIOutput* DXGIOutput;
typedef IDXGIOutput6* DXGIOutput6;
typedef IDXGIDevice* DXGIDevice;
typedef IDXGIFactory1* DXGIFactory;
#ifdef __WINRT__
@ -292,7 +328,7 @@ typedef IDXGIOutputDuplication* DXGIOutputDuplication;
typedef IDXGIDecodeSwapChain* DXGIDecodeSwapChain;
typedef IDXGIFactoryMedia* DXGIFactoryMedia;
typedef IDXGISwapChainMedia* DXGISwapChainMedia;
typedef IDXGISwapChain3* DXGISwapChain;
typedef IDXGISwapChain4* DXGISwapChain;
#if !defined(__cplusplus) || defined(CINTERFACE)
static INLINE ULONG DXGIReleaseDeviceSubObject(DXGIDeviceSubObject device_sub_object)
@ -392,6 +428,14 @@ static INLINE HRESULT DXGIGetDisplaySurfaceData(DXGIOutput output, DXGISurface d
{
return output->lpVtbl->GetDisplaySurfaceData(output, (IDXGISurface*)destination);
}
static INLINE HRESULT DXGIGetOutputDesc(DXGIOutput output, DXGI_OUTPUT_DESC* desc)
{
return output->lpVtbl->GetDesc(output, desc);
}
static INLINE HRESULT DXGIGetOutputDesc1(DXGIOutput6 output, DXGI_OUTPUT_DESC1* desc)
{
return output->lpVtbl->GetDesc1(output, desc);
}
static INLINE ULONG DXGIReleaseDevice(DXGIDevice device) { return device->lpVtbl->Release(device); }
static INLINE HRESULT DXGICreateSurface(
DXGIDevice device,
@ -769,11 +813,14 @@ static INLINE HRESULT DXGICheckColorSpaceSupport(
{
return swap_chain->lpVtbl->CheckColorSpaceSupport(swap_chain, color_space, color_space_support);
}
static INLINE HRESULT
DXGISetColorSpace1(DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space)
static INLINE HRESULT DXGISetColorSpace1(DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space)
{
return swap_chain->lpVtbl->SetColorSpace1(swap_chain, color_space);
}
static INLINE HRESULT DXGISetHDRMetaData(DXGISwapChain swap_chain, DXGI_HDR_METADATA_TYPE type, UINT size, void *metaData)
{
return swap_chain->lpVtbl->SetHDRMetaData(swap_chain, type, size, metaData);
}
#endif
/* end of auto-generated */
@ -821,6 +868,26 @@ void dxgi_copy(
int dst_pitch,
void* dst_data);
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
bool dxgi_check_display_hdr_support(DXGIFactory2 factory, HWND hwnd);
#else
bool dxgi_check_display_hdr_support(DXGIFactory factory, HWND hwnd);
#endif
void dxgi_swapchain_color_space(DXGISwapChain handle, DXGI_COLOR_SPACE_TYPE
*chain_color_space, DXGI_COLOR_SPACE_TYPE color_space);
void dxgi_set_hdr_metadata(
DXGISwapChain handle,
bool hdr_supported,
enum dxgi_swapchain_bit_depth chain_bit_depth,
DXGI_COLOR_SPACE_TYPE chain_color_space,
float max_output_nits,
float min_output_nits,
float max_cll,
float max_fall
);
#endif
DXGI_FORMAT glslang_format_to_dxgi(glslang_format fmt);
RETRO_END_DECLS

View File

@ -932,6 +932,12 @@ static LRESULT CALLBACK wnd_proc_common(
/* fall-through */
case WM_MOVE:
win32_save_position();
#if 0
#if !defined(_XBOX)
if(d3d12)
d3d12_check_display_hdr_support(d3d12, hwnd);
#endif
#endif
break;
case WM_SIZE:
/* Do not send resize message if we minimize. */

View File

@ -270,6 +270,10 @@ static const video_poke_interface_t caca_poke_interface = {
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void caca_gfx_get_poke_interface(void *data,

View File

@ -1535,7 +1535,11 @@ static const video_poke_interface_t ctr_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void ctr_get_poke_interface(void* data,

View File

@ -1008,7 +1008,7 @@ static void *d3d10_gfx_init(const video_info_t* video,
#else
DXGICreateFactory(&d3d10->factory);
#endif
{
int i = 0;
int gpu_index = settings->ints.d3d10_gpu_index;
@ -1800,6 +1800,10 @@ static const video_poke_interface_t d3d10_poke_interface = {
#else
NULL, /* get_hw_render_interface */
#endif
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void d3d10_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface)

View File

@ -255,6 +255,79 @@ static void d3d11_get_overlay_interface(
}
#endif
#ifdef HAVE_DXGI_HDR
static void d3d11_set_hdr_max_nits(void *data, float max_nits)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->hdr.max_output_nits = max_nits;
d3d11->hdr.ubo_values.maxNits = max_nits;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_ubo);
{
dxgi_hdr_uniform_t *ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
}
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
dxgi_set_hdr_metadata(
d3d11->swapChain,
d3d11->hdr.support,
d3d11->chain_bit_depth,
d3d11->chain_color_space,
d3d11->hdr.max_output_nits,
d3d11->hdr.min_output_nits,
d3d11->hdr.max_cll,
d3d11->hdr.max_fall);
}
static void d3d11_set_hdr_paper_white_nits(void* data, float paper_white_nits)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
dxgi_hdr_uniform_t *ubo = NULL;
d3d11_video_t *d3d11 = (d3d11_video_t*)data;
d3d11->hdr.ubo_values.paperWhiteNits = paper_white_nits;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
}
static void d3d11_set_hdr_contrast(void* data, float contrast)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
dxgi_hdr_uniform_t *ubo = NULL;
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->hdr.ubo_values.contrast = contrast;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
}
static void d3d11_set_hdr_expand_gamut(void* data, bool expand_gamut)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
dxgi_hdr_uniform_t *ubo = NULL;
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->hdr.ubo_values.expandGamut = expand_gamut;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
}
#endif
static void d3d11_set_filtering(void* data, unsigned index,
bool smooth, bool ctx_scaling)
{
@ -559,6 +632,10 @@ static void d3d11_gfx_free(void* data)
d3d11_release_texture(&d3d11->menu.texture);
Release(d3d11->menu.vbo);
#ifdef HAVE_DXGI_HDR
Release(d3d11->hdr.ubo);
#endif
d3d11_release_shader(&d3d11->sprites.shader);
d3d11_release_shader(&d3d11->sprites.shader_font);
Release(d3d11->sprites.vbo);
@ -580,6 +657,10 @@ static void d3d11_gfx_free(void* data)
Release(d3d11->samplers[RARCH_FILTER_NEAREST][i]);
}
#ifdef HAVE_DXGI_HDR
d3d11_release_texture(&d3d11->back_buffer);
#endif
Release(d3d11->scissor_enabled);
Release(d3d11->scissor_disabled);
Release(d3d11->swapChain);
@ -607,6 +688,10 @@ static void d3d11_gfx_free(void* data)
}
}
#ifdef HAVE_DXGI_HDR
video_driver_unset_hdr_support();
#endif
#ifdef HAVE_MONITOR
win32_monitor_from_window();
#endif
@ -622,6 +707,7 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
D3D11DeviceContext *cached_context,
void *corewindow)
{
HWND hwnd;
#ifdef __WINRT__
IDXGIFactory2* dxgiFactory = NULL;
#else
@ -646,19 +732,51 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
#endif
UINT number_feature_levels = ARRAY_SIZE(requested_feature_levels);
#ifdef HAVE_DXGI_HDR
DXGI_COLOR_SPACE_TYPE color_space;
d3d11->chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_8] = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d11->chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_10] = DXGI_FORMAT_R10G10B10A2_UNORM;
d3d11->chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_16] = DXGI_FORMAT_R16G16B16A16_UNORM;
#endif
hwnd = (HWND)corewindow;
#ifdef HAVE_DXGI_HDR
if (!(d3d11->hdr.support =
dxgi_check_display_hdr_support(d3d11->factory, hwnd)))
d3d11->hdr.enable = false;
d3d11->chain_bit_depth = d3d11->hdr.enable
? DXGI_SWAPCHAIN_BIT_DEPTH_10
: DXGI_SWAPCHAIN_BIT_DEPTH_8;
#endif
#ifdef __WINRT__
/* Flip model forces us to do double-buffering */
desc.BufferCount = 2;
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.support)
desc.Format = d3d11->chain_formats[
d3d11->chain_bit_depth];
else
#endif
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#else
desc.BufferCount = 2;
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.support)
desc.BufferDesc.Format = d3d11->chain_formats[
d3d11->chain_bit_depth];
else
#endif
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.RefreshRate.Numerator = 60;
desc.BufferDesc.RefreshRate.Denominator = 1;
#endif
@ -777,7 +895,44 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
}
#endif
#endif // __WINRT__
#endif /* __WINRT__ */
#ifdef HAVE_DXGI_HDR
/* Check display HDR support and
initialize ST.2084 support to match
the display's support. */
#if 0
d3d11->hdr.max_output_nits = 300.0f;
d3d11->hdr.min_output_nits = 0.001f;
d3d11->hdr.max_cll = 0.0f;
d3d11->hdr.max_fall = 0.0f;
#endif
color_space =
d3d11->hdr.enable
? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
dxgi_swapchain_color_space(
d3d11->swapChain,
&d3d11->chain_color_space,
color_space);
dxgi_set_hdr_metadata(
d3d11->swapChain,
d3d11->hdr.support,
d3d11->chain_bit_depth,
d3d11->chain_color_space,
d3d11->hdr.max_output_nits,
d3d11->hdr.min_output_nits,
d3d11->hdr.max_cll,
d3d11->hdr.max_fall);
memset(&d3d11->back_buffer, 0, sizeof(d3d11->back_buffer));
d3d11->back_buffer.desc.Width = width;
d3d11->back_buffer.desc.Height = height;
d3d11->back_buffer.desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d11->back_buffer.desc.BindFlags = D3D11_BIND_RENDER_TARGET;
d3d11_init_texture(d3d11->device, &d3d11->back_buffer);
#endif
dxgiFactory->lpVtbl->Release(dxgiFactory);
adapter->lpVtbl->Release(adapter);
@ -840,6 +995,19 @@ static void *d3d11_gfx_init(const video_info_t* video,
d3d_input_driver(settings->arrays.input_driver, settings->arrays.input_joypad_driver, input, input_data);
#ifdef __WINRT__
DXGICreateFactory2(&d3d11->factory);
#else
DXGICreateFactory(&d3d11->factory);
#endif
#ifdef HAVE_DXGI_HDR
d3d11->hdr.enable = settings->bools.video_hdr_enable;
d3d11->hdr.max_output_nits = settings->floats.video_hdr_max_nits;
d3d11->hdr.min_output_nits = 0.001f;
d3d11->hdr.max_cll = 0.0f;
d3d11->hdr.max_fall = 0.0f;
#endif
#ifdef __WINRT__
if (!d3d11_init_swapchain(d3d11,
d3d11->vp.full_width,
@ -905,6 +1073,39 @@ static void *d3d11_gfx_init(const video_info_t* video,
d3d11_gfx_set_rotation(d3d11, 0);
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.enable)
{
D3D11_BUFFER_DESC desc;
D3D11_SUBRESOURCE_DATA ubo_data;
matrix_4x4_ortho(d3d11->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
d3d11->hdr.ubo_values.mvp =
d3d11->mvp_no_rot;
d3d11->hdr.ubo_values.maxNits =
settings->floats.video_hdr_max_nits;
d3d11->hdr.ubo_values.paperWhiteNits =
settings->floats.video_hdr_paper_white_nits;
d3d11->hdr.ubo_values.contrast =
settings->floats.video_hdr_contrast;
d3d11->hdr.ubo_values.expandGamut =
settings->bools.video_hdr_expand_gamut;
desc.ByteWidth = sizeof(dxgi_hdr_uniform_t);
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
ubo_data.pSysMem = &d3d11->hdr.ubo_values.mvp;
ubo_data.SysMemPitch = 0;
ubo_data.SysMemSlicePitch = 0;
D3D11CreateBuffer(d3d11->device, &desc, &ubo_data, &d3d11->hdr.ubo);
}
#endif
{
D3D11_SAMPLER_DESC desc = { D3D11_FILTER_MIN_MAG_MIP_POINT };
desc.MaxAnisotropy = 1;
@ -974,6 +1175,33 @@ static void *d3d11_gfx_init(const video_info_t* video,
D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->sprites.vbo);
}
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.enable)
{
D3D11_INPUT_ELEMENT_DESC desc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0,
offsetof(d3d11_vertex_t, position),
D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0,
offsetof(d3d11_vertex_t, texcoord),
D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
offsetof(d3d11_vertex_t, color),
D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
static const char shader[] =
#include "d3d_shaders/hdr_sm5.hlsl.h"
;
if (!d3d11_init_shader(
d3d11->device, shader, sizeof(shader),
NULL, "VSMain", "PSMain", NULL, desc,
countof(desc), &d3d11->shaders[VIDEO_SHADER_STOCK_HDR]))
goto error;
}
#endif
{
D3D11_INPUT_ELEMENT_DESC desc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, position),
@ -1156,12 +1384,6 @@ static void *d3d11_gfx_init(const video_info_t* video,
d3d11->hw.iface.D3DCompile = D3DCompile;
}
#ifdef __WINRT__
DXGICreateFactory2(&d3d11->factory);
#else
DXGICreateFactory(&d3d11->factory);
#endif
{
int i = 0;
int gpu_index = settings->ints.d3d11_gpu_index;
@ -1384,32 +1606,91 @@ static bool d3d11_gfx_frame(
#ifdef HAVE_GFX_WIDGETS
bool widgets_active = video_info->widgets_active;
#endif
#ifdef HAVE_DXGI_HDR
bool video_hdr_enable = video_info->hdr_enable;
if ( d3d11->resize_chain ||
(d3d11->hdr.enable != video_hdr_enable))
#else
if (d3d11->resize_chain)
#endif
{
UINT swapchain_flags = d3d11->has_allow_tearing
UINT swapchain_flags = d3d11->has_allow_tearing
? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0, DXGI_FORMAT_UNKNOWN,
swapchain_flags);
#ifdef HAVE_DXGI_HDR
d3d11->hdr.enable = video_hdr_enable;
d3d11->viewport.Width = video_width;
d3d11->viewport.Height = video_height;
d3d11->scissor.right = video_width;
d3d11->scissor.bottom = video_height;
if(d3d11->hdr.enable)
d3d11_release_texture(&d3d11->back_buffer);
DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0,
d3d11->chain_formats[d3d11->chain_bit_depth],
swapchain_flags);
#else
DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0,
DXGI_FORMAT_UNKNOWN,
swapchain_flags);
#endif
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->resize_chain = false;
d3d11->resize_viewport = true;
d3d11->resize_chain = false;
d3d11->resize_viewport = true;
video_driver_set_size(video_width, video_height);
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
if (!(d3d11->hdr.support =
dxgi_check_display_hdr_support(d3d11->factory, uwp_get_corewindow())))
d3d11->hdr.enable = false;
#else
if (!(d3d11->hdr.support =
dxgi_check_display_hdr_support(d3d11->factory, main_window.hwnd)))
d3d11->hdr.enable = false;
#endif
if(d3d11->hdr.enable)
{
memset(&d3d11->back_buffer, 0, sizeof(d3d11->back_buffer));
d3d11->back_buffer.desc.Width = video_width;
d3d11->back_buffer.desc.Height = video_height;
d3d11->back_buffer.desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d11->back_buffer.desc.BindFlags = D3D11_BIND_RENDER_TARGET;
d3d11_init_texture(d3d11->device, &d3d11->back_buffer);
dxgi_swapchain_color_space(
d3d11->swapChain,
&d3d11->chain_color_space,
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
}
else
dxgi_swapchain_color_space(
d3d11->swapChain,
&d3d11->chain_color_space,
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
dxgi_set_hdr_metadata(
d3d11->swapChain,
d3d11->hdr.support,
d3d11->chain_bit_depth,
d3d11->chain_color_space,
d3d11->hdr.max_output_nits,
d3d11->hdr.min_output_nits,
d3d11->hdr.max_cll,
d3d11->hdr.max_fall);
#endif
}
{
D3D11Texture2D backBuffer;
DXGIGetSwapChainBufferD3D11(d3d11->swapChain, 0, &backBuffer);
D3D11CreateTexture2DRenderTargetView(d3d11->device, backBuffer, NULL, &rtv);
Release(backBuffer);
D3D11Texture2D back_buffer;
DXGIGetSwapChainBufferD3D11(d3d11->swapChain, 0, &back_buffer);
D3D11CreateTexture2DRenderTargetView(d3d11->device, back_buffer, NULL, &rtv);
Release(back_buffer);
}
/* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */
@ -1603,8 +1884,25 @@ static bool d3d11_gfx_frame(
}
}
D3D11SetRenderTargets(context, 1, &rtv, NULL);
D3D11ClearRenderTargetView(context, rtv, d3d11->clearcolor);
#ifdef HAVE_DXGI_HDR
if(d3d11->hdr.enable)
{
/* TODO/FIXME -
* following D3D11 warnings are spammed in Debug mode -
* Forcing PS shader resource slot 0 to NULL. [ STATE_SETTING WARNING #7: DEVICE_PSSETSHADERRESOURCES_HAZARD]
* Resource being set to OM RenderTarget slot 0 is still bound on input! [ STATE_SETTING WARNING #9: DEVICE_OMSETRENDERTARGETS_HAZARD]
*/
D3D11SetRenderTargets(context, 1, &d3d11->back_buffer.rt_view, NULL);
D3D11ClearRenderTargetView(context, d3d11->back_buffer.rt_view, d3d11->clearcolor);
}
else
#endif
{
D3D11SetRenderTargets(context, 1, &rtv, NULL);
D3D11ClearRenderTargetView(context, rtv, d3d11->clearcolor);
}
D3D11SetViewports(context, 1, &d3d11->frame.viewport);
if (texture)
@ -1702,6 +2000,41 @@ static bool d3d11_gfx_frame(
#if defined(_WIN32) && !defined(__WINRT__)
win32_update_title();
#endif
#ifdef HAVE_DXGI_HDR
/* Copy over back buffer to swap chain render targets */
if(d3d11->hdr.enable)
{
D3D11SetRenderTargets(context, 1, &rtv, NULL);
D3D11ClearRenderTargetView(context, rtv,
d3d11->clearcolor);
D3D11SetViewports(context, 1,
&d3d11->viewport);
D3D11SetScissorRects(context, 1,
&d3d11->scissor);
d3d11_set_shader(context,
&d3d11->shaders[VIDEO_SHADER_STOCK_HDR]);
D3D11SetVShaderConstantBuffer(context, 0,
d3d11->hdr.ubo);
D3D11SetPShaderResources(context, 0, 1,
&d3d11->back_buffer.view);
D3D11SetPShaderSamplers(context, 0, 1,
&d3d11->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
D3D11SetPShaderConstantBuffer(context, 0, d3d11->hdr.ubo);
D3D11SetVertexBuffer(context, 0, d3d11->frame.vbo,
sizeof(d3d11_vertex_t), 0);
D3D11SetRasterizerState(context, d3d11->scissor_disabled);
D3D11SetBlendState(context, d3d11->blend_disable, NULL,
D3D11_DEFAULT_SAMPLE_MASK);
D3D11SetPrimitiveTopology(context,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D11Draw(context, 4, 0);
}
#endif
DXGIPresent(d3d11->swapChain, !!vsync, present_flags);
Release(rtv);
@ -1957,6 +2290,17 @@ static const video_poke_interface_t d3d11_poke_interface = {
d3d11_gfx_get_current_shader,
NULL, /* get_current_software_framebuffer */
d3d11_get_hw_render_interface,
#ifdef HAVE_DXGI_HDR
d3d11_set_hdr_max_nits,
d3d11_set_hdr_paper_white_nits,
d3d11_set_hdr_contrast,
d3d11_set_hdr_expand_gamut
#else
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
#endif
};
static void d3d11_gfx_get_poke_interface(void* data,

View File

@ -238,6 +238,78 @@ static void d3d12_get_overlay_interface(void* data, const video_overlay_interfac
}
#endif
#if 0
d3d12->hdr.max_output_nits = settings->floats.video_hdr_max_nits;
d3d12->hdr.ubo_values.maxNits = settings->floats.video_hdr_max_nits;
d3d12->hdr.ubo_values.paperWhiteNits = settings->floats.video_hdr_paper_white_nits;
d3d12->hdr.ubo_values.contrast = settings->floats.video_hdr_contrast;
d3d12->hdr.ubo_values.expandGamut = settings->bools.video_hdr_expand_gamut;
#endif
#ifdef HAVE_DXGI_HDR
static void d3d12_set_hdr_max_nits(void* data, float max_nits)
{
dxgi_hdr_uniform_t *mapped_ubo = NULL;
D3D12_RANGE read_range = { 0, 0 };
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
d3d12->hdr.max_output_nits = max_nits;
d3d12->hdr.ubo_values.maxNits = max_nits;
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->hdr.support,
d3d12->chain.bit_depth,
d3d12->chain.color_space,
d3d12->hdr.max_output_nits,
d3d12->hdr.min_output_nits,
d3d12->hdr.max_cll,
d3d12->hdr.max_fall);
}
static void d3d12_set_hdr_paper_white_nits(void* data, float paper_white_nits)
{
D3D12_RANGE read_range = { 0, 0 };
dxgi_hdr_uniform_t *mapped_ubo = NULL;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
d3d12->hdr.ubo_values.paperWhiteNits = paper_white_nits;
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
static void d3d12_set_hdr_contrast(void* data, float contrast)
{
D3D12_RANGE read_range = { 0, 0 };
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
dxgi_hdr_uniform_t *mapped_ubo = NULL;
d3d12->hdr.ubo_values.contrast = contrast;
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
static void d3d12_set_hdr_expand_gamut(void* data, bool expand_gamut)
{
D3D12_RANGE read_range = { 0, 0 };
dxgi_hdr_uniform_t *mapped_ubo = NULL;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
d3d12->hdr.ubo_values.expandGamut = expand_gamut;
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
#endif
static void d3d12_set_filtering(void* data, unsigned index, bool smooth, bool ctx_scaling)
{
int i;
@ -494,9 +566,18 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
if (!d3d12->pass[i].pipe)
goto error;
#ifdef HAVE_DXGI_HDR
d3d12->pass[i].rt.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr +
(countof(d3d12->chain.renderTargets) + (2 * i)) * d3d12->desc.rtv_heap.stride;
d3d12->desc.rtv_heap.cpu.ptr +
(countof(d3d12->chain.renderTargets) + 1 + (2 * i))
* d3d12->desc.rtv_heap.stride;
#else
d3d12->pass[i].rt.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr +
(countof(d3d12->chain.renderTargets) + (2 * i))
* d3d12->desc.rtv_heap.stride;
#endif
d3d12->pass[i].feedback.rt_view.ptr = d3d12->pass[i].rt.rt_view.ptr + d3d12->desc.rtv_heap.stride;
d3d12->pass[i].textures.ptr =
@ -562,12 +643,51 @@ 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;
#ifdef HAVE_DXGI_HDR
desc.RTVFormats[0] = DXGI_FORMAT_R10G10B10A2_UNORM;
{
static const char shader[] =
#include "d3d_shaders/hdr_sm5.hlsl.h"
;
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position),
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord),
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_vertex_t, color),
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};
if (!d3d_compile(shader, sizeof(shader), NULL, "VSMain", "vs_5_0", &vs_code))
goto error;
if (!d3d_compile(shader, sizeof(shader), NULL, "PSMain", "ps_5_0", &ps_code))
goto error;
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
desc.InputLayout.pInputElementDescs = inputElementDesc;
desc.InputLayout.NumElements = countof(inputElementDesc);
if (!d3d12_init_pipeline(
d3d12->device, vs_code, ps_code, NULL, &desc,
&d3d12->pipes[VIDEO_SHADER_STOCK_HDR]))
goto error;
Release(vs_code);
Release(ps_code);
vs_code = NULL;
ps_code = NULL;
}
#endif
desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc;
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
{
static const char shader[] =
#include "../drivers/d3d_shaders/opaque_sm5.hlsl.h"
#include "d3d_shaders/opaque_sm5.hlsl.h"
;
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
@ -839,6 +959,10 @@ static void d3d12_gfx_free(void* data)
Release(d3d12->sprites.vbo);
Release(d3d12->menu_pipeline_vbo);
#ifdef HAVE_DXGI_HDR
Release(d3d12->hdr.ubo);
#endif
Release(d3d12->frame.ubo);
Release(d3d12->frame.vbo);
Release(d3d12->frame.texture[0].handle);
@ -847,6 +971,10 @@ static void d3d12_gfx_free(void* data)
Release(d3d12->menu.texture.handle);
Release(d3d12->menu.texture.upload_buffer);
#ifdef HAVE_DXGI_HDR
d3d12_release_texture(&d3d12->chain.back_buffer);
d3d12->chain.back_buffer.handle = NULL;
#endif
free(d3d12->desc.sampler_heap.map);
free(d3d12->desc.srv_heap.map);
free(d3d12->desc.rtv_heap.map);
@ -890,6 +1018,10 @@ static void d3d12_gfx_free(void* data)
}
}
#ifdef HAVE_DXGI_HDR
video_driver_unset_hdr_support();
#endif
#ifdef HAVE_MONITOR
win32_monitor_from_window();
#endif
@ -951,6 +1083,14 @@ static void *d3d12_gfx_init(const video_info_t* video,
goto error;
}
#ifdef HAVE_DXGI_HDR
d3d12->hdr.enable = settings->bools.video_hdr_enable;
d3d12->hdr.max_output_nits = settings->floats.video_hdr_max_nits;
d3d12->hdr.min_output_nits = 0.001f;
d3d12->hdr.max_cll = 0.0f;
d3d12->hdr.max_fall = 0.0f;
#endif
d3d_input_driver(settings->arrays.input_driver, settings->arrays.input_joypad_driver, input, input_data);
if (!d3d12_init_base(d3d12))
@ -1007,6 +1147,26 @@ static void *d3d12_gfx_init(const video_info_t* video,
D3D12Unmap(d3d12->ubo, 0, NULL);
}
#ifdef HAVE_DXGI_HDR
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_values.mvp = d3d12->mvp_no_rot;
d3d12->hdr.ubo_values.maxNits = settings->floats.video_hdr_max_nits;
d3d12->hdr.ubo_values.paperWhiteNits = settings->floats.video_hdr_paper_white_nits;
d3d12->hdr.ubo_values.contrast = settings->floats.video_hdr_contrast;
d3d12->hdr.ubo_values.expandGamut = settings->bools.video_hdr_expand_gamut;
{
dxgi_hdr_uniform_t* mapped_ubo;
D3D12_RANGE read_range = { 0, 0 };
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
#endif
d3d12_gfx_set_rotation(d3d12, 0);
video_driver_set_size(d3d12->vp.full_width, d3d12->vp.full_height);
d3d12->chain.viewport.Width = d3d12->vp.full_width;
@ -1197,53 +1357,132 @@ static bool d3d12_gfx_frame(
#ifdef HAVE_GFX_WIDGETS
bool widgets_active = video_info->widgets_active;
#endif
#ifdef HAVE_DXGI_HDR
bool video_hdr_enable = video_info->hdr_enable;
if (d3d12->resize_chain || (d3d12->hdr.enable != video_hdr_enable))
#else
if (d3d12->resize_chain)
#endif
{
unsigned i;
#ifdef HAVE_DXGI_HDR
d3d12->hdr.enable = video_hdr_enable;
#endif
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
Release(d3d12->chain.renderTargets[i]);
DXGIResizeBuffers(d3d12->chain.handle, 0, 0, 0, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING);
#ifdef HAVE_DXGI_HDR
if (d3d12->hdr.enable)
{
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);
#else
DXGIResizeBuffers(d3d12->chain.handle,
0,
0,
0,
DXGI_FORMAT_UNKNOWN,
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING);
#endif
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
{
DXGIGetSwapChainBuffer(d3d12->chain.handle, i, &d3d12->chain.renderTargets[i]);
DXGIGetSwapChainBuffer(d3d12->chain.handle, i,
&d3d12->chain.renderTargets[i]);
D3D12CreateRenderTargetView(
d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]);
d3d12->device, d3d12->chain.renderTargets[i],
NULL, d3d12->chain.desc_handles[i]);
}
d3d12->chain.viewport.Width = video_width;
d3d12->chain.viewport.Height = video_height;
d3d12->chain.scissorRect.right = video_width;
d3d12->chain.scissorRect.bottom = video_height;
d3d12->resize_chain = false;
d3d12->resize_viewport = true;
d3d12->chain.viewport.Width = video_width;
d3d12->chain.viewport.Height = video_height;
d3d12->chain.scissorRect.right = video_width;
d3d12->chain.scissorRect.bottom = video_height;
d3d12->resize_chain = false;
d3d12->resize_viewport = true;
d3d12->ubo_values.OutputSize.width = d3d12->chain.viewport.Width;
d3d12->ubo_values.OutputSize.height = d3d12->chain.viewport.Height;
video_driver_set_size(video_width, video_height);
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
if (!(d3d12->hdr.support =
dxgi_check_display_hdr_support(d3d12->factory, uwp_get_corewindow())))
d3d12->hdr.enable = false;
#else
if (!(d3d12->hdr.support =
dxgi_check_display_hdr_support(d3d12->factory, main_window.hwnd)))
d3d12->hdr.enable = false;
#endif
if(d3d12->hdr.enable)
{
memset(&d3d12->chain.back_buffer,
0, sizeof(d3d12->chain.back_buffer));
d3d12->chain.back_buffer.desc.Width = video_width;
d3d12->chain.back_buffer.desc.Height = video_height;
d3d12->chain.back_buffer.desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d12->chain.back_buffer.desc.Flags =
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
d3d12->chain.back_buffer.srv_heap = &d3d12->desc.srv_heap;
d3d12->chain.back_buffer.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr
+ countof(d3d12->chain.renderTargets)
* d3d12->desc.rtv_heap.stride;
d3d12_init_texture(d3d12->device, &d3d12->chain.back_buffer);
dxgi_swapchain_color_space(d3d12->chain.handle,
&d3d12->chain.color_space,
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
}
else
dxgi_swapchain_color_space(d3d12->chain.handle,
&d3d12->chain.color_space,
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
dxgi_set_hdr_metadata(
d3d12->chain.handle,
d3d12->hdr.support,
d3d12->chain.bit_depth,
d3d12->chain.color_space,
d3d12->hdr.max_output_nits,
d3d12->hdr.min_output_nits,
d3d12->hdr.max_cll,
d3d12->hdr.max_fall);
#endif
}
D3D12ResetCommandAllocator(d3d12->queue.allocator);
D3D12ResetGraphicsCommandList(
d3d12->queue.cmd, d3d12->queue.allocator, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
d3d12->queue.cmd, d3d12->queue.allocator,
d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
{
D3D12DescriptorHeap desc_heaps[] = { d3d12->desc.srv_heap.handle,
d3d12->desc.sampler_heap.handle };
D3D12SetDescriptorHeaps(d3d12->queue.cmd, countof(desc_heaps), desc_heaps);
D3D12SetDescriptorHeaps(d3d12->queue.cmd,
countof(desc_heaps), desc_heaps);
}
#if 0 /* 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 (d3d12->resize_viewport)
#endif
d3d12_update_viewport(d3d12, false);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
if (frame && width && height)
{
@ -1260,7 +1499,8 @@ static bool d3d12_gfx_frame(
if (d3d12->resize_render_targets)
{
/* release all render targets first to avoid memory fragmentation */
/* Release all render targets first
to avoid memory fragmentation */
for (i = 0; i < d3d12->shader_preset->passes; i++)
{
d3d12_release_texture(&d3d12->pass[i].rt);
@ -1277,9 +1517,10 @@ static bool d3d12_gfx_frame(
else
{
int k;
/* todo: what about frame-duping ?
/* TODO/FIXME: what about frame-duping ?
* maybe clone d3d12_texture_t with AddRef */
d3d12_texture_t tmp = d3d12->frame.texture[d3d12->shader_preset->history_size];
d3d12_texture_t tmp =
d3d12->frame.texture[d3d12->shader_preset->history_size];
for (k = d3d12->shader_preset->history_size; k > 0; k--)
d3d12->frame.texture[k] = d3d12->frame.texture[k - 1];
d3d12->frame.texture[0] = tmp;
@ -1287,8 +1528,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 ||
/* 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;
@ -1300,7 +1542,8 @@ static bool d3d12_gfx_frame(
if (d3d12->resize_render_targets)
d3d12_init_render_targets(d3d12, width, height);
d3d12_update_texture(width, height, pitch, d3d12->format, frame, &d3d12->frame.texture[0]);
d3d12_update_texture(width, height, pitch, d3d12->format,
frame, &d3d12->frame.texture[0]);
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.texture[0],
d3d12);
@ -1311,7 +1554,8 @@ static bool d3d12_gfx_frame(
if (d3d12->shader_preset)
{
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.sl_rootSignature);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd,
d3d12->desc.sl_rootSignature);
for (i = 0; i < d3d12->shader_preset->passes; i++)
{
@ -1330,16 +1574,17 @@ static bool d3d12_gfx_frame(
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pass[i].pipe);
if (d3d12->shader_preset->pass[i].frame_count_mod)
d3d12->pass[i].frame_count =
frame_count % d3d12->shader_preset->pass[i].frame_count_mod;
d3d12->pass[i].frame_count = frame_count
% d3d12->shader_preset->pass[i].frame_count_mod;
else
d3d12->pass[i].frame_count = frame_count;
#ifdef HAVE_REWIND
d3d12->pass[i].frame_direction = state_manager_frame_is_reversed() ? -1 : 1;
#else
d3d12->pass[i].frame_direction = 1;
if (state_manager_frame_is_reversed())
d3d12->pass[i].frame_direction = -1;
else
#endif
d3d12->pass[i].frame_direction = 1;
for (j = 0; j < SLANG_CBUFFER_MAX; j++)
{
@ -1351,17 +1596,21 @@ static bool d3d12_gfx_frame(
uint8_t* mapped_data = NULL;
uniform_sem_t* uniform = buffer_sem->uniforms;
D3D12Map(d3d12->pass[i].buffers[j], 0, &range, (void**)&mapped_data);
D3D12Map(d3d12->pass[i].buffers[j], 0, &range,
(void**)&mapped_data);
while (uniform->size)
{
if (uniform->data)
memcpy(mapped_data + uniform->offset, uniform->data, uniform->size);
memcpy(mapped_data + uniform->offset,
uniform->data, uniform->size);
uniform++;
}
D3D12Unmap(d3d12->pass[i].buffers[j], 0, NULL);
D3D12SetGraphicsRootConstantBufferView(
d3d12->queue.cmd, j == SLANG_CBUFFER_UBO ? ROOT_ID_UBO : ROOT_ID_PC,
d3d12->queue.cmd, j == SLANG_CBUFFER_UBO
? ROOT_ID_UBO
: ROOT_ID_PC,
d3d12->pass[i].buffer_view[j].BufferLocation);
}
}
@ -1375,15 +1624,19 @@ static bool d3d12_gfx_frame(
{
{
D3D12_CPU_DESCRIPTOR_HANDLE handle = {
d3d12->pass[i].textures.ptr - d3d12->desc.srv_heap.gpu.ptr +
d3d12->desc.srv_heap.cpu.ptr +
texture_sem->binding * d3d12->desc.srv_heap.stride
d3d12->pass[i].textures.ptr
- d3d12->desc.srv_heap.gpu.ptr
+ d3d12->desc.srv_heap.cpu.ptr
+ texture_sem->binding * d3d12->desc.srv_heap.stride
};
d3d12_texture_t* tex = (d3d12_texture_t*)texture_sem->texture_data;
d3d12_texture_t* tex =
(d3d12_texture_t*)texture_sem->texture_data;
D3D12_SHADER_RESOURCE_VIEW_DESC desc = { tex->desc.Format };
desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
desc.Shader4ComponentMapping =
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
desc.ViewDimension =
D3D12_SRV_DIMENSION_TEXTURE2D;
desc.Texture2D.MipLevels = tex->desc.MipLevels;
D3D12CreateShaderResourceView(d3d12->device,
@ -1392,9 +1645,11 @@ static bool d3d12_gfx_frame(
{
D3D12_CPU_DESCRIPTOR_HANDLE handle = {
d3d12->pass[i].samplers.ptr - d3d12->desc.sampler_heap.gpu.ptr +
d3d12->desc.sampler_heap.cpu.ptr +
texture_sem->binding * d3d12->desc.sampler_heap.stride
d3d12->pass[i].samplers.ptr
- d3d12->desc.sampler_heap.gpu.ptr
+ d3d12->desc.sampler_heap.cpu.ptr
+ texture_sem->binding
* d3d12->desc.sampler_heap.stride
};
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_LINEAR };
@ -1435,29 +1690,37 @@ static bool d3d12_gfx_frame(
}
D3D12SetGraphicsRootDescriptorTable(
d3d12->queue.cmd, ROOT_ID_TEXTURE_T, d3d12->pass[i].textures);
d3d12->queue.cmd, ROOT_ID_TEXTURE_T,
d3d12->pass[i].textures);
D3D12SetGraphicsRootDescriptorTable(
d3d12->queue.cmd, ROOT_ID_SAMPLER_T, d3d12->pass[i].samplers);
d3d12->queue.cmd, ROOT_ID_SAMPLER_T,
d3d12->pass[i].samplers);
}
if (d3d12->pass[i].rt.handle)
{
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->pass[i].rt.handle,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12OMSetRenderTargets(d3d12->queue.cmd, 1, &d3d12->pass[i].rt.rt_view, FALSE, NULL);
D3D12OMSetRenderTargets(d3d12->queue.cmd, 1,
&d3d12->pass[i].rt.rt_view, FALSE, NULL);
#if 0
D3D12ClearRenderTargetView(
d3d12->queue.cmd, d3d12->pass[i].rt.rt_view, d3d12->chain.clearcolor, 0, NULL);
d3d12->queue.cmd, d3d12->pass[i].rt.rt_view,
d3d12->chain.clearcolor, 0, NULL);
#endif
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->pass[i].viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->pass[i].scissorRect);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->pass[i].viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->pass[i].scissorRect);
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->pass[i].rt.handle, D3D12_RESOURCE_STATE_RENDER_TARGET,
d3d12->queue.cmd, d3d12->pass[i].rt.handle,
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
texture = &d3d12->pass[i].rt;
}
@ -1471,31 +1734,68 @@ static bool d3d12_gfx_frame(
if (texture)
{
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd,
d3d12->desc.rootSignature);
d3d12_set_texture(d3d12->queue.cmd, &d3d12->frame.texture[0]);
d3d12_set_sampler(d3d12->queue.cmd, d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
d3d12_set_sampler(d3d12->queue.cmd,
d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
D3D12SetGraphicsRootConstantBufferView(
d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation);
d3d12->queue.cmd, ROOT_ID_UBO,
d3d12->frame.ubo_view.BufferLocation);
}
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(
d3d12->chain.handle);
D3D12OMSetRenderTargets(
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);
#ifdef HAVE_DXGI_HDR
if(d3d12->hdr.enable)
{
d3d12_resource_transition(
d3d12->queue.cmd, 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);
/* 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
*/
D3D12ClearRenderTargetView(
d3d12->queue.cmd, d3d12->chain.back_buffer.rt_view,
d3d12->chain.clearcolor, 0, NULL);
}
else
#endif
{
d3d12_resource_transition(
d3d12->queue.cmd,
d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12OMSetRenderTargets(
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);
}
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->frame.scissorRect);
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature);
if (d3d12->menu.enabled && d3d12->menu.texture.handle)
@ -1520,7 +1820,8 @@ static bool d3d12_gfx_frame(
d3d12->sprites.pipe = d3d12->sprites.pipe_noblend;
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd,
D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
d3d12->sprites.enabled = true;
@ -1529,9 +1830,12 @@ static bool d3d12_gfx_frame(
if (d3d12->menu.enabled)
#endif
{
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->sprites.vbo_view);
}
#endif
@ -1544,10 +1848,14 @@ static bool d3d12_gfx_frame(
{
if (osd_params)
{
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->sprites.vbo_view);
font_driver_render_msg(d3d12, stat_text,
(const struct font_params*)osd_params, NULL);
}
@ -1557,17 +1865,21 @@ static bool d3d12_gfx_frame(
{
if (d3d12->overlays.fullscreen)
{
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
}
else
{
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->frame.scissorRect);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->frame.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->frame.scissorRect);
}
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->overlays.vbo_view);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->overlays.vbo_view);
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe_blend);
D3D12SetGraphicsRootDescriptorTable(
@ -1582,7 +1894,8 @@ static bool d3d12_gfx_frame(
d3d12);
D3D12SetGraphicsRootDescriptorTable(
d3d12->queue.cmd, ROOT_ID_TEXTURE_T, d3d12->overlays.textures[i].gpu_descriptor[0]);
d3d12->queue.cmd, ROOT_ID_TEXTURE_T,
d3d12->overlays.textures[i].gpu_descriptor[0]);
D3D12DrawInstanced(d3d12->queue.cmd, 1, 1, i, 0);
}
}
@ -1595,21 +1908,78 @@ static bool d3d12_gfx_frame(
if (msg && *msg)
{
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->sprites.vbo_view);
font_driver_render_msg(d3d12, msg, NULL, NULL);
}
d3d12->sprites.enabled = false;
#ifdef HAVE_DXGI_HDR
/* Copy over back buffer to swap chain render targets */
if (d3d12->hdr.enable)
{
d3d12_resource_transition(
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);
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);
D3D12ClearRenderTargetView(
d3d12->queue.cmd,
d3d12->chain.desc_handles[d3d12->chain.frame_index],
d3d12->chain.clearcolor, 0, NULL);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd,
d3d12->desc.rootSignature);
d3d12_set_texture(d3d12->queue.cmd, &d3d12->chain.back_buffer);
d3d12_set_sampler(d3d12->queue.cmd,
d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
D3D12SetGraphicsRootConstantBufferView(
d3d12->queue.cmd, ROOT_ID_UBO,
d3d12->hdr.ubo_view.BufferLocation);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->frame.vbo_view);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
}
#endif
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
d3d12->queue.cmd,
d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT);
D3D12CloseGraphicsCommandList(d3d12->queue.cmd);
D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1, &d3d12->queue.cmd);
D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1,
&d3d12->queue.cmd);
#if defined(_WIN32) && !defined(__WINRT__)
win32_update_title();
@ -1890,6 +2260,17 @@ static const video_poke_interface_t d3d12_poke_interface = {
d3d12_gfx_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
#ifdef HAVE_DXGI_HDR
d3d12_set_hdr_max_nits,
d3d12_set_hdr_paper_white_nits,
d3d12_set_hdr_contrast,
d3d12_set_hdr_expand_gamut,
#else
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
#endif
};
static void d3d12_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface)

View File

@ -1831,7 +1831,11 @@ static const video_poke_interface_t d3d_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void d3d8_get_poke_interface(void *data,

View File

@ -1976,7 +1976,11 @@ static const video_poke_interface_t d3d9_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void d3d9_get_poke_interface(void *data,

View File

@ -0,0 +1,120 @@
#define SRC(...) #__VA_ARGS__
SRC(
struct UBO
{
float4x4 modelViewProj;
float contrast; /* 2.0f; */
float paperWhiteNits; /* 200.0f; */
float maxNits; /* 1000.0f; */
float expandGamut; /* 1.0f; */
};
uniform UBO global;
struct PSInput
{
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
float4 color : COLOR;
};
PSInput VSMain(float4 position : POSITION, float2 texcoord : TEXCOORD0, float4 color : COLOR)
{
PSInput result;
result.position = mul(global.modelViewProj, position);
result.texcoord = texcoord;
result.color = color;
return result;
}
uniform sampler s0;
uniform Texture2D <float4> t0;
static const float kMaxNitsFor2084 = 10000.0f;
static const float kEpsilon = 0.0001f;
static const float kLumaChannelRatio = 0.25f;
static const float3x3 k709to2020 =
{
{ 0.6274040f, 0.3292820f, 0.0433136f },
{ 0.0690970f, 0.9195400f, 0.0113612f },
{ 0.0163916f, 0.0880132f, 0.8955950f }
};
static const float3x3 kP3to2020 =
{
{ 0.753845f, 0.198593f, 0.047562f },
{ 0.0457456f, 0.941777f, 0.0124772f },
{ -0.00121055f, 0.0176041f, 0.983607f }
};
/* START Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */
static const float3x3 kExpanded709to2020 =
{
{ 0.6274040f, 0.3292820f, 0.0433136f },
{ 0.0457456, 0.941777, 0.0124772 },
{ -0.00121055, 0.0176041, 0.983607 }
};
float3 LinearToST2084(float3 normalizedLinearValue)
{
float3 ST2084 = pow((0.8359375f + 18.8515625f * pow(abs(normalizedLinearValue), 0.1593017578f)) / (1.0f + 18.6875f * pow(abs(normalizedLinearValue), 0.1593017578f)), 78.84375f);
return ST2084; /* Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits */
}
/* END Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */
float3 SRGBToLinear(float3 color)
{
float3 scale = color / 12.92f;
float3 gamma = pow(abs(color + 0.055f) / 1.055f, 2.4f);
return float3( color.x < 0.04045f ? scale.x : gamma.x,
color.y < 0.04045f ? scale.y : gamma.y,
color.z < 0.04045f ? scale.z : gamma.z);
}
float4 Hdr(float4 sdr)
{
sdr.xyz = pow(abs(sdr.xyz), 2.2f / global.contrast); /* Display Gamma - needs to be determined by calibration screen but should be in the 0.8 - 1.4 range */
float luma = dot(sdr.xyz, float3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */
/* Inverse reinhard tonemap */
float maxValue = (global.maxNits / global.paperWhiteNits) + kEpsilon;
float elbow = maxValue / (maxValue - 1.0f); /* Convert (1.0 + epsilon) to infinite to range 1001 -> 1.0 */
float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); /* Convert 1001 to 1.0 to range 0.5 -> 1.0 */
float hdrLumaInvTonemap = offset + ((luma * elbow) / (elbow - luma));
float sdrLumaInvTonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
float lumaInvTonemap = (luma > 0.5f) ? hdrLumaInvTonemap : sdrLumaInvTonemap;
float3 perLuma = sdr.xyz / (luma + kEpsilon) * lumaInvTonemap;
float3 hdrInvTonemap = offset + ((sdr.xyz * elbow) / (elbow - sdr.xyz));
float3 sdrInvTonemap = sdr.xyz / ((1.0f + kEpsilon) - sdr.xyz); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
float3 perChannel = float3(sdr.x > 0.5f ? hdrInvTonemap.x : sdrInvTonemap.x,
sdr.y > 0.5f ? hdrInvTonemap.y : sdrInvTonemap.y,
sdr.z > 0.5f ? hdrInvTonemap.z : sdrInvTonemap.z);
float3 hdr = lerp(perLuma, perChannel, kLumaChannelRatio);
/* Now convert into HDR10 */
float3 rec2020 = mul(k709to2020, hdr);
if(global.expandGamut > 0.0f)
{
rec2020 = mul( kExpanded709to2020, hdr);
}
float3 linearColour = rec2020 * (global.paperWhiteNits / kMaxNitsFor2084);
float3 hdr10 = LinearToST2084(linearColour);
return float4(hdr10, sdr.w);
}
float4 PSMain(PSInput input) : SV_TARGET
{
float4 sdr = input.color * t0.Sample(s0, input.texcoord);
return Hdr(sdr);
};
)

View File

@ -600,7 +600,11 @@ static const video_poke_interface_t dispmanx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void dispmanx_gfx_get_poke_interface(void *data,

View File

@ -956,7 +956,11 @@ static const video_poke_interface_t drm_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void drm_gfx_get_poke_interface(void *data,

View File

@ -1498,7 +1498,11 @@ static const video_poke_interface_t exynos_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void exynos_gfx_get_poke_interface(void *data,

View File

@ -386,6 +386,10 @@ static const video_poke_interface_t fpga_poke_interface = {
#ifdef HAVE_MENU
NULL,
#endif
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void fpga_gfx_get_poke_interface(void *data,

View File

@ -724,7 +724,11 @@ static const video_poke_interface_t gdi_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gdi_gfx_get_poke_interface(void *data,

View File

@ -4588,7 +4588,11 @@ static const video_poke_interface_t gl2_poke_interface = {
NULL,
gl2_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gl2_get_poke_interface(void *data,

View File

@ -1448,7 +1448,11 @@ static const video_poke_interface_t gl1_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gl1_gfx_get_poke_interface(void *data,

View File

@ -2287,6 +2287,10 @@ static const video_poke_interface_t gl_core_poke_interface = {
gl_core_get_current_shader,
NULL,
NULL,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gl_core_get_poke_interface(void *data,

View File

@ -1735,6 +1735,10 @@ static const video_poke_interface_t wiiu_poke_interface = {
wiiu_gfx_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void wiiu_gfx_get_poke_interface(void *data,

View File

@ -1372,7 +1372,11 @@ static const video_poke_interface_t gx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gx_get_poke_interface(void *data,

View File

@ -399,19 +399,31 @@ static uint32_t metal_get_flags(void *data)
}
static const video_poke_interface_t metal_poke_interface = {
.get_flags = metal_get_flags,
.load_texture = metal_load_texture,
.unload_texture = metal_unload_texture,
.set_video_mode = metal_set_video_mode,
.get_refresh_rate = metal_get_refresh_rate,
.set_filtering = metal_set_filtering,
.set_aspect_ratio = metal_set_aspect_ratio,
.apply_state_changes = metal_apply_state_changes,
.set_texture_frame = metal_set_texture_frame,
.set_texture_enable = metal_set_texture_enable,
.set_osd_msg = font_driver_render_msg,
.show_mouse = metal_show_mouse,
.get_current_shader = metal_get_current_shader,
metal_get_flags,
metal_load_texture,
metal_unload_texture,
metal_set_video_mode,
metal_get_refresh_rate,
metal_set_filtering,
NULL, /* get_video_output_size */
NULL, /* get_video_output_prev */
NULL, /* get_video_output_next */
NULL, /* get_current_framebuffer */
NULL, /* get_proc_address */
metal_set_aspect_ratio,
metal_apply_state_changes,
metal_set_texture_frame,
metal_set_texture_enable,
font_driver_render_msg,
metal_show_mouse,
NULL, /* grab_mouse_toggle */
metal_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void metal_get_poke_interface(void *data,

View File

@ -1123,7 +1123,11 @@ static const video_poke_interface_t omap_gfx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void omap_gfx_get_poke_interface(void *data,

View File

@ -465,7 +465,11 @@ static const video_poke_interface_t ps2_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
ps2_get_hw_render_interface /* get_hw_render_interface */
ps2_get_hw_render_interface, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void ps2_gfx_get_poke_interface(void *data,

View File

@ -802,7 +802,11 @@ static const video_poke_interface_t psp_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void psp_get_poke_interface(void *data,

View File

@ -720,7 +720,11 @@ static const video_poke_interface_t rsx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void rsx_get_poke_interface(void* data,

View File

@ -1106,7 +1106,11 @@ static const video_poke_interface_t sdl_dingux_poke_interface = {
NULL, /* sdl_grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sdl_dingux_get_poke_interface(void *data, const video_poke_interface_t **iface)

View File

@ -547,7 +547,11 @@ static const video_poke_interface_t sdl_poke_interface = {
sdl_grab_mouse_toggle,
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sdl_get_poke_interface(void *data, const video_poke_interface_t **iface)

View File

@ -1393,7 +1393,11 @@ static const video_poke_interface_t sdl_rs90_poke_interface = {
NULL, /* sdl_grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sdl_rs90_get_poke_interface(void *data, const video_poke_interface_t **iface)

View File

@ -551,6 +551,10 @@ static const video_poke_interface_t sixel_poke_interface = {
NULL,
NULL,
NULL,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sixel_gfx_get_poke_interface(void *data,

View File

@ -951,7 +951,11 @@ static const video_poke_interface_t sunxi_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sunxi_gfx_get_poke_interface(void *data,

View File

@ -397,6 +397,10 @@ static const video_poke_interface_t switch_poke_interface = {
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void switch_get_poke_interface(void *data,

View File

@ -682,6 +682,10 @@ static const video_poke_interface_t switch_poke_interface = {
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void switch_get_poke_interface(void *data,

View File

@ -385,7 +385,11 @@ static const video_poke_interface_t vga_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void vga_gfx_get_poke_interface(void *data,

View File

@ -824,7 +824,11 @@ static const video_poke_interface_t vita_poke_interface = {
NULL,
NULL,
vita_get_current_sw_framebuffer,
NULL
NULL,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void vita2d_gfx_get_poke_interface(void *data,

View File

@ -2638,6 +2638,10 @@ static const video_poke_interface_t vulkan_poke_interface = {
vulkan_get_current_shader,
vulkan_get_current_sw_framebuffer,
vulkan_get_hw_render_interface,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void vulkan_get_poke_interface(void *data,

View File

@ -366,6 +366,34 @@ static bool video_thread_handle_packet(
/* Never reply on no command. Possible deadlock if
* thread sends command right after frame update. */
break;
case CMD_POKE_SET_HDR_MAX_NITS:
if (thr->poke && thr->poke->set_hdr_max_nits)
thr->poke->set_hdr_max_nits(thr->driver_data,
pkt.data.hdr.max_nits);
video_thread_reply(thr, &pkt);
break;
case CMD_POKE_SET_HDR_PAPER_WHITE_NITS:
if (thr->poke && thr->poke->set_hdr_paper_white_nits)
thr->poke->set_hdr_paper_white_nits(thr->driver_data,
pkt.data.hdr.paper_white_nits);
video_thread_reply(thr, &pkt);
break;
case CMD_POKE_SET_HDR_CONTRAST:
if (thr->poke && thr->poke->set_hdr_contrast)
thr->poke->set_hdr_contrast(thr->driver_data,
pkt.data.hdr.contrast);
video_thread_reply(thr, &pkt);
break;
case CMD_POKE_SET_HDR_EXPAND_GAMUT:
if (thr->poke && thr->poke->set_hdr_expand_gamut)
thr->poke->set_hdr_expand_gamut(thr->driver_data,
pkt.data.hdr.expand_gamut);
video_thread_reply(thr, &pkt);
break;
default:
video_thread_reply(thr, &pkt);
break;
@ -931,6 +959,58 @@ static void thread_set_filtering(void *data, unsigned idx, bool smooth, bool ctx
video_thread_send_and_wait_user_to_thread(thr, &pkt);
}
static void thread_set_hdr_max_nits(void *data, float max_nits)
{
thread_packet_t pkt;
thread_video_t *thr = (thread_video_t*)data;
if (!thr)
return;
pkt.type = CMD_POKE_SET_HDR_MAX_NITS;
pkt.data.hdr.max_nits = max_nits;
video_thread_send_and_wait_user_to_thread(thr, &pkt);
}
static void thread_set_hdr_paper_white_nits(void *data, float paper_white_nits)
{
thread_packet_t pkt;
thread_video_t *thr = (thread_video_t*)data;
if (!thr)
return;
pkt.type = CMD_POKE_SET_HDR_PAPER_WHITE_NITS;
pkt.data.hdr.paper_white_nits = paper_white_nits;
video_thread_send_and_wait_user_to_thread(thr, &pkt);
}
static void thread_set_hdr_contrast(void *data, float contrast)
{
thread_packet_t pkt;
thread_video_t *thr = (thread_video_t*)data;
if (!thr)
return;
pkt.type = CMD_POKE_SET_HDR_CONTRAST;
pkt.data.hdr.contrast = contrast;
video_thread_send_and_wait_user_to_thread(thr, &pkt);
}
static void thread_set_hdr_expand_gamut(void *data, bool expand_gamut)
{
thread_packet_t pkt;
thread_video_t *thr = (thread_video_t*)data;
if (!thr)
return;
pkt.type = CMD_POKE_SET_HDR_EXPAND_GAMUT;
pkt.data.hdr.expand_gamut = expand_gamut;
video_thread_send_and_wait_user_to_thread(thr, &pkt);
}
static void thread_get_video_output_size(void *data,
unsigned *width, unsigned *height)
{
@ -1132,7 +1212,11 @@ static const video_poke_interface_t thread_poke = {
thread_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
thread_set_hdr_max_nits,
thread_set_hdr_paper_white_nits,
thread_set_hdr_contrast,
thread_set_hdr_expand_gamut
};
static void video_thread_get_poke_interface(

View File

@ -57,6 +57,11 @@ enum thread_cmd
CMD_POKE_SHOW_MOUSE,
CMD_POKE_GRAB_MOUSE_TOGGLE,
CMD_POKE_SET_HDR_MAX_NITS,
CMD_POKE_SET_HDR_PAPER_WHITE_NITS,
CMD_POKE_SET_HDR_CONTRAST,
CMD_POKE_SET_HDR_EXPAND_GAMUT,
CMD_DUMMY = INT_MAX
};
@ -150,6 +155,14 @@ struct thread_packet
bool is_threaded;
enum font_driver_render_api api;
} font_init;
struct
{
float max_nits;
float paper_white_nits;
float contrast;
bool expand_gamut;
} hdr;
} data;
enum thread_cmd type;
};

View File

@ -1072,6 +1072,10 @@ MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_VIDEO_SCALING_SETTINGS_LIST,
"deferred_video_scaling_settings_list"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_VIDEO_HDR_SETTINGS_LIST,
"deferred_video_hdr_settings_list"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_VIDEO_SYNCHRONIZATION_SETTINGS_LIST,
"deferred_video_synchronization_settings_list"
@ -3356,6 +3360,10 @@ MSG_HASH(
MENU_ENUM_LABEL_VIDEO_SCALING_SETTINGS,
"video_scaling_settings"
)
MSG_HASH(
MENU_ENUM_LABEL_VIDEO_HDR_SETTINGS,
"video_hdr_settings"
)
MSG_HASH(
MENU_ENUM_LABEL_VIDEO_SYNCHRONIZATION_SETTINGS,
"video_synchronization_settings"

View File

@ -1316,6 +1316,36 @@ int msg_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
"Resolution of 0 uses the \n"
"resolution of the environment.\n");
break;
case MENU_ENUM_LABEL_VIDEO_HDR_ENABLE:
snprintf(s, len,
"Enable HDR.\n"
" \n"
"If supported this enables hdr \n");
break;
case MENU_ENUM_LABEL_VIDEO_HDR_MAX_NITS:
snprintf(s, len,
"Max Nits\n"
" \n"
"Set the maximum no. nits the display can reproduce\n");
break;
case MENU_ENUM_LABEL_VIDEO_HDR_PAPER_WHITE_NITS:
snprintf(s, len,
"Paper White Nits\n"
" \n"
"Set the no. nits at which paper white should be\n");
break;
case MENU_ENUM_LABEL_VIDEO_HDR_CONTRAST:
snprintf(s, len,
"Contrast\n"
" \n"
"The constrast setting for HDR\n");
break;
case MENU_ENUM_LABEL_VIDEO_HDR_EXPAND_GAMUT:
snprintf(s, len,
"Expand Gamut\n"
" \n"
"Once converted to linear space should we use an expanded gamut to get to HDR10\n");
break;
case MENU_ENUM_LABEL_FASTFORWARD_RATIO:
snprintf(s, len,
"Fastforward ratio.\n"

View File

@ -1304,6 +1304,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_SCALING_SETTINGS,
"Change video scaling settings."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_SETTINGS,
"HDR"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_HDR_SETTINGS,
"Change video hdr settings."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_SYNCHRONIZATION_SETTINGS,
"Synchronization"
@ -1748,6 +1756,49 @@ MSG_HASH(
"Cut off a few pixels around the edges of the image customarily left blank by developers which sometimes also contain garbage pixels."
)
/* Settings > Video > HDR */
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_ENABLE,
"Enable HDR"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_HDR_ENABLE,
"Enable HDR if the display supports it"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_MAX_NITS,
"Max Nits"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_HDR_MAX_NITS,
""
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_PAPER_WHITE_NITS,
"Paper White Nits"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_HDR_PAPER_WHITE_NITS,
""
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_CONTRAST,
"Contrast"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_HDR_CONTRAST,
""
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_EXPAND_GAMUT,
"Expand Gamut"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_HDR_EXPAND_GAMUT,
""
)
/* Settings > Video > Synchronization */
MSG_HASH(

View File

@ -167,6 +167,7 @@ GENERIC_DEFERRED_PUSH(deferred_push_video_windowed_mode_settings_list, DISPLA
GENERIC_DEFERRED_PUSH(deferred_push_video_synchronization_settings_list, DISPLAYLIST_VIDEO_SYNCHRONIZATION_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_video_output_settings_list, DISPLAYLIST_VIDEO_OUTPUT_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_video_scaling_settings_list, DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_video_hdr_settings_list, DISPLAYLIST_VIDEO_HDR_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_crt_switchres_settings_list, DISPLAYLIST_CRT_SWITCHRES_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_configuration_settings_list, DISPLAYLIST_CONFIGURATION_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_saving_settings_list, DISPLAYLIST_SAVING_SETTINGS_LIST)
@ -766,6 +767,7 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
{MENU_ENUM_LABEL_DEFERRED_VIDEO_SYNCHRONIZATION_SETTINGS_LIST, deferred_push_video_synchronization_settings_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_OUTPUT_SETTINGS_LIST, deferred_push_video_output_settings_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_SCALING_SETTINGS_LIST, deferred_push_video_scaling_settings_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_HDR_SETTINGS_LIST, deferred_push_video_hdr_settings_list},
{MENU_ENUM_LABEL_DEFERRED_CRT_SWITCHRES_SETTINGS_LIST, deferred_push_crt_switchres_settings_list},
{MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST, deferred_push_audio_settings_list},
{MENU_ENUM_LABEL_DEFERRED_AUDIO_SYNCHRONIZATION_SETTINGS_LIST, deferred_push_audio_synchronization_settings_list},
@ -1209,6 +1211,9 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
case MENU_ENUM_LABEL_DEFERRED_VIDEO_OUTPUT_SETTINGS_LIST:
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_video_output_settings_list);
break;
case MENU_ENUM_LABEL_DEFERRED_VIDEO_HDR_SETTINGS_LIST:
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_video_hdr_settings_list);
break;
case MENU_ENUM_LABEL_DEFERRED_VIDEO_SCALING_SETTINGS_LIST:
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_video_scaling_settings_list);
break;

View File

@ -330,6 +330,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
return MENU_ENUM_LABEL_DEFERRED_VIDEO_WINDOWED_MODE_SETTINGS_LIST;
case ACTION_OK_DL_VIDEO_SCALING_SETTINGS_LIST:
return MENU_ENUM_LABEL_DEFERRED_VIDEO_SCALING_SETTINGS_LIST;
case ACTION_OK_DL_VIDEO_HDR_SETTINGS_LIST:
return MENU_ENUM_LABEL_DEFERRED_VIDEO_HDR_SETTINGS_LIST;
case ACTION_OK_DL_VIDEO_OUTPUT_SETTINGS_LIST:
return MENU_ENUM_LABEL_DEFERRED_VIDEO_OUTPUT_SETTINGS_LIST;
case ACTION_OK_DL_CRT_SWITCHRES_SETTINGS_LIST:
@ -1458,6 +1460,7 @@ int generic_action_ok_displaylist_push(const char *path,
case ACTION_OK_DL_CORE_SETTINGS_LIST:
case ACTION_OK_DL_CORE_INFORMATION_LIST:
case ACTION_OK_DL_VIDEO_SETTINGS_LIST:
case ACTION_OK_DL_VIDEO_HDR_SETTINGS_LIST:
case ACTION_OK_DL_VIDEO_SYNCHRONIZATION_SETTINGS_LIST:
case ACTION_OK_DL_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST:
case ACTION_OK_DL_VIDEO_WINDOWED_MODE_SETTINGS_LIST:
@ -5609,6 +5612,7 @@ DEFAULT_ACTION_OK_FUNC(action_ok_push_video_fullscreen_mode_settings_list, ACTIO
DEFAULT_ACTION_OK_FUNC(action_ok_push_video_synchronization_settings_list, ACTION_OK_DL_VIDEO_SYNCHRONIZATION_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_push_video_windowed_mode_settings_list, ACTION_OK_DL_VIDEO_WINDOWED_MODE_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_push_video_scaling_settings_list, ACTION_OK_DL_VIDEO_SCALING_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_push_video_hdr_settings_list, ACTION_OK_DL_VIDEO_HDR_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_push_video_output_settings_list, ACTION_OK_DL_VIDEO_OUTPUT_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_push_configuration_settings_list, ACTION_OK_DL_CONFIGURATION_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_push_core_settings_list, ACTION_OK_DL_CORE_SETTINGS_LIST)
@ -7688,6 +7692,7 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_VIDEO_FULLSCREEN_MODE_SETTINGS, action_ok_push_video_fullscreen_mode_settings_list},
{MENU_ENUM_LABEL_VIDEO_WINDOWED_MODE_SETTINGS, action_ok_push_video_windowed_mode_settings_list},
{MENU_ENUM_LABEL_VIDEO_SCALING_SETTINGS, action_ok_push_video_scaling_settings_list},
{MENU_ENUM_LABEL_VIDEO_HDR_SETTINGS, action_ok_push_video_hdr_settings_list},
{MENU_ENUM_LABEL_VIDEO_OUTPUT_SETTINGS, action_ok_push_video_output_settings_list},
{MENU_ENUM_LABEL_CRT_SWITCHRES_SETTINGS, action_ok_push_crt_switchres_settings_list},
{MENU_ENUM_LABEL_AUDIO_SETTINGS, action_ok_push_audio_settings_list},

View File

@ -203,6 +203,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_synchronization_settings_list,
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_fullscreen_mode_settings_list, MENU_ENUM_SUBLABEL_VIDEO_FULLSCREEN_MODE_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_windowed_mode_settings_list, MENU_ENUM_SUBLABEL_VIDEO_WINDOWED_MODE_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_scaling_settings_list, MENU_ENUM_SUBLABEL_VIDEO_SCALING_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_hdr_settings_list, MENU_ENUM_SUBLABEL_VIDEO_HDR_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_output_settings_list, MENU_ENUM_SUBLABEL_VIDEO_OUTPUT_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_crt_switchres_settings_list, MENU_ENUM_SUBLABEL_CRT_SWITCHRES_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_suspend_screensaver_enable, MENU_ENUM_SUBLABEL_SUSPEND_SCREENSAVER_ENABLE)
@ -3878,6 +3879,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_VIDEO_SCALING_SETTINGS:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scaling_settings_list);
break;
case MENU_ENUM_LABEL_VIDEO_HDR_SETTINGS:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_hdr_settings_list);
break;
case MENU_ENUM_LABEL_VIDEO_OUTPUT_SETTINGS:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_output_settings_list);
break;

View File

@ -589,6 +589,7 @@ DEFAULT_TITLE_MACRO(action_get_core_settings_list, MENU_ENUM_LABEL_
DEFAULT_TITLE_MACRO(action_get_video_settings_list, MENU_ENUM_LABEL_VALUE_VIDEO_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_video_fullscreen_mode_settings_list, MENU_ENUM_LABEL_VALUE_VIDEO_FULLSCREEN_MODE_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_video_windowed_mode_settings_list, MENU_ENUM_LABEL_VALUE_VIDEO_WINDOWED_MODE_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_video_hdr_settings_list, MENU_ENUM_LABEL_VALUE_VIDEO_HDR_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_video_scaling_settings_list, MENU_ENUM_LABEL_VALUE_VIDEO_SCALING_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_video_output_settings_list, MENU_ENUM_LABEL_VALUE_VIDEO_OUTPUT_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_video_synchronization_settings_list, MENU_ENUM_LABEL_VALUE_VIDEO_SYNCHRONIZATION_SETTINGS)
@ -1000,6 +1001,7 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_ONLINE_UPDATER, action_get_online_updater_list},
{MENU_ENUM_LABEL_DEFERRED_RECORDING_SETTINGS_LIST, action_get_recording_settings_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_SCALING_SETTINGS_LIST, action_get_video_scaling_settings_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_HDR_SETTINGS_LIST, action_get_video_hdr_settings_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_OUTPUT_SETTINGS_LIST, action_get_video_output_settings_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_SYNCHRONIZATION_SETTINGS_LIST, action_get_video_synchronization_settings_list},
{MENU_ENUM_LABEL_DEFERRED_INPUT_MENU_SETTINGS_LIST, action_get_input_menu_settings_list},

View File

@ -10383,6 +10383,7 @@ static void materialui_list_insert(
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_FULLSCREEN_MODE_SETTINGS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_WINDOWED_MODE_SETTINGS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SCALING_SETTINGS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_HDR_SETTINGS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_AUDIO_SETTINGS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_AUDIO_OUTPUT_SETTINGS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_AUDIO_RESAMPLER_SETTINGS)) ||

View File

@ -107,6 +107,7 @@ enum
ACTION_OK_DL_VIDEO_SYNCHRONIZATION_SETTINGS_LIST,
ACTION_OK_DL_VIDEO_OUTPUT_SETTINGS_LIST,
ACTION_OK_DL_VIDEO_SCALING_SETTINGS_LIST,
ACTION_OK_DL_VIDEO_HDR_SETTINGS_LIST,
ACTION_OK_DL_CRT_SWITCHRES_SETTINGS_LIST,
ACTION_OK_DL_AUDIO_SETTINGS_LIST,
ACTION_OK_DL_AUDIO_OUTPUT_SETTINGS_LIST,

View File

@ -6095,6 +6095,11 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_VIDEO_SCALING_SETTINGS,
PARSE_ACTION, false) == 0)
count++;
/* if (video_driver_supports_hdr()) */
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_HDR_SETTINGS,
PARSE_ACTION, false) == 0)
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_SYNCHRONIZATION_SETTINGS,
PARSE_ACTION, false) == 0)
@ -7917,6 +7922,37 @@ unsigned menu_displaylist_build_list(
count++;
}
break;
case DISPLAYLIST_VIDEO_HDR_SETTINGS_LIST:
{
if (video_driver_supports_hdr())
{
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_HDR_ENABLE,
PARSE_ONLY_BOOL, false) == 0)
count++;
/* if (settings->bools.video_hdr_enable) */
{
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_HDR_MAX_NITS,
PARSE_ONLY_FLOAT, false) == 0)
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_HDR_PAPER_WHITE_NITS,
PARSE_ONLY_FLOAT, false) == 0)
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_HDR_CONTRAST,
PARSE_ONLY_FLOAT, false) == 0)
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_VIDEO_HDR_EXPAND_GAMUT,
PARSE_ONLY_BOOL, false) == 0)
count++;
}
}
}
break;
case DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST:
{
#if defined(DINGUX)
@ -11637,6 +11673,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
case DISPLAYLIST_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST:
case DISPLAYLIST_VIDEO_WINDOWED_MODE_SETTINGS_LIST:
case DISPLAYLIST_VIDEO_OUTPUT_SETTINGS_LIST:
case DISPLAYLIST_VIDEO_HDR_SETTINGS_LIST:
case DISPLAYLIST_VIDEO_SYNCHRONIZATION_SETTINGS_LIST:
case DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST:
case DISPLAYLIST_OPTIONS_DISK:

View File

@ -156,6 +156,7 @@ enum menu_displaylist_ctl_state
DISPLAYLIST_VIDEO_SYNCHRONIZATION_SETTINGS_LIST,
DISPLAYLIST_VIDEO_OUTPUT_SETTINGS_LIST,
DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST,
DISPLAYLIST_VIDEO_HDR_SETTINGS_LIST,
DISPLAYLIST_CRT_SWITCHRES_SETTINGS_LIST,
DISPLAYLIST_VIDEO_SETTINGS_LIST,
DISPLAYLIST_CONFIGURATION_SETTINGS_LIST,

View File

@ -7711,6 +7711,51 @@ static void general_write_handler(rarch_setting_t *setting)
rarch_cmd = CMD_EVENT_REINIT;
}
break;
case MENU_ENUM_LABEL_VIDEO_HDR_ENABLE:
{
settings_t *settings = config_get_ptr();
settings->modified = true;
settings->bools.video_hdr_enable = *setting->value.target.boolean;
rarch_cmd = CMD_EVENT_REINIT;
}
break;
case MENU_ENUM_LABEL_VIDEO_HDR_MAX_NITS:
{
settings_t *settings = config_get_ptr();
settings->modified = true;
settings->floats.video_hdr_max_nits = roundf(*setting->value.target.fraction);
video_driver_set_hdr_max_nits(settings->floats.video_hdr_max_nits);
}
break;
case MENU_ENUM_LABEL_VIDEO_HDR_PAPER_WHITE_NITS:
{
settings_t *settings = config_get_ptr();
settings->modified = true;
settings->floats.video_hdr_paper_white_nits = roundf(*setting->value.target.fraction);
video_driver_set_hdr_paper_white_nits(settings->floats.video_hdr_paper_white_nits);
}
break;
case MENU_ENUM_LABEL_VIDEO_HDR_CONTRAST:
{
settings_t *settings = config_get_ptr();
settings->modified = true;
settings->floats.video_hdr_contrast = *setting->value.target.fraction;
video_driver_set_hdr_contrast(settings->floats.video_hdr_contrast);
}
break;
case MENU_ENUM_LABEL_VIDEO_HDR_EXPAND_GAMUT:
{
settings_t *settings = config_get_ptr();
settings->modified = true;
settings->bools.video_hdr_expand_gamut = *setting->value.target.boolean;;
video_driver_set_hdr_expand_gamut(settings->bools.video_hdr_expand_gamut);
}
break;
case MENU_ENUM_LABEL_INPUT_MAX_USERS:
command_event(CMD_EVENT_CONTROLLER_INIT, NULL);
break;
@ -11783,6 +11828,114 @@ static bool setting_append_list(
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ADVANCED);
END_SUB_GROUP(list, list_info, parent_group);
if(video_driver_supports_hdr())
{
START_SUB_GROUP(list, list_info, "HDR", &group_info, &subgroup_info, parent_group);
CONFIG_ACTION(
list, list_info,
MENU_ENUM_LABEL_VIDEO_HDR_SETTINGS,
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_SETTINGS,
&group_info,
&subgroup_info,
parent_group);
CONFIG_BOOL(
list, list_info,
&settings->bools.video_hdr_enable,
MENU_ENUM_LABEL_VIDEO_HDR_ENABLE,
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_ENABLE,
DEFAULT_VIDEO_HDR_ENABLE,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE);
(*list)[list_info->index - 1].action_ok = setting_bool_action_left_with_refresh;
(*list)[list_info->index - 1].action_left = setting_bool_action_left_with_refresh;
(*list)[list_info->index - 1].action_right = setting_bool_action_right_with_refresh;
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(
list,
list_info,
CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
/* if (settings->bools.video_hdr_enable) */
{
CONFIG_FLOAT(
list, list_info,
&settings->floats.video_hdr_max_nits,
MENU_ENUM_LABEL_VIDEO_HDR_MAX_NITS,
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_MAX_NITS,
DEFAULT_VIDEO_HDR_MAX_NITS,
"%.1fx",
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
menu_settings_list_current_add_range(list, list_info, 0.0, 10000.0, 10.0, true, true);
CONFIG_FLOAT(
list, list_info,
&settings->floats.video_hdr_paper_white_nits,
MENU_ENUM_LABEL_VIDEO_HDR_PAPER_WHITE_NITS,
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_PAPER_WHITE_NITS,
DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS,
"%.1fx",
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
menu_settings_list_current_add_range(list, list_info, 0.0, 10000.0, 10.0, true, true);
CONFIG_FLOAT(
list, list_info,
&settings->floats.video_hdr_contrast,
MENU_ENUM_LABEL_VIDEO_HDR_CONTRAST,
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_CONTRAST,
DEFAULT_VIDEO_HDR_CONTRAST,
"%.2fx",
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
menu_settings_list_current_add_range(list, list_info, 0.1, 3.0, 0.01, true, true);
CONFIG_BOOL(
list, list_info,
&settings->bools.video_hdr_expand_gamut,
MENU_ENUM_LABEL_VIDEO_HDR_EXPAND_GAMUT,
MENU_ENUM_LABEL_VALUE_VIDEO_HDR_EXPAND_GAMUT,
DEFAULT_VIDEO_HDR_EXPAND_GAMUT,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE);
(*list)[list_info->index - 1].action_ok = setting_bool_action_left_with_refresh;
(*list)[list_info->index - 1].action_left = setting_bool_action_left_with_refresh;
(*list)[list_info->index - 1].action_right = setting_bool_action_right_with_refresh;
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(
list,
list_info,
CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
}
END_SUB_GROUP(list, list_info, parent_group);
}
START_SUB_GROUP(
list,
list_info,

View File

@ -1097,6 +1097,12 @@ enum msg_hash_enums
MENU_LABEL(VIDEO_REFRESH_RATE_AUTO),
MENU_LABEL(VIDEO_REFRESH_RATE_POLLED),
MENU_LABEL(VIDEO_HDR_ENABLE),
MENU_LABEL(VIDEO_HDR_MAX_NITS),
MENU_LABEL(VIDEO_HDR_PAPER_WHITE_NITS),
MENU_LABEL(VIDEO_HDR_CONTRAST),
MENU_LABEL(VIDEO_HDR_EXPAND_GAMUT),
MENU_LABEL(VIDEO_LAYOUT_ENABLE),
MENU_LABEL(VIDEO_LAYOUT_PATH),
MENU_LABEL(VIDEO_LAYOUT_SELECTED_VIEW),
@ -1538,6 +1544,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_DEFERRED_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_VIDEO_OUTPUT_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_VIDEO_SYNCHRONIZATION_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_VIDEO_HDR_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_VIDEO_SCALING_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_CRT_SWITCHRES_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST,
@ -2345,6 +2352,7 @@ enum msg_hash_enums
MENU_LABEL(VIDEO_OUTPUT_SETTINGS),
MENU_LABEL(VIDEO_SYNCHRONIZATION_SETTINGS),
MENU_LABEL(VIDEO_SCALING_SETTINGS),
MENU_LABEL(VIDEO_HDR_SETTINGS),
MENU_LABEL(CRT_SWITCHRES_SETTINGS),
MENU_LABEL(AUDIO_SETTINGS),
MENU_LABEL(AUDIO_RESAMPLER_SETTINGS),

View File

@ -27718,6 +27718,38 @@ void video_driver_set_filtering(unsigned index, bool smooth, bool ctx_scaling)
index, smooth, ctx_scaling);
}
void video_driver_set_hdr_max_nits(float max_nits)
{
struct rarch_state *p_rarch = &rarch_st;
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_max_nits)
p_rarch->video_driver_poke->set_hdr_max_nits(p_rarch->video_driver_data,
max_nits);
}
void video_driver_set_hdr_paper_white_nits(float paper_white_nits)
{
struct rarch_state *p_rarch = &rarch_st;
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_paper_white_nits)
p_rarch->video_driver_poke->set_hdr_paper_white_nits(p_rarch->video_driver_data,
paper_white_nits);
}
void video_driver_set_hdr_contrast(float contrast)
{
struct rarch_state *p_rarch = &rarch_st;
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_contrast)
p_rarch->video_driver_poke->set_hdr_contrast(p_rarch->video_driver_data,
contrast);
}
void video_driver_set_hdr_expand_gamut(bool expand_gamut)
{
struct rarch_state *p_rarch = &rarch_st;
if (p_rarch->video_driver_poke && p_rarch->video_driver_poke->set_hdr_expand_gamut)
p_rarch->video_driver_poke->set_hdr_expand_gamut(p_rarch->video_driver_data,
expand_gamut);
}
void video_driver_cached_frame_set(const void *data, unsigned width,
unsigned height, size_t pitch)
{
@ -28068,6 +28100,32 @@ bool video_driver_supports_rgba(void)
return tmp;
}
void video_driver_set_hdr_support(void)
{
struct rarch_state *p_rarch = &rarch_st;
VIDEO_DRIVER_LOCK();
p_rarch->video_driver_hdr_support = true;
VIDEO_DRIVER_UNLOCK();
}
void video_driver_unset_hdr_support(void)
{
struct rarch_state *p_rarch = &rarch_st;
VIDEO_DRIVER_LOCK();
p_rarch->video_driver_hdr_support = false;
VIDEO_DRIVER_UNLOCK();
}
bool video_driver_supports_hdr(void)
{
bool tmp;
struct rarch_state *p_rarch = &rarch_st;
VIDEO_DRIVER_LOCK();
tmp = p_rarch->video_driver_hdr_support;
VIDEO_DRIVER_UNLOCK();
return tmp;
}
bool video_driver_get_next_video_out(void)
{
struct rarch_state *p_rarch = &rarch_st;
@ -29152,6 +29210,7 @@ void video_driver_build_info(video_frame_info_t *video_info)
video_info->height = p_rarch->video_driver_height;
video_info->use_rgba = p_rarch->video_driver_use_rgba;
video_info->hdr_enable = settings->bools.video_hdr_enable;
video_info->libretro_running = false;
video_info->msg_bgcolor_enable =
@ -30527,6 +30586,7 @@ static void retroarch_deinit_drivers(
video_display_server_destroy();
p_rarch->video_driver_use_rgba = false;
p_rarch->video_driver_hdr_support = false;
p_rarch->video_driver_active = false;
p_rarch->video_driver_cache_context = false;
p_rarch->video_driver_cache_context_ack = false;

View File

@ -283,6 +283,13 @@
# The angle is <value> * 90 degrees counter-clockwise.
# screen_orientation = 0
# HDR settings
# video_hdr_enable = false
# video_hdr_max_nits = 1000.0f
# video_hdr_paper_white_nits = 200.0f
# video_hdr_contrast = 1.0f
# video_hdr_expand_gamut = true
#### Audio
# Enable audio.

View File

@ -799,6 +799,7 @@ void recording_driver_update_streaming_url(void);
#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)
#if defined(_XBOX360)
#define DEFAULT_SHADER_TYPE RARCH_SHADER_HLSL
@ -1233,6 +1234,7 @@ typedef struct video_frame_info
bool fullscreen;
bool font_enable;
bool use_rgba;
bool hdr_support;
bool libretro_running;
bool xmb_shadows_enable;
bool battery_level_enable;
@ -1243,7 +1245,7 @@ typedef struct video_frame_info
bool menu_screensaver_active;
bool msg_bgcolor_enable;
bool crt_switch_hires_menu;
bool hdr_enable;
} video_frame_info_t;
typedef void (*update_window_title_cb)(void*);
@ -1452,6 +1454,12 @@ typedef struct video_poke_interface
struct retro_framebuffer *framebuffer);
bool (*get_hw_render_interface)(void *data,
const struct retro_hw_render_interface **iface);
/* hdr settings */
void (*set_hdr_max_nits)(void *data, float max_nits);
void (*set_hdr_paper_white_nits)(void *data, float paper_white_nits);
void (*set_hdr_contrast)(void *data, float contrast);
void (*set_hdr_expand_gamut)(void *data, bool expand_gamut);
} video_poke_interface_t;
/* msg is for showing a message on the screen
@ -1579,6 +1587,12 @@ void video_driver_unset_rgba(void);
bool video_driver_supports_rgba(void);
void video_driver_set_hdr_support(void);
void video_driver_unset_hdr_support(void);
bool video_driver_supports_hdr(void);
bool video_driver_get_next_video_out(void);
bool video_driver_get_prev_video_out(void);
@ -1655,6 +1669,11 @@ void * video_driver_read_frame_raw(unsigned *width,
void video_driver_set_filtering(unsigned index, bool smooth, bool ctx_scaling);
void video_driver_set_hdr_max_nits(float max_nits);
void video_driver_set_hdr_paper_white_nits(float paper_white_nits);
void video_driver_set_hdr_contrast(float contrast);
void video_driver_set_hdr_expand_gamut(bool expand_gamut);
const char *video_driver_get_ident(void);
void video_driver_set_viewport(unsigned width, unsigned height,

View File

@ -1844,6 +1844,11 @@ struct rarch_state
* TODO: Refactor this better. */
bool video_driver_use_rgba;
/* Graphics driver supports HDR displays
* Currently only D3D11/D3D12 supports HDR displays and
* whether we've enabled it */
bool video_driver_hdr_support;
/* If set during context deinit, the driver should keep
* graphics context alive to avoid having to reset all
* context state. */

View File

@ -173,7 +173,7 @@ vector<string> derived_types_list =
"IDXGIFactory1",
"IDXGIAdapter1",
"IDXGISurface1",
"IDXGISwapChain3",
"IDXGISwapChain4",
"IDXGIOutput",
"IDXGIDevice",
};

View File

@ -1235,6 +1235,9 @@ QWidget *VideoPage::widget()
CheckableSettingsGroup *savePosGroup = new CheckableSettingsGroup(MENU_ENUM_LABEL_VIDEO_WINDOW_CUSTOM_SIZE_ENABLE);
#endif
SettingsGroup *hdrGroup = new SettingsGroup("HDR");
QHBoxLayout *hdrLayout = new QHBoxLayout;
SettingsGroup *syncGroup = new SettingsGroup("Synchronization");
CheckableSettingsGroup *vSyncGroup = new CheckableSettingsGroup(MENU_ENUM_LABEL_VIDEO_VSYNC);
@ -1307,6 +1310,12 @@ QWidget *VideoPage::widget()
windowedGroup->add(MENU_ENUM_LABEL_VIDEO_WINDOW_SHOW_DECORATIONS);
hdrGroup->add(MENU_ENUM_LABEL_VIDEO_HDR_ENABLE);
hdrGroup->add(MENU_ENUM_LABEL_VIDEO_HDR_MAX_NITS);
hdrGroup->add(MENU_ENUM_LABEL_VIDEO_HDR_PAPER_WHITE_NITS);
hdrGroup->add(MENU_ENUM_LABEL_VIDEO_HDR_CONTRAST);
hdrGroup->add(MENU_ENUM_LABEL_VIDEO_HDR_EXPAND_GAMUT);
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_SWAP_INTERVAL);
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC);
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_FRAME_DELAY);
@ -1333,6 +1342,8 @@ QWidget *VideoPage::widget()
miscGroup->add(MENU_ENUM_LABEL_VIDEO_CTX_SCALING);
miscGroup->add(MENU_ENUM_LABEL_VIDEO_SHADER_DELAY);
hdrLayout->addWidget(hdrGroup);
syncMiscLayout->addWidget(syncGroup);
syncMiscLayout->addWidget(miscGroup);
@ -1348,6 +1359,7 @@ QWidget *VideoPage::widget()
layout->addLayout(outputScalingLayout);
layout->addLayout(modeLayout);
layout->addLayout(hdrLayout);
layout->addLayout(syncMiscLayout);
layout->addWidget(filterGroup);