mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
input: a port's RetroPad buttons are compiled once a frame
A core that reads its buttons one by one went through input_state_internal() for each: the port mapping, the remap table, turbo, hold, the overlay and analog-to-d-pad, sixteen times a frame for one pad. A core that asks for the bitmask got all sixteen from one such walk. Keep the result of that walk as the frame's view of the port: one word holding the sixteen buttons as the core is to see them. It is compiled through the existing mask path - nothing about how a button is decided changes - when a core asks for the port's mask, or for a second button in the frame. After that every button and mask query for the port reads the word. input_driver_poll() invalidates it, and so does a core's first analog request, which switches analog-to-d-pad off for the port. The first button of a frame still takes the old path, so a core that reads a single button a frame pays what it did. In samples/runloop/frontend_overhead, on the release build: - sixteen buttons read one by one: about 65 ns a query before, about 25 ns now with the compile spread over them; - 256 queries a frame: 8 ns each; - one query a frame: unchanged, 2.7 us for the whole frame against 2.9 us before, which is within the noise of this machine. The lane added in the previous commit holds this to what cores saw before: reading button by button and reading the mask give the same buttons frame for frame, and the same recorded digests, under the default mapping, a remap, analog-to-d-pad, turbo and hold. The digests did not change. The port a core passes is now checked before it indexes the per-port arrays here; one past MAX_USERS read and wrote outside them. Not covered by a test: run-ahead, netplay and input recording. All three reach this function the same way a core does - recording still logs every query - and each run of the core polls, which invalidates the view. Turbo modes other than the classic one are not in the lane either.
This commit is contained in:
1 parent
932aa6a984
commit
3a6a1e9c4f
2 files changed
+76
-4
No files matched your search
+64
-4
@@ -7853,6 +7853,10 @@ void input_driver_poll(void)
|
||||
/* Invalidate joypad state bitmask cache for the new frame */
|
||||
memset(input_st->joypad_state_cache_valid, 0,
|
||||
sizeof(input_st->joypad_state_cache_valid));
|
||||
memset(input_st->frame_view_valid, 0,
|
||||
sizeof(input_st->frame_view_valid));
|
||||
memset(input_st->frame_view_asked, 0,
|
||||
sizeof(input_st->frame_view_asked));
|
||||
|
||||
/* Enable/disable sensors at the driver level based on demand
|
||||
* from shaders and/or core. Setting gates everything. */
|
||||
@@ -8483,20 +8487,76 @@ int16_t input_driver_state_wrapper(unsigned port, unsigned device,
|
||||
*input_st = &input_driver_st;
|
||||
settings_t *settings = config_get_ptr();
|
||||
int16_t result = 0;
|
||||
|
||||
/* The port comes from the core, and indexes per-port arrays here
|
||||
* and below. */
|
||||
if (port >= MAX_USERS)
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_BSV_MOVIE
|
||||
if (BSV_MOVIE_IS_PLAYBACK_ON())
|
||||
return bsv_movie_read_state(input_st, port, device, idx, id);
|
||||
#endif
|
||||
|
||||
/* Read input state */
|
||||
result = input_state_internal(input_st, settings, port, device, idx, id);
|
||||
/* Read input state.
|
||||
*
|
||||
* The RetroPad's buttons come from the frame's view of the port: a
|
||||
* word holding all sixteen, compiled once through the mask path of
|
||||
* input_state_internal(). After that a button or a mask query is
|
||||
* a read of that word, however many a core makes and whichever way
|
||||
* it asks.
|
||||
*
|
||||
* A core that reads button by button used to walk the port
|
||||
* mapping, remaps, turbo, hold and overlay once per button. The
|
||||
* view is compiled on its second button of the frame, not its
|
||||
* first: a core that reads a single button a frame keeps the cost
|
||||
* it had, and one that reads more pays for the walk once. A core
|
||||
* that asks for the mask already got its buttons compiled this
|
||||
* way. samples/runloop/frontend_overhead holds the two readings
|
||||
* to the same result, frame for frame. */
|
||||
if ( (device & RETRO_DEVICE_MASK) == RETRO_DEVICE_JOYPAD
|
||||
&& idx == 0
|
||||
&& ( id < RARCH_FIRST_CUSTOM_BIND
|
||||
|| id == RETRO_DEVICE_ID_JOYPAD_MASK))
|
||||
{
|
||||
if ( !input_st->frame_view_valid[port]
|
||||
&& ( id == RETRO_DEVICE_ID_JOYPAD_MASK
|
||||
|| input_st->frame_view_asked[port]))
|
||||
{
|
||||
input_st->frame_view_joypad[port] = input_state_internal(
|
||||
input_st, settings, port, RETRO_DEVICE_JOYPAD, 0,
|
||||
RETRO_DEVICE_ID_JOYPAD_MASK);
|
||||
input_st->frame_view_valid[port] = true;
|
||||
}
|
||||
|
||||
if (!input_st->frame_view_valid[port])
|
||||
{
|
||||
/* the frame's first button for this port */
|
||||
input_st->frame_view_asked[port] = true;
|
||||
result = input_state_internal(input_st, settings,
|
||||
port, device, idx, id);
|
||||
}
|
||||
else if (id == RETRO_DEVICE_ID_JOYPAD_MASK)
|
||||
result = input_st->frame_view_joypad[port];
|
||||
else
|
||||
result = ((uint16_t)input_st->frame_view_joypad[port] >> id) & 1;
|
||||
}
|
||||
else
|
||||
result = input_state_internal(input_st, settings, port, device, idx, id);
|
||||
|
||||
/* Register any analog stick input requests for
|
||||
* this 'virtual' (core) port */
|
||||
* this 'virtual' (core) port. The first one switches
|
||||
* analog-to-d-pad off for the port, which changes its buttons:
|
||||
* the view is compiled again for the queries that follow. */
|
||||
if ( (device == RETRO_DEVICE_ANALOG)
|
||||
&& ( (idx == RETRO_DEVICE_INDEX_ANALOG_LEFT)
|
||||
|| (idx == RETRO_DEVICE_INDEX_ANALOG_RIGHT)))
|
||||
|| (idx == RETRO_DEVICE_INDEX_ANALOG_RIGHT))
|
||||
&& !input_st->analog_requested[port])
|
||||
{
|
||||
input_st->analog_requested[port] = true;
|
||||
input_st->frame_view_valid[port] = false;
|
||||
input_st->frame_view_asked[port] = false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_BSV_MOVIE
|
||||
if (BSV_MOVIE_IS_RECORDING())
|
||||
|
||||
@@ -696,7 +696,19 @@ typedef struct
|
||||
* armed outside input_keys_pressed() starts from the previous
|
||||
* frame's held set. */
|
||||
uint16_t wait_release_mask[MAX_USERS];
|
||||
|
||||
/* The frame's view of each port's RetroPad buttons, as a core is
|
||||
* given them: after port mapping, remaps, turbo, hold, overlays and
|
||||
* analog-to-d-pad. Compiled when a core asks for the port's mask,
|
||||
* or for a second button in the frame (frame_view_asked marks the
|
||||
* first); from then on every button and mask query for the port
|
||||
* reads this word. Invalidated by input_driver_poll(), and when
|
||||
* the core's first analog request changes analog-to-d-pad for the
|
||||
* port. */
|
||||
int16_t frame_view_joypad[MAX_USERS];
|
||||
bool joypad_state_cache_valid[MAX_USERS];
|
||||
bool frame_view_valid[MAX_USERS];
|
||||
bool frame_view_asked[MAX_USERS];
|
||||
|
||||
retro_bits_512_t keyboard_mapping_bits; /* bool alignment */
|
||||
input_game_focus_state_t game_focus_state; /* bool alignment */
|
||||
|
||||
Reference in new issue
Block a user