Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.def.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@
#define DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS 200.0f

/* Should we expand the colour gamut when using hdr */
#define DEFAULT_VIDEO_HDR_EXPAND_GAMUT false
#define DEFAULT_VIDEO_HDR_EXPAND_GAMUT 0

/* Enable a basic HDR scanline implementation which is the main reason for using HDR in RetroArch */
#define DEFAULT_VIDEO_HDR_SCANLINES true
Expand Down
4 changes: 2 additions & 2 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -1920,7 +1920,6 @@ static struct config_bool_setting *populate_settings_bool(
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("video_hdr_scanlines", &settings->bools.video_hdr_scanlines, true, DEFAULT_VIDEO_HDR_SCANLINES, 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);
Expand Down Expand Up @@ -2560,7 +2559,8 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("video_record_scale_factor", &settings->uints.video_record_scale_factor, true, 1, false);
SETTING_UINT("video_stream_scale_factor", &settings->uints.video_stream_scale_factor, true, 1, false);

SETTING_UINT("video_hdr_subpixel_layout", &settings->uints.video_hdr_subpixel_layout, true, DEFAULT_VIDEO_HDR_SUBPIXEL_LAYOUT, false);
SETTING_UINT("video_hdr_subpixel_layout", &settings->uints.video_hdr_subpixel_layout, true, DEFAULT_VIDEO_HDR_SUBPIXEL_LAYOUT, false);
SETTING_UINT("video_hdr_expand_gamut", &settings->uints.video_hdr_expand_gamut, true, DEFAULT_VIDEO_HDR_EXPAND_GAMUT, false);
#ifdef HAVE_NETWORKING
SETTING_UINT("streaming_mode", &settings->uints.streaming_mode, true, STREAMING_MODE_TWITCH, false);
#endif
Expand Down
2 changes: 1 addition & 1 deletion configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ typedef struct settings
unsigned video_shader_subframes;
unsigned video_autoswitch_refresh_rate;
unsigned video_hdr_subpixel_layout;
unsigned video_hdr_expand_gamut;

unsigned quit_on_close_content;

Expand Down Expand Up @@ -689,7 +690,6 @@ typedef struct settings
bool video_wiiu_prefer_drc;
bool video_notch_write_over_enable;
bool video_hdr_enable;
bool video_hdr_expand_gamut;
bool video_hdr_scanlines;
bool video_use_metal_arg_buffers;

Expand Down
2 changes: 1 addition & 1 deletion gfx/common/dxgi_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ typedef struct ALIGN(16)
float max_nits; /* 1000.0f */
unsigned subpixel_layout; /* 0 */
float scanlines; /* 1.0f */
float expand_gamut; /* 0.0f */
unsigned expand_gamut; /* 0 */
float inverse_tonemap; /* 1.0f */
float hdr10; /* 1.0f */
} dxgi_hdr_uniform_t;
Expand Down
12 changes: 6 additions & 6 deletions gfx/drivers/d3d11.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ typedef struct
float enable_hdr;
float paper_white_nits;
float max_nits;
float expand_gamut;
unsigned expand_gamut;
float scanlines;
unsigned subpixel_layout;
float inverse_tonemap;
Expand Down Expand Up @@ -1635,13 +1635,13 @@ static void d3d11_set_hdr_paper_white_nits(void* data, float paper_white_nits)
}
}

