Preemptive Frames updates (#17003)

* Preemptive Frames: input_poll and input_state improvements

- Check pointing devices when used by core; ignore input_libretro_device
- Use stored mouse x,y input state (lower level call might flush deltas)
- Remove port mapping code (unnecessary now)
- Fewer memsets

* Add Preemptive Frames to Qt options menu
This commit is contained in:
neil4 2024-09-14 14:14:36 -05:00 committed by GitHub
parent 7601df9a4c
commit 53081f1794
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 70 additions and 68 deletions

View File

@ -1332,26 +1332,29 @@ force_input_dirty:
static int16_t preempt_input_state(unsigned port,
unsigned device, unsigned index, unsigned id)
{
settings_t *settings = config_get_ptr();
runloop_state_t *runloop_st = runloop_state_get_ptr();
preempt_t *preempt = runloop_st->preempt_data;
unsigned device_class = device & RETRO_DEVICE_MASK;
unsigned *port_map = settings->uints.input_remap_port_map[port];
uint8_t p;
runloop_state_t *runloop_st = runloop_state_get_ptr();
preempt_t *preempt = runloop_st->preempt_data;
unsigned device_class = device & RETRO_DEVICE_MASK;
switch (device_class)
{
case RETRO_DEVICE_ANALOG:
/* Add requested inputs to mask */
while ((p = *(port_map++)) < MAX_USERS)
preempt->analog_mask[p] |= (1 << (id + index * 2));
preempt->analog_mask[port] |= (1 << (id + index * 2));
break;
case RETRO_DEVICE_LIGHTGUN:
case RETRO_DEVICE_MOUSE:
case RETRO_DEVICE_POINTER:
/* Set pointing device for this port */
while ((p = *(port_map++)) < MAX_USERS)
preempt->ptr_dev[p] = device_class;
preempt->ptr_dev_needed[port] = device_class;
break;
case RETRO_DEVICE_MOUSE:
/* Set pointing device and return stored x,y */
if (id <= RETRO_DEVICE_ID_MOUSE_Y)
{
preempt->ptr_dev_needed[port] = device_class;
if (preempt->ptr_dev_polled[port] == device_class)
return preempt->ptrdev_state[port][id];
}
break;
default:
break;
@ -1480,7 +1483,7 @@ error:
}
static INLINE bool preempt_analog_input_dirty(preempt_t *preempt,
retro_input_state_t state_cb, unsigned port, unsigned mapped_port)
retro_input_state_t state_cb, unsigned port)
{
int16_t state[20] = {0};
uint8_t base, i;
@ -1490,17 +1493,20 @@ static INLINE bool preempt_analog_input_dirty(preempt_t *preempt,
{
base = i * 2;
if (preempt->analog_mask[port] & (1 << (base )))
state[base ] = state_cb(mapped_port, RETRO_DEVICE_ANALOG, i, 0);
state[base ] = state_cb(port, RETRO_DEVICE_ANALOG, i, 0);
if (preempt->analog_mask[port] & (1 << (base + 1)))
state[base + 1] = state_cb(mapped_port, RETRO_DEVICE_ANALOG, i, 1);
state[base + 1] = state_cb(port, RETRO_DEVICE_ANALOG, i, 1);
}
/* buttons */
for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
if (preempt->analog_mask[port] & 0xfff0)
{
if (preempt->analog_mask[port] & (1 << (i + 4)))
state[i + 4] = state_cb(mapped_port, RETRO_DEVICE_ANALOG,
RETRO_DEVICE_INDEX_ANALOG_BUTTON, i);
for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
{
if (preempt->analog_mask[port] & (1 << (i + 4)))
state[i + 4] = state_cb(port, RETRO_DEVICE_ANALOG,
RETRO_DEVICE_INDEX_ANALOG_BUTTON, i);
}
}
if (memcmp(preempt->analog_state[port], state, sizeof(state)) == 0)
@ -1511,8 +1517,7 @@ static INLINE bool preempt_analog_input_dirty(preempt_t *preempt,
}
static INLINE bool preempt_ptr_input_dirty(preempt_t *preempt,
retro_input_state_t state_cb, unsigned device,
unsigned port, unsigned mapped_port)
retro_input_state_t state_cb, unsigned device, unsigned port)
{
int16_t state[4] = {0};
unsigned count_id = 0;
@ -1537,16 +1542,16 @@ static INLINE bool preempt_ptr_input_dirty(preempt_t *preempt,
}
/* x, y */
state[0] = state_cb(mapped_port, device, 0, x_id );
state[1] = state_cb(mapped_port, device, 0, x_id + 1);
state[0] = state_cb(port, device, 0, x_id );
state[1] = state_cb(port, device, 0, x_id + 1);
/* buttons */
for (id = 2; id <= max_id; id++)
state[2] |= state_cb(mapped_port, device, 0, id) ? 1 << id : 0;
state[2] |= state_cb(port, device, 0, id) ? 1 << id : 0;
/* ptr count */
if (count_id)
state[3] = state_cb(mapped_port, device, 0, count_id);
state[3] = state_cb(port, device, 0, count_id);
if (memcmp(preempt->ptrdev_state[port], state, sizeof(state)) == 0)
return false;
@ -1560,52 +1565,42 @@ static INLINE void preempt_input_poll(preempt_t *preempt,
{
size_t p;
int16_t joypad_state;
retro_input_state_t state_cb = input_driver_state_wrapper;
unsigned max_users = settings->uints.input_max_users;
retro_input_state_t state_cb = input_driver_state_wrapper;
unsigned max_users = settings->uints.input_max_users;
input_driver_poll();
/* Check for input state changes */
for (p = 0; p < max_users; p++)
{
unsigned mapped_port = settings->uints.input_remap_ports[p];
unsigned device = settings->uints.input_libretro_device[mapped_port]
& RETRO_DEVICE_MASK;
switch (device)
/* Check full digital joypad */
joypad_state = state_cb(p, RETRO_DEVICE_JOYPAD,
0, RETRO_DEVICE_ID_JOYPAD_MASK);
if (joypad_state != preempt->joypad_state[p])
{
case RETRO_DEVICE_JOYPAD:
case RETRO_DEVICE_ANALOG:
/* Check full digital joypad */
joypad_state = state_cb(mapped_port, RETRO_DEVICE_JOYPAD,
0, RETRO_DEVICE_ID_JOYPAD_MASK);
if (joypad_state != preempt->joypad_state[p])
{
preempt->joypad_state[p] = joypad_state;
runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
}
preempt->joypad_state[p] = joypad_state;
runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
}
/* Check requested analogs */
if ( preempt->analog_mask[p]
&& preempt_analog_input_dirty(preempt, state_cb, (unsigned)p, mapped_port))
runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
break;
case RETRO_DEVICE_MOUSE:
case RETRO_DEVICE_LIGHTGUN:
case RETRO_DEVICE_POINTER:
/* Check full device state */
if (preempt_ptr_input_dirty(
preempt, state_cb, preempt->ptr_dev[p], (unsigned)p, mapped_port))
runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
break;
default:
break;
/* Check requested analogs */
if ( preempt->analog_mask[p]
&& preempt_analog_input_dirty(preempt, state_cb, (unsigned)p))
{
runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
preempt->analog_mask[p] = 0;
}
/* Check requested pointing device */
if (preempt->ptr_dev_needed[p])
{
if (preempt_ptr_input_dirty(
preempt, state_cb, preempt->ptr_dev_needed[p], (unsigned)p))
runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
preempt->ptr_dev_polled[p] = preempt->ptr_dev_needed[p];
preempt->ptr_dev_needed[p] = RETRO_DEVICE_NONE;
}
}
/* Clear requested inputs */
memset(preempt->analog_mask, 0, max_users * sizeof(uint32_t));
memset(preempt->ptr_dev, 0, max_users * sizeof(uint8_t));
}
/* macro for preempt_run */

View File

@ -56,7 +56,9 @@ typedef struct preemptive_frames_data
int16_t ptrdev_state[MAX_USERS][4];
/* Pointing device requested */
uint8_t ptr_dev[MAX_USERS];
uint8_t ptr_dev_needed[MAX_USERS];
/* Device ID of ptrdev_state */
uint8_t ptr_dev_polled[MAX_USERS];
/* Buffer indexes for replays */
uint8_t start_ptr;
uint8_t replay_ptr;

View File

@ -385,9 +385,10 @@ LatencyPage::LatencyPage(QObject *parent) :
QWidget *LatencyPage::widget()
{
QWidget *widget = new QWidget;
FormLayout *layout = new FormLayout;
CheckableSettingsGroup *runAheadGpuSync = new CheckableSettingsGroup(MENU_ENUM_LABEL_RUN_AHEAD_ENABLED);
QWidget *widget = new QWidget;
FormLayout *layout = new FormLayout;
CheckableSettingsGroup *runAheadGroup = new CheckableSettingsGroup(MENU_ENUM_LABEL_RUN_AHEAD_ENABLED);
CheckableSettingsGroup *preemptGroup = new CheckableSettingsGroup(MENU_ENUM_LABEL_PREEMPT_ENABLE);
rarch_setting_t *hardSyncSetting = menu_setting_find_enum(MENU_ENUM_LABEL_VIDEO_HARD_SYNC);
@ -408,10 +409,14 @@ QWidget *LatencyPage::widget()
layout->add(menu_setting_find_enum(MENU_ENUM_LABEL_AUDIO_LATENCY));
layout->add(menu_setting_find_enum(MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR));
runAheadGpuSync->add(menu_setting_find_enum(MENU_ENUM_LABEL_RUN_AHEAD_FRAMES));
runAheadGpuSync->add(menu_setting_find_enum(MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE));
runAheadGpuSync->add(menu_setting_find_enum(MENU_ENUM_LABEL_RUN_AHEAD_HIDE_WARNINGS));
layout->addRow(runAheadGpuSync);
runAheadGroup->add(menu_setting_find_enum(MENU_ENUM_LABEL_RUN_AHEAD_FRAMES));
runAheadGroup->add(menu_setting_find_enum(MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE));
runAheadGroup->add(menu_setting_find_enum(MENU_ENUM_LABEL_RUN_AHEAD_HIDE_WARNINGS));
layout->addRow(runAheadGroup);
preemptGroup->add(menu_setting_find_enum(MENU_ENUM_LABEL_PREEMPT_FRAMES));
preemptGroup->add(menu_setting_find_enum(MENU_ENUM_LABEL_PREEMPT_HIDE_WARNINGS));
layout->addRow(preemptGroup);
widget->setLayout(layout);