mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 12:32:52 +00:00
Added rolling scan line simulation based on the shader subframe feature. This is implemented with a scrolling scissor rect rather than in the shader itself as this is more efficient although may not work for every shader pass - we may need an option to exclude certain passes. The implementation simply divides the screen up by the number of sub frames and then moves the scissor rect down over the screen over the number of sub frames. (#16282)
This commit is contained in:
parent
5452999b2a
commit
eef34e9461
@ -401,6 +401,11 @@
|
||||
*/
|
||||
#define DEFAULT_SHADER_SUBFRAMES 1
|
||||
|
||||
/* Divides implements basic rolling scanning of sub frames - does this simply by scrolling a
|
||||
* a scissor rect down the screen according to how many sub frames there are
|
||||
*/
|
||||
#define DEFAULT_SCAN_SUBFRAMES false
|
||||
|
||||
/* Inserts black frame(s) inbetween frames.
|
||||
* Useful for Higher Hz monitors (set to multiples of 60 Hz) who want to play 60 Hz
|
||||
* material with CRT-like motion clarity.
|
||||
|
@ -1809,6 +1809,8 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
/* Let implementation decide if automatic, or 1:1 PAR. */
|
||||
SETTING_BOOL("video_aspect_ratio_auto", &settings->bools.video_aspect_ratio_auto, true, DEFAULT_ASPECT_RATIO_AUTO, false);
|
||||
|
||||
SETTING_BOOL("video_scan_subframes", &settings->bools.video_scan_subframes, true, DEFAULT_SCAN_SUBFRAMES, false);
|
||||
|
||||
SETTING_BOOL("video_allow_rotate", &settings->bools.video_allow_rotate, true, DEFAULT_ALLOW_ROTATE, false);
|
||||
SETTING_BOOL("video_windowed_fullscreen", &settings->bools.video_windowed_fullscreen, true, DEFAULT_WINDOWED_FULLSCREEN, false);
|
||||
SETTING_BOOL("video_crop_overscan", &settings->bools.video_crop_overscan, true, DEFAULT_CROP_OVERSCAN, false);
|
||||
|
@ -611,6 +611,7 @@ typedef struct settings
|
||||
bool video_shader_watch_files;
|
||||
bool video_shader_remember_last_dir;
|
||||
bool video_shader_preset_save_reference_enable;
|
||||
bool video_scan_subframes;
|
||||
bool video_threaded;
|
||||
bool video_font_enable;
|
||||
bool video_disable_composition;
|
||||
|
@ -60,6 +60,8 @@
|
||||
#error "UWP does not support D3D10"
|
||||
#endif
|
||||
|
||||
#define D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
typedef struct
|
||||
{
|
||||
d3d10_texture_t texture;
|
||||
@ -2417,6 +2419,41 @@ static bool d3d10_gfx_frame(
|
||||
context->lpVtbl->RSSetViewports(context, 1,
|
||||
&d3d10->pass[i].viewport);
|
||||
|
||||
#ifdef D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !black_frame_insertion
|
||||
&& !nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(d3d10->flags & D3D10_ST_FLAG_MENU_ENABLE)))
|
||||
{
|
||||
D3D10_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = (unsigned int)(((float)d3d10->pass[i].viewport.Height / (float)video_info->shader_subframes)
|
||||
* (float)video_info->current_subframe);
|
||||
scissor_rect.right = d3d10->pass[i].viewport.Width ;
|
||||
scissor_rect.bottom = (unsigned int)(((float)d3d10->pass[i].viewport.Height / (float)video_info->shader_subframes)
|
||||
* (float)(video_info->current_subframe + 1));
|
||||
|
||||
d3d10->device->lpVtbl->RSSetScissorRects(d3d10->device, 1,
|
||||
&scissor_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D10_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = 0;
|
||||
scissor_rect.right = d3d10->pass[i].viewport.Width;
|
||||
scissor_rect.bottom = d3d10->pass[i].viewport.Height;
|
||||
|
||||
d3d10->device->lpVtbl->RSSetScissorRects(d3d10->device, 1,
|
||||
&scissor_rect);
|
||||
}
|
||||
#endif // D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
context->lpVtbl->Draw(context, 4, 0);
|
||||
texture = &d3d10->pass[i].rt;
|
||||
}
|
||||
@ -2448,6 +2485,29 @@ static bool d3d10_gfx_frame(
|
||||
d3d10->clearcolor);
|
||||
context->lpVtbl->RSSetViewports(context, 1, &d3d10->frame.viewport);
|
||||
|
||||
#ifdef D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !black_frame_insertion
|
||||
&& !nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(d3d10->flags & D3D10_ST_FLAG_MENU_ENABLE)))
|
||||
{
|
||||
D3D10_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = (unsigned int)(((float)video_height / (float)video_info->shader_subframes)
|
||||
* (float)video_info->current_subframe);
|
||||
scissor_rect.right = video_width ;
|
||||
scissor_rect.bottom = (unsigned int)(((float)video_height / (float)video_info->shader_subframes)
|
||||
* (float)(video_info->current_subframe + 1));
|
||||
|
||||
d3d10->device->lpVtbl->RSSetScissorRects(d3d10->device, 1,
|
||||
&scissor_rect);
|
||||
}
|
||||
else
|
||||
#endif // D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
{
|
||||
D3D10_RECT scissor_rect;
|
||||
|
||||
@ -2464,6 +2524,20 @@ static bool d3d10_gfx_frame(
|
||||
context->lpVtbl->OMSetBlendState(context, d3d10->blend_enable, NULL,
|
||||
D3D10_DEFAULT_SAMPLE_MASK);
|
||||
|
||||
#ifdef D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
{
|
||||
D3D10_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = 0;
|
||||
scissor_rect.right = video_width;
|
||||
scissor_rect.bottom = video_height;
|
||||
|
||||
d3d10->device->lpVtbl->RSSetScissorRects(d3d10->device, 1,
|
||||
&scissor_rect);
|
||||
}
|
||||
#endif // D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
if ( (d3d10->flags & D3D10_ST_FLAG_MENU_ENABLE)
|
||||
&& d3d10->menu.texture.handle)
|
||||
{
|
||||
@ -2622,8 +2696,13 @@ static bool d3d10_gfx_frame(
|
||||
&& (!(d3d10->flags & D3D10_ST_FLAG_FRAME_DUPE_LOCK)))
|
||||
{
|
||||
d3d10->flags |= D3D10_ST_FLAG_FRAME_DUPE_LOCK;
|
||||
|
||||
for (k = 1; k < video_info->shader_subframes; k++)
|
||||
{
|
||||
#ifdef D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
video_info->current_subframe = k;
|
||||
#endif // D3D10_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
if (d3d10->shader_preset)
|
||||
for (m = 0; m < d3d10->shader_preset->passes; m++)
|
||||
{
|
||||
|
@ -76,6 +76,8 @@ const GUID DECLSPEC_SELECTANY libretro_IID_IDXGIFactory5 = { 0x7632e1f5,0xee65,0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
/* Temporary workaround for d3d11 not being able to poll flags during init */
|
||||
static gfx_ctx_driver_t d3d11_fake_context;
|
||||
|
||||
@ -3025,7 +3027,23 @@ static bool d3d11_gfx_frame(
|
||||
context, width, height, pitch, d3d11->format, frame, &d3d11->frame.texture[0]);
|
||||
}
|
||||
|
||||
context->lpVtbl->RSSetState(context, d3d11->scissor_disabled);
|
||||
#ifdef D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !black_frame_insertion
|
||||
&& !nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(d3d11->flags & D3D11_ST_FLAG_MENU_ENABLE)))
|
||||
{
|
||||
context->lpVtbl->RSSetState(context, d3d11->scissor_enabled);
|
||||
}
|
||||
else
|
||||
#endif // D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
{
|
||||
context->lpVtbl->RSSetState(context, d3d11->scissor_disabled);
|
||||
}
|
||||
|
||||
d3d11->context->lpVtbl->OMSetBlendState(
|
||||
d3d11->context, d3d11->blend_disable,
|
||||
NULL, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
@ -3158,6 +3176,41 @@ static bool d3d11_gfx_frame(
|
||||
&d3d11->pass[i].rt.rt_view, NULL);
|
||||
context->lpVtbl->RSSetViewports(context, 1, &d3d11->pass[i].viewport);
|
||||
|
||||
#ifdef D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !black_frame_insertion
|
||||
&& !nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(d3d11->flags & D3D11_ST_FLAG_MENU_ENABLE)))
|
||||
{
|
||||
D3D11_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = (unsigned int)(((float)d3d11->pass[i].viewport.Height / (float)video_info->shader_subframes)
|
||||
* (float)video_info->current_subframe);
|
||||
scissor_rect.right = d3d11->pass[i].viewport.Width ;
|
||||
scissor_rect.bottom = (unsigned int)(((float)d3d11->pass[i].viewport.Height / (float)video_info->shader_subframes)
|
||||
* (float)(video_info->current_subframe + 1));
|
||||
|
||||
d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1,
|
||||
&scissor_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = 0;
|
||||
scissor_rect.right = d3d11->pass[i].viewport.Width;
|
||||
scissor_rect.bottom = d3d11->pass[i].viewport.Height;
|
||||
|
||||
d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1,
|
||||
&scissor_rect);
|
||||
}
|
||||
#endif // D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
if (i == d3d11->shader_preset->passes - 1)
|
||||
context->lpVtbl->Draw(context, 4, 0);
|
||||
else
|
||||
@ -3204,6 +3257,33 @@ static bool d3d11_gfx_frame(
|
||||
context->lpVtbl->VSSetConstantBuffers(context, 0, 1, &d3d11->frame.ubo);
|
||||
}
|
||||
|
||||
#ifdef D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !black_frame_insertion
|
||||
&& !nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(d3d11->flags & D3D11_ST_FLAG_MENU_ENABLE)))
|
||||
{
|
||||
D3D11_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = (unsigned int)(((float)video_height / (float)video_info->shader_subframes)
|
||||
* (float)video_info->current_subframe);
|
||||
scissor_rect.right = video_width ;
|
||||
scissor_rect.bottom = (unsigned int)(((float)video_height / (float)video_info->shader_subframes)
|
||||
* (float)(video_info->current_subframe + 1));
|
||||
|
||||
d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1,
|
||||
&scissor_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1, &d3d11->scissor);
|
||||
}
|
||||
#endif // D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
context->lpVtbl->Draw(context, 4, 0);
|
||||
context->lpVtbl->RSSetState(context, d3d11->scissor_enabled);
|
||||
d3d11->context->lpVtbl->RSSetScissorRects(d3d11->context, 1, &d3d11->scissor);
|
||||
@ -3458,6 +3538,10 @@ static bool d3d11_gfx_frame(
|
||||
d3d11->flags |= D3D11_ST_FLAG_FRAME_DUPE_LOCK;
|
||||
for (k = 1; k < video_info->shader_subframes; k++)
|
||||
{
|
||||
#ifdef D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
video_info->current_subframe = k;
|
||||
#endif // D3D11_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
if (d3d11->shader_preset)
|
||||
for (m = 0; m < d3d11->shader_preset->passes; m++)
|
||||
{
|
||||
|
@ -79,6 +79,8 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define D3D12_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
typedef struct
|
||||
{
|
||||
d3d12_texture_t texture;
|
||||
@ -3748,8 +3750,33 @@ static bool d3d12_gfx_frame(
|
||||
#endif
|
||||
cmd->lpVtbl->RSSetViewports(cmd, 1,
|
||||
&d3d12->pass[i].viewport);
|
||||
cmd->lpVtbl->RSSetScissorRects(cmd, 1,
|
||||
&d3d12->pass[i].scissorRect);
|
||||
|
||||
#ifdef D3D12_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !black_frame_insertion
|
||||
&& !nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(d3d12->flags & D3D12_ST_FLAG_MENU_ENABLE)))
|
||||
{
|
||||
D3D12_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = (unsigned int)(((float)d3d12->pass[i].viewport.Height / (float)video_info->shader_subframes)
|
||||
* (float)video_info->current_subframe);
|
||||
scissor_rect.right = d3d12->pass[i].viewport.Width;
|
||||
scissor_rect.bottom = (unsigned int)(((float)d3d12->pass[i].viewport.Height / (float)video_info->shader_subframes)
|
||||
* (float)(video_info->current_subframe + 1));
|
||||
|
||||
cmd->lpVtbl->RSSetScissorRects(cmd, 1, &scissor_rect);
|
||||
}
|
||||
else
|
||||
#endif // D3D12_ROLLING_SCANLINE_SIMULATION
|
||||
{
|
||||
cmd->lpVtbl->RSSetScissorRects(cmd, 1,
|
||||
&d3d12->pass[i].scissorRect);
|
||||
}
|
||||
|
||||
if (i == d3d12->shader_preset->passes - 1)
|
||||
start_vertex_location = 0;
|
||||
@ -3836,7 +3863,32 @@ static bool d3d12_gfx_frame(
|
||||
}
|
||||
|
||||
cmd->lpVtbl->RSSetViewports(cmd, 1, &d3d12->frame.viewport);
|
||||
cmd->lpVtbl->RSSetScissorRects(cmd, 1, &d3d12->frame.scissorRect);
|
||||
|
||||
#ifdef D3D12_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !black_frame_insertion
|
||||
&& !nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(d3d12->flags & D3D12_ST_FLAG_MENU_ENABLE)))
|
||||
{
|
||||
D3D12_RECT scissor_rect;
|
||||
|
||||
scissor_rect.left = 0;
|
||||
scissor_rect.top = (unsigned int)(((float)video_height / (float)video_info->shader_subframes)
|
||||
* (float)video_info->current_subframe);
|
||||
scissor_rect.right = video_width ;
|
||||
scissor_rect.bottom = (unsigned int)(((float)video_height / (float)video_info->shader_subframes)
|
||||
* (float)(video_info->current_subframe + 1));
|
||||
|
||||
cmd->lpVtbl->RSSetScissorRects(cmd, 1, &scissor_rect);
|
||||
}
|
||||
else
|
||||
#endif // D3D12_ROLLING_SCANLINE_SIMULATION
|
||||
{
|
||||
cmd->lpVtbl->RSSetScissorRects(cmd, 1, &d3d12->frame.scissorRect);
|
||||
}
|
||||
|
||||
cmd->lpVtbl->DrawInstanced(cmd, 4, 1, 0, 0);
|
||||
|
||||
@ -4046,6 +4098,10 @@ static bool d3d12_gfx_frame(
|
||||
d3d12->flags |= D3D12_ST_FLAG_FRAME_DUPE_LOCK;
|
||||
for (k = 1; k < video_info->shader_subframes; k++)
|
||||
{
|
||||
#ifdef D3D12_ROLLING_SCANLINE_SIMULATION
|
||||
video_info->current_subframe = k;
|
||||
#endif // D3D12_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
if (d3d12->shader_preset)
|
||||
for (m = 0; m < d3d12->shader_preset->passes; m++)
|
||||
{
|
||||
|
@ -2604,6 +2604,25 @@ static bool gl3_frame(void *data, const void *frame,
|
||||
gl->filter_chain, 1);
|
||||
}
|
||||
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& !video_info->black_frame_insertion
|
||||
&& !video_info->input_driver_nonblock_state
|
||||
&& !video_info->runloop_is_slowmotion
|
||||
&& !video_info->runloop_is_paused
|
||||
&& (!(gl->flags & GL3_FLAG_MENU_TEXTURE_ENABLE)))
|
||||
{
|
||||
gl3_filter_chain_set_simulate_scanline(
|
||||
gl->filter_chain, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl3_filter_chain_set_simulate_scanline(
|
||||
gl->filter_chain, false);
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
gl3_filter_chain_set_input_texture(gl->filter_chain, &texture);
|
||||
gl3_filter_chain_build_offscreen_passes(gl->filter_chain,
|
||||
&gl->filter_chain_vp);
|
||||
|
@ -4232,6 +4232,28 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
vulkan_filter_chain_set_current_shader_subframe(
|
||||
(vulkan_filter_chain_t*)vk->filter_chain, 1);
|
||||
}
|
||||
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
if ( (video_info->shader_subframes > 1)
|
||||
&& (video_info->scan_subframes)
|
||||
&& (backbuffer->image != VK_NULL_HANDLE)
|
||||
&& !black_frame_insertion
|
||||
&& !input_driver_nonblock_state
|
||||
&& !runloop_is_slowmotion
|
||||
&& !runloop_is_paused
|
||||
&& (!(vk->flags & VK_FLAG_MENU_ENABLE))
|
||||
&& !(vk->context->swap_interval > 1))
|
||||
{
|
||||
vulkan_filter_chain_set_simulate_scanline(
|
||||
(vulkan_filter_chain_t*)vk->filter_chain, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
vulkan_filter_chain_set_simulate_scanline(
|
||||
(vulkan_filter_chain_t*)vk->filter_chain, false);
|
||||
}
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
#ifdef HAVE_REWIND
|
||||
vulkan_filter_chain_set_frame_direction(
|
||||
(vulkan_filter_chain_t*)vk->filter_chain,
|
||||
|
@ -935,6 +935,13 @@ public:
|
||||
current_subframe = cur_subframe;
|
||||
}
|
||||
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
void set_simulate_scanline(bool simulate)
|
||||
{
|
||||
simulate_scanline = simulate;
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
void set_name(const char *name)
|
||||
{
|
||||
pass_name = name;
|
||||
@ -1036,6 +1043,9 @@ private:
|
||||
unsigned pass_number = 0;
|
||||
uint32_t total_subframes = 1;
|
||||
uint32_t current_subframe = 1;
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
bool simulate_scanline = false;
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
size_t ubo_offset = 0;
|
||||
std::string pass_name;
|
||||
@ -1790,12 +1800,55 @@ void Pass::build_commands(
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
if (simulate_scanline)
|
||||
{
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
if (final_pass)
|
||||
{
|
||||
glViewport(current_viewport.x, current_viewport.y,
|
||||
current_viewport.width, current_viewport.height);
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
if (simulate_scanline)
|
||||
{
|
||||
glScissor( current_viewport.x,
|
||||
int32_t((float(current_viewport.height) / float(total_subframes))
|
||||
* float(current_subframe - 1)),
|
||||
current_viewport.width,
|
||||
uint32_t(float(current_viewport.height) / float(total_subframes))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
glScissor( current_viewport.x, current_viewport.y,
|
||||
current_viewport.width, current_viewport.height);
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
}
|
||||
else
|
||||
{
|
||||
glViewport(0, 0, size.width, size.height);
|
||||
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
if (simulate_scanline)
|
||||
{
|
||||
glScissor( 0,
|
||||
int32_t((float(size.height) / float(total_subframes))
|
||||
* float(current_subframe - 1)),
|
||||
size.width,
|
||||
uint32_t(float(size.height) / float(total_subframes))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
glScissor(0, 0, size.width, size.height);
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
}
|
||||
|
||||
#if !defined(HAVE_OPENGLES)
|
||||
if (framebuffer && framebuffer->get_format() == GL_SRGB8_ALPHA8)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
@ -1818,6 +1871,12 @@ void Pass::build_commands(
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
if (simulate_scanline)
|
||||
{
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
#if !defined(HAVE_OPENGLES)
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
@ -1870,6 +1929,9 @@ public:
|
||||
void set_rotation(uint32_t rot);
|
||||
void set_shader_subframes(uint32_t tot_subframes);
|
||||
void set_current_shader_subframe(uint32_t cur_subframe);
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
void set_simulate_scanline(bool simulate);
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
void set_pass_name(unsigned pass, const char *name);
|
||||
|
||||
void add_static_texture(std::unique_ptr<gl3_shader::StaticTexture> texture);
|
||||
@ -2373,6 +2435,15 @@ void gl3_filter_chain::set_current_shader_subframe(uint32_t cur_subframe)
|
||||
passes[i]->set_current_shader_subframe(cur_subframe);
|
||||
}
|
||||
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
void gl3_filter_chain::set_simulate_scanline(bool simulate_scanline)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < passes.size(); i++)
|
||||
passes[i]->set_simulate_scanline(simulate_scanline);
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
void gl3_filter_chain::set_pass_name(unsigned pass, const char *name)
|
||||
{
|
||||
passes[pass]->set_name(name);
|
||||
@ -2807,6 +2878,15 @@ void gl3_filter_chain_set_current_shader_subframe(
|
||||
chain->set_current_shader_subframe(cur_subframe);
|
||||
}
|
||||
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
void gl3_filter_chain_set_simulate_scanline(
|
||||
gl3_filter_chain_t *chain,
|
||||
bool simulate_scanline)
|
||||
{
|
||||
chain->set_simulate_scanline(simulate_scanline);
|
||||
}
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
void gl3_filter_chain_set_frame_count_period(
|
||||
gl3_filter_chain_t *chain,
|
||||
unsigned pass,
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
#include "glslang_util.h"
|
||||
|
||||
#define GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct gl3_filter_chain gl3_filter_chain_t;
|
||||
@ -125,6 +127,12 @@ void gl3_filter_chain_set_current_shader_subframe(
|
||||
gl3_filter_chain_t *chain,
|
||||
uint32_t cur_subframe);
|
||||
|
||||
#ifdef GL3_ROLLING_SCANLINE_SIMULATION
|
||||
void gl3_filter_chain_set_simulate_scanline(
|
||||
gl3_filter_chain_t *chain,
|
||||
bool simulate_scanline);
|
||||
#endif // GL3_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
void gl3_filter_chain_set_pass_name(
|
||||
gl3_filter_chain_t *chain,
|
||||
unsigned pass,
|
||||
|
@ -512,6 +512,9 @@ class Pass
|
||||
cache(cache),
|
||||
num_sync_indices(num_sync_indices),
|
||||
final_pass(final_pass)
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
,simulate_scanline(false)
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
{}
|
||||
|
||||
~Pass();
|
||||
@ -548,6 +551,9 @@ class Pass
|
||||
void set_frame_count_period(unsigned p) { frame_count_period = p; }
|
||||
void set_shader_subframes(uint32_t ts) { total_subframes = ts; }
|
||||
void set_current_shader_subframe(uint32_t cs) { current_subframe = cs; }
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
void set_simulate_scanline(bool simulate) { simulate_scanline = simulate; }
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
void set_frame_direction(int32_t dir) { frame_direction = dir; }
|
||||
void set_rotation(uint32_t rot) { rotation = rot; }
|
||||
void set_name(const char *name) { pass_name = name; }
|
||||
@ -581,6 +587,9 @@ class Pass
|
||||
unsigned num_sync_indices;
|
||||
unsigned sync_index;
|
||||
bool final_pass;
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
bool simulate_scanline;
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
Size2D get_output_size(const Size2D &original_size,
|
||||
const Size2D &max_source) const;
|
||||
@ -699,6 +708,9 @@ struct vulkan_filter_chain
|
||||
void set_frame_count_period(unsigned pass, unsigned period);
|
||||
void set_shader_subframes(uint32_t total_subframes);
|
||||
void set_current_shader_subframe(uint32_t current_subframe);
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
void set_simulate_scanline(bool simulate_scanline);
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
void set_frame_direction(int32_t direction);
|
||||
void set_rotation(uint32_t rot);
|
||||
void set_pass_name(unsigned pass, const char *name);
|
||||
@ -1707,6 +1719,15 @@ void vulkan_filter_chain::set_current_shader_subframe(uint32_t current_subframe)
|
||||
passes[i]->set_current_shader_subframe(current_subframe);
|
||||
}
|
||||
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
void vulkan_filter_chain::set_simulate_scanline(bool simulate_scanline)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < passes.size(); i++)
|
||||
passes[i]->set_simulate_scanline(simulate_scanline);
|
||||
}
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
void vulkan_filter_chain::set_frame_direction(int32_t direction)
|
||||
{
|
||||
unsigned i;
|
||||
@ -2758,18 +2779,39 @@ void Pass::build_commands(
|
||||
|
||||
if (final_pass)
|
||||
{
|
||||
const VkRect2D sci = {
|
||||
{
|
||||
int32_t(current_viewport.x),
|
||||
int32_t(current_viewport.y)
|
||||
},
|
||||
{
|
||||
uint32_t(current_viewport.width),
|
||||
uint32_t(current_viewport.height)
|
||||
},
|
||||
};
|
||||
vkCmdSetViewport(cmd, 0, 1, ¤t_viewport);
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
if (simulate_scanline)
|
||||
{
|
||||
const VkRect2D sci = {
|
||||
{
|
||||
int32_t(current_viewport.x),
|
||||
int32_t((current_viewport.height / float(total_subframes))
|
||||
* float(current_subframe - 1))
|
||||
},
|
||||
{
|
||||
uint32_t(current_viewport.width),
|
||||
uint32_t(current_viewport.height / float(total_subframes))
|
||||
},
|
||||
};
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
}
|
||||
else
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
{
|
||||
const VkRect2D sci = {
|
||||
{
|
||||
int32_t(current_viewport.x),
|
||||
int32_t(current_viewport.y)
|
||||
},
|
||||
{
|
||||
uint32_t(current_viewport.width),
|
||||
uint32_t(current_viewport.height)
|
||||
},
|
||||
};
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2779,16 +2821,37 @@ void Pass::build_commands(
|
||||
float(current_framebuffer_size.height),
|
||||
0.0f, 1.0f
|
||||
};
|
||||
const VkRect2D sci = {
|
||||
{ 0, 0 },
|
||||
{
|
||||
current_framebuffer_size.width,
|
||||
current_framebuffer_size.height
|
||||
},
|
||||
};
|
||||
|
||||
vkCmdSetViewport(cmd, 0, 1, &_vp);
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
if (simulate_scanline)
|
||||
{
|
||||
const VkRect2D sci = {
|
||||
{
|
||||
0,
|
||||
int32_t((float(current_framebuffer_size.height) / float(total_subframes))
|
||||
* float(current_subframe - 1))
|
||||
},
|
||||
{
|
||||
uint32_t(current_framebuffer_size.width),
|
||||
uint32_t(float(current_framebuffer_size.height) / float(total_subframes))
|
||||
},
|
||||
};
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
}
|
||||
else
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
{
|
||||
const VkRect2D sci = {
|
||||
{ 0, 0 },
|
||||
{
|
||||
current_framebuffer_size.width,
|
||||
current_framebuffer_size.height
|
||||
},
|
||||
};
|
||||
vkCmdSetScissor(cmd, 0, 1, &sci);
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdDraw(cmd, 4, 1, 0, 0);
|
||||
@ -3403,6 +3466,15 @@ void vulkan_filter_chain_set_current_shader_subframe(
|
||||
chain->set_current_shader_subframe(cur_subframe);
|
||||
}
|
||||
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
void vulkan_filter_chain_set_simulate_scanline(
|
||||
vulkan_filter_chain_t *chain,
|
||||
bool simulate_scanline)
|
||||
{
|
||||
chain->set_simulate_scanline(simulate_scanline);
|
||||
}
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
void vulkan_filter_chain_set_frame_direction(
|
||||
vulkan_filter_chain_t *chain,
|
||||
int32_t direction)
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include "../include/vulkan/vulkan.h"
|
||||
|
||||
#define VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct vulkan_filter_chain vulkan_filter_chain_t;
|
||||
@ -126,6 +128,11 @@ void vulkan_filter_chain_set_shader_subframes(vulkan_filter_chain_t *chain,
|
||||
void vulkan_filter_chain_set_current_shader_subframe(vulkan_filter_chain_t *chain,
|
||||
uint32_t cur_subframe);
|
||||
|
||||
#ifdef VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
void vulkan_filter_chain_set_simulate_scanline(vulkan_filter_chain_t *chain,
|
||||
bool simulate_scanline);
|
||||
#endif // VULKAN_ROLLING_SCANLINE_SIMULATION
|
||||
|
||||
void vulkan_filter_chain_set_frame_direction(vulkan_filter_chain_t *chain,
|
||||
int32_t direction);
|
||||
|
||||
|
@ -2563,6 +2563,8 @@ void video_driver_build_info(video_frame_info_t *video_info)
|
||||
video_info->black_frame_insertion = settings->uints.video_black_frame_insertion;
|
||||
video_info->bfi_dark_frames = settings->uints.video_bfi_dark_frames;
|
||||
video_info->shader_subframes = settings->uints.video_shader_subframes;
|
||||
video_info->current_subframe = 0;
|
||||
video_info->scan_subframes = settings->bools.video_scan_subframes;
|
||||
video_info->hard_sync = settings->bools.video_hard_sync;
|
||||
video_info->hard_sync_frames = settings->uints.video_hard_sync_frames;
|
||||
video_info->runahead = settings->bools.run_ahead_enabled;
|
||||
@ -3920,6 +3922,7 @@ void video_driver_frame(const void *data, unsigned width,
|
||||
&& video_st->current_video
|
||||
&& video_st->current_video->frame)
|
||||
{
|
||||
video_info.current_subframe = 0;
|
||||
if (video_st->current_video->frame(
|
||||
video_st->data, data, width, height,
|
||||
video_st->frame_count, (unsigned)pitch,
|
||||
|
@ -417,6 +417,7 @@ typedef struct video_frame_info
|
||||
unsigned black_frame_insertion;
|
||||
unsigned bfi_dark_frames;
|
||||
unsigned shader_subframes;
|
||||
unsigned current_subframe;
|
||||
unsigned fps_update_interval;
|
||||
unsigned memory_update_interval;
|
||||
unsigned msg_queue_delay;
|
||||
@ -489,6 +490,7 @@ typedef struct video_frame_info
|
||||
bool crt_switch_hires_menu;
|
||||
bool hdr_enable;
|
||||
bool overlay_behind_menu;
|
||||
bool scan_subframes;
|
||||
} video_frame_info_t;
|
||||
|
||||
typedef void (*update_window_title_cb)(void*);
|
||||
|
@ -4131,6 +4131,10 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_VIDEO_SHADER_SUBFRAMES,
|
||||
"video_shader_subframes"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VIDEO_SCAN_SUBFRAMES,
|
||||
"video_scan_subframes"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VIDEO_CROP_OVERSCAN,
|
||||
"video_crop_overscan"
|
||||
|
@ -428,6 +428,9 @@ int msg_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
case MENU_ENUM_LABEL_VIDEO_SHADER_SUBFRAMES:
|
||||
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_HELP_VIDEO_SHADER_SUBFRAMES), len);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_VIDEO_SCAN_SUBFRAMES:
|
||||
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_HELP_VIDEO_SCAN_SUBFRAMES), len);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_SAVEFILE_DIRECTORY:
|
||||
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_HELP_SAVEFILE_DIRECTORY), len);
|
||||
break;
|
||||
|
@ -2098,6 +2098,18 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_GPU_SCREENSHOT,
|
||||
"GPU Screenshot"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_SCAN_SUBFRAMES,
|
||||
"Rolling scanline simulation"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_VIDEO_SCAN_SUBFRAMES,
|
||||
"Simulates a basic rolling scanline over multiple sub-frames by dividing the screen up vertically and rendering each part of the screen according to how many sub frames there are"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_HELP_VIDEO_SCAN_SUBFRAMES,
|
||||
"Simulates a basic rolling scanline over multiple sub-frames by dividing the screen up vertically and rendering each part of the screen according to how many sub frames there are from the top of the screen down"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_VIDEO_GPU_SCREENSHOT,
|
||||
"Screenshots capture GPU shaded material if available."
|
||||
|
@ -501,6 +501,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_shader_delay, MENU_
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_black_frame_insertion, MENU_ENUM_SUBLABEL_VIDEO_BLACK_FRAME_INSERTION)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_bfi_dark_frames, MENU_ENUM_SUBLABEL_VIDEO_BFI_DARK_FRAMES)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_shader_subframes, MENU_ENUM_SUBLABEL_VIDEO_SHADER_SUBFRAMES)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_scan_subframes, MENU_ENUM_SUBLABEL_VIDEO_SCAN_SUBFRAMES)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_toggle_gamepad_combo, MENU_ENUM_SUBLABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_quit_gamepad_combo, MENU_ENUM_SUBLABEL_INPUT_QUIT_GAMEPAD_COMBO)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_show_hidden_files, MENU_ENUM_SUBLABEL_SHOW_HIDDEN_FILES)
|
||||
@ -4828,6 +4829,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_VIDEO_SHADER_SUBFRAMES:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_shader_subframes);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_VIDEO_SCAN_SUBFRAMES:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_scan_subframes);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_VIDEO_FRAME_DELAY:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_frame_delay);
|
||||
break;
|
||||
|
@ -9400,6 +9400,7 @@ unsigned menu_displaylist_build_list(
|
||||
bool video_hard_sync = settings->bools.video_hard_sync;
|
||||
bool video_wait_swap = settings->bools.video_waitable_swapchains;
|
||||
unsigned bfi = settings->uints.video_black_frame_insertion;
|
||||
unsigned shader_subframes = settings->uints.video_shader_subframes;
|
||||
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
MENU_ENUM_LABEL_VIDEO_VSYNC,
|
||||
@ -9418,6 +9419,14 @@ unsigned menu_displaylist_build_list(
|
||||
MENU_ENUM_LABEL_VIDEO_SHADER_SUBFRAMES,
|
||||
PARSE_ONLY_UINT, false) == 0)
|
||||
count++;
|
||||
|
||||
if (shader_subframes > 1)
|
||||
{
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
MENU_ENUM_LABEL_VIDEO_SCAN_SUBFRAMES,
|
||||
PARSE_ONLY_BOOL, false) == 0)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION,
|
||||
|
@ -13551,6 +13551,26 @@ static bool setting_append_list(
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_CMD_APPLY_AUTO);
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.video_scan_subframes,
|
||||
MENU_ENUM_LABEL_VIDEO_SCAN_SUBFRAMES,
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_SCAN_SUBFRAMES,
|
||||
DEFAULT_SCAN_SUBFRAMES,
|
||||
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;
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_CMD_APPLY_AUTO);
|
||||
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_REINIT);
|
||||
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.video_max_swapchain_images,
|
||||
|
@ -1378,6 +1378,7 @@ enum msg_hash_enums
|
||||
MENU_LBL_H(VIDEO_BLACK_FRAME_INSERTION),
|
||||
MENU_LBL_H(VIDEO_BFI_DARK_FRAMES),
|
||||
MENU_LBL_H(VIDEO_SHADER_SUBFRAMES),
|
||||
MENU_LBL_H(VIDEO_SCAN_SUBFRAMES),
|
||||
MENU_LBL_H(VIDEO_FRAME_DELAY),
|
||||
MENU_LBL_H(VIDEO_FRAME_DELAY_AUTO),
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_AUTOMATIC,
|
||||
|
@ -1375,6 +1375,7 @@ QWidget *VideoPage::widget()
|
||||
|
||||
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_SWAP_INTERVAL);
|
||||
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_SHADER_SUBFRAMES);
|
||||
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_SCAN_SUBFRAMES);
|
||||
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION);
|
||||
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC);
|
||||
vSyncGroup->add(MENU_ENUM_LABEL_VIDEO_FRAME_DELAY);
|
||||
|
Loading…
x
Reference in New Issue
Block a user