static void d3d11_set_hdr_expand_gamut(void* data, bool expand_gamut)
static void d3d11_set_hdr_expand_gamut(void* data, unsigned 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.expand_gamut = expand_gamut ? 1.0f : 0.0f;
d3d11->hdr.ubo_values.expand_gamut = expand_gamut;

d3d11->context->lpVtbl->Map(
d3d11->context, (D3D11Resource)d3d11->hdr.ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
Expand All @@ -1653,7 +1653,7 @@ static void d3d11_set_hdr_expand_gamut(void* data, bool expand_gamut)
{
for (unsigned i = 0; i < d3d11->shader_preset->passes; i++)
{
d3d11->pass[i].expand_gamut = expand_gamut ? 1.0f : 0.0f;
d3d11->pass[i].expand_gamut = expand_gamut;
}
}
}
Expand Down Expand Up @@ -2703,7 +2703,7 @@ static void *d3d11_gfx_init(const video_info_t* video,
d3d11->hdr.ubo_values.subpixel_layout =
settings->uints.video_hdr_subpixel_layout;
d3d11->hdr.ubo_values.expand_gamut =
settings->bools.video_hdr_expand_gamut;
settings->uints.video_hdr_expand_gamut;
d3d11->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */
d3d11->hdr.ubo_values.hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */

Expand Down Expand Up @@ -3619,7 +3619,7 @@ static bool d3d11_gfx_frame(
d3d11->pass[i].max_nits = settings->floats.video_hdr_max_nits;
d3d11->pass[i].scanlines = settings->bools.video_hdr_scanlines ? 1.0f : 0.0f;
d3d11->pass[i].subpixel_layout = settings->uints.video_hdr_subpixel_layout;
d3d11->pass[i].expand_gamut = settings->bools.video_hdr_expand_gamut ? 1.0f : 0.0f;
d3d11->pass[i].expand_gamut = settings->uints.video_hdr_expand_gamut;
}
#endif /* HAVE_DXGI_HDR */

Expand Down
10 changes: 5 additions & 5 deletions gfx/drivers/d3d12.c
Original file line number Diff line number Diff line change
Expand Up @@ -1887,17 +1887,17 @@ static void d3d12_set_hdr_paper_white_nits(void* data, float paper_white_nits)
}
}

static void d3d12_set_hdr_expand_gamut(void* data, bool expand_gamut)
static void d3d12_set_hdr_expand_gamut(void* data, unsigned expand_gamut)
{
d3d12_video_t *d3d12 = (d3d12_video_t*)data;

d3d12->hdr.ubo_values.expand_gamut = expand_gamut ? 1.0f : 0.0f;
d3d12->hdr.ubo_values.expand_gamut = expand_gamut;

if(d3d12->shader_preset)
{
for (unsigned i = 0; i < d3d12->shader_preset->passes; i++)
{
d3d12->pass[i].expand_gamut = expand_gamut ? 1.0f : 0.0f;
d3d12->pass[i].expand_gamut = expand_gamut;
}
}
}
Expand Down Expand Up @@ -3505,7 +3505,7 @@ static void *d3d12_gfx_init(const video_info_t* video,

d3d12->hdr.ubo_values.subpixel_layout = settings->uints.video_hdr_subpixel_layout;
d3d12->hdr.ubo_values.scanlines = settings->bools.video_hdr_scanlines;
d3d12->hdr.ubo_values.expand_gamut = settings->bools.video_hdr_expand_gamut;
d3d12->hdr.ubo_values.expand_gamut = settings->uints.video_hdr_expand_gamut;

d3d12->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */
d3d12->hdr.ubo_values.hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */
Expand Down Expand Up @@ -4185,7 +4185,7 @@ static bool d3d12_gfx_frame(
d3d12->pass[i].max_nits = settings->floats.video_hdr_max_nits;
d3d12->pass[i].scanlines = settings->bools.video_hdr_scanlines ? 1.0f : 0.0f;
d3d12->pass[i].subpixel_layout = settings->uints.video_hdr_subpixel_layout;
d3d12->pass[i].expand_gamut = settings->bools.video_hdr_expand_gamut ? 1.0f : 0.0f;
d3d12->pass[i].expand_gamut = settings->uints.video_hdr_expand_gamut;
}
#endif /* HAVE_DXGI_HDR */

Expand Down
138 changes: 99 additions & 39 deletions gfx/drivers/d3d_shaders/hdr_sm5.hlsl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SRC(
float max_nits; /* 1000.0f */
uint subpixel_layout; /* 0 */
float scanlines; /* 1.0f */
float expand_gamut; /* 0.0f */
uint expand_gamut; /* 0 */
float inverse_tonemap;
float hdr10;
};
Expand Down Expand Up @@ -82,14 +82,14 @@ static const float k_crt_green_horizontal_convergence = 0.0f;
static const float k_crt_blue_horizontal_convergence = 0.0f;

static const float k_crt_red_scanline_min = 0.45f;
static const float k_crt_red_scanline_max = 0.70f;
static const float k_crt_red_scanline_attack = 0.30f;
static const float k_crt_red_scanline_max = 0.90f;
static const float k_crt_red_scanline_attack = 0.60f;
static const float k_crt_green_scanline_min = 0.45f;
static const float k_crt_green_scanline_max = 0.70f;
static const float k_crt_green_scanline_attack = 0.30f;
static const float k_crt_green_scanline_max = 0.90f;
static const float k_crt_green_scanline_attack = 0.60f;
static const float k_crt_blue_scanline_min = 0.45f;
static const float k_crt_blue_scanline_max = 0.70f;
static const float k_crt_blue_scanline_attack = 0.30f;
static const float k_crt_blue_scanline_max = 0.90f;
static const float k_crt_blue_scanline_attack = 0.60f;

static const float k_crt_red_beam_sharpness = 1.30f;
static const float k_crt_red_beam_attack = 1.00f;
Expand All @@ -111,6 +111,13 @@ static const float3x3 k709to2020 =
{ 0.0163916f, 0.0880132f, 0.8955950f }
};

static const float3x3 k2020toP3 =
{
{ 1.343578f, -0.282180f, -0.061399f },
{-0.065297f, 1.075788f, -0.010490f },
{ 0.002822f, -0.019598f, 1.016777f }
};

static const float4 kFallOffControlPoints = float4(0.0f, 0.0f, 0.0f, 1.0f);
static const float4 kAttackControlPoints = float4(0.0f, 1.0f, 1.0f, 1.0f);

Expand All @@ -122,9 +129,9 @@ static const float4x4 kCubicBezier = float4x4( 1.0f, 0.0f, 0.0f, 0.0f,
/* 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 }
{ 0.6274040, 0.3292820, 0.0433136 },
{ 0.0457456, 0.941777, 0.0124772 },
{-0.00121055, 0.0176041, 0.983607 }
};

float3 LinearToST2084(float3 normalizedLinearValue)
Expand All @@ -149,59 +156,110 @@ float3 InverseTonemap(const float3 sdr_linear, const float max_nits, const float
return sdr_linear * (tonemapped_val / input_val);
}

float4 Sample(float2 texcoord)
float3 Sample(float2 texcoord)
{
const float4 sdr = t0.Sample(s0, texcoord);

const float3 sdr_linear = pow(abs(sdr.rgb), 2.2f);
const float3 sdr_linear = pow(abs(sdr.rgb), 2.22f);

return float4(sdr_linear, sdr.a);
return sdr_linear;
}

float4 Sample(float4 colour, float2 texcoord)
{
const float4 sdr = colour * t0.Sample(s0, texcoord);

const float3 sdr_linear = pow(abs(sdr.rgb), 2.2f);
const float3 sdr_linear = pow(abs(sdr.rgb), 2.22f);

return float4(sdr_linear, sdr.a);
}

float4 HDR(const float4 sdr_linear)
float3 To2020(const float3 sdr_linear)
{
const float3 hdr_linear = InverseTonemap(sdr_linear.rgb, global.max_nits, global.paper_white_nits);
float3 rec2020;

if(global.expand_gamut == 0)
{
rec2020 = mul(k709to2020, sdr_linear);
}
else if(global.expand_gamut == 1)
{
rec2020 = mul( kExpanded709to2020, sdr_linear);
}
else if(global.expand_gamut == 2)
{
rec2020 = mul(k709to2020, sdr_linear);
rec2020 = mul(k2020toP3, rec2020);
}
else
{
rec2020 = sdr_linear;
}

return float4(hdr_linear, sdr_linear.a);
rec2020 = max(rec2020, float3(0.0f, 0.0f, 0.0f));

return rec2020;
}

float3 HDR10(const float3 hdr_linear)
float4 To2020(const float4 sdr_linear)
{
float3 rec2020 = mul(k709to2020, hdr_linear);
float3 rec2020;

if(global.expand_gamut > 0.0f)
if(global.expand_gamut == 0)
{
rec2020 = mul(k709to2020, sdr_linear.rgb);
}
else if(global.expand_gamut == 1)
{
rec2020 = mul( kExpanded709to2020, sdr_linear.rgb);
}
else if(global.expand_gamut == 2)
{
rec2020 = mul(k709to2020, sdr_linear.rgb);
rec2020 = mul(k2020toP3, rec2020);
}
else
{
rec2020 = mul( kExpanded709to2020, hdr_linear);
rec2020 = sdr_linear.rgb;
}

const float3 linearColour = rec2020 * (global.paper_white_nits / kMaxNitsFor2084);
rec2020 = max(rec2020, float3(0.0f, 0.0f, 0.0f));

return float4(rec2020, sdr_linear.a);
}

float3 HDR(const float3 sdr_linear)
{
return InverseTonemap(sdr_linear, global.max_nits, global.paper_white_nits);
}

float4 HDR(const float4 sdr_linear)
{
const float3 hdr_linear = InverseTonemap(sdr_linear.rgb, global.max_nits, global.paper_white_nits);

return float4(hdr_linear, sdr_linear.a);
}

float3 LinearToSignal(const float3 linear_colour)
{
// Always Encode to Gamma 2.4
return pow(max(linear_colour.rgb, float3(0.0f, 0.0f, 0.0f)), 1.0f / 2.4f);
}

float3 HDR10(const float3 hdr_linear)
{
const float3 pq_input = hdr_linear * (global.paper_white_nits / kMaxNitsFor2084);

const float3 hdr10 = LinearToST2084(max(linearColour, 0.0f));
const float3 hdr10 = LinearToST2084(max(pq_input, 0.0f));

return hdr10;
}

float4 HDR10(const float4 hdr_linear)
{
float3 rec2020 = mul(k709to2020, hdr_linear.rgb);

if(global.expand_gamut > 0.0f)
{
rec2020 = mul( kExpanded709to2020, hdr_linear.rgb);
}

const float3 linearColour = rec2020 * (global.paper_white_nits / kMaxNitsFor2084);
const float3 pq_input = hdr_linear.rgb * (global.paper_white_nits / kMaxNitsFor2084);

const float3 hdr10 = LinearToST2084(max(linearColour, 0.0f));
const float3 hdr10 = LinearToST2084(max(pq_input, 0.0f));

return float4(hdr10, hdr_linear.a);
}
Expand Down Expand Up @@ -248,13 +306,13 @@ float ScanlineColour(const uint channel,
const float2 tex_coord_0 = float2(source_tex_coord_x, source_tex_coord_y);
const float2 tex_coord_1 = float2(source_tex_coord_x + (1.0f / source_size.x), source_tex_coord_y);

const float hdr_channel_0 = HDR(Sample(tex_coord_0))[channel];
const float hdr_channel_1 = HDR(Sample(tex_coord_1))[channel];
const float hdr_channel_0 = LinearToSignal(HDR(To2020(Sample(tex_coord_0))))[channel];
const float hdr_channel_1 = LinearToSignal(HDR(To2020(Sample(tex_coord_1))))[channel];

const float horiz_interp = Bezier(narrowed_source_pixel_offset, BeamControlPoints(beam_attack, hdr_channel_0 > hdr_channel_1));
const float hdr_channel = lerp(hdr_channel_0, hdr_channel_1, horiz_interp);

const float physics_signal = pow(max(hdr_channel, 0.0f), 1.0f / 2.2f);
const float physics_signal = hdr_channel;

const float signal_strength = clamp(physics_signal, 0.0f, 2.5f);

Expand Down Expand Up @@ -368,7 +426,9 @@ float3 Scanlines(float2 texcoord)
scanline_colour = scanline_channel_0 * kColourMask[channel_0];
}

return HDR10(scanline_colour);
float3 linear_colour = pow(max(scanline_colour, float3(0.0f, 0.0f, 0.0f)), 2.4f);

return HDR10(linear_colour);
}

float4 PSMain(PSInput input) : SV_TARGET
Expand All @@ -381,16 +441,16 @@ float4 PSMain(PSInput input) : SV_TARGET
}
else
{
return HDR10(HDR(Sample(input.color, input.texcoord)));
return HDR10(HDR(To2020(Sample(input.color, input.texcoord))));
}
}
else if(global.inverse_tonemap > 0.0f)
{
return HDR(Sample(input.color, input.texcoord));
return HDR(To2020(Sample(input.color, input.texcoord)));
}
else if(global.hdr10 > 0.0f)
{
return HDR10(Sample(input.color, input.texcoord));
return HDR10(To2020(Sample(input.color, input.texcoord)));
}
else
{
Expand Down
Loading
Loading