Skip to main content
Porting from XInput to GameInput is the least complicated of any of the legacy APIs. This is because GameInput was heavily influenced by XInput’s simple (and easy to use) programming model, and therefore, many XInput APIs map 1:1 with equivalent functions in GameInput.

Key differences

The key differences between XInput and GameInput are discussed in the following sections.

C vs. C++

The XInput API is a collection of flat C functions. GameInput, on the other hand, is C++ and uses interfaces (just like the graphics and audio APIs). In practice, this doesn’t complicate code that uses the GameInput API, doesn’t impact performance, and has some advantages that become apparent once you become more familiar with how GameInput works. It’s important to understand that although these interfaces may look like COM, they aren’t. Only a basic understanding of reference counting is required to use these interfaces. For more information, see the Interfaces section of the GameInput fundamentals topic.

Getting input

In XInput, most games loop through the user indices until one is found with a connected device, then state is read from that device. Games will often remember the user index so they don’t have to loop the next time. For example, the following code is typical for a game prompting the user to “press A” on their controller:
In GameInput, you first get the input without specifying a device and you can query which device the input came from if you want. The code looks similar but eliminating the need for explicit device enumeration can lead to simpler algorithms.
The code isn’t quite as simple as XInput, but it’s very similar. As you become more familiar with the GameInput API, you’ll see how this model provides powerful options to handle input that do not exist in XInput. It is also worth noting that XInput returns analog values from triggers as type BYTE, and analog values from thumbsticks as type SHORT. With the GameInput API, these analog values are returned as float values from 0 to 1 (triggers) or -1 to 1 (thumbsticks).

Rumble feedback

In XInput, games simply callXInputSetState to send rumble (vibration) commands to a device. In GameInput, games need to acquire the IGameInputDevice instance for the device, then call its SetRumbleState method. The usage is similar between these two methods. This is an example of when you’ll call functions on the device interface, rather than it solely being a device identifier.

Application Focus

On console, GameInput provides input to an application only when it is in focus. Otherwise, the state returned contains neutral or “rest” values, as if the user isn’t touching the device at all. This eliminates the need for extra input code that deals with change in focus (for example, callingXInputEnable). On PC, input goes to all processes by default. In the future, this behavior will be changeable by using the SetFocusPolicy method.

The XInputOnGameInput wrapper

The Microsoft Game Development Kit (GDK) ships with a header file calledXInputOnGameInput.h that contains an implementation of the XInput API on top of GameInput. We recommend porting directly to GameInput especially if you want keyboard and mouse or other input devices. However, the XInputOnGameInput wrapper can be used to help bootstrap an initial porting effort without requiring any changes to existing XInput code. To use the XInputOnGameInput wrapper, simply replace this code:
with this code:
and then recompile your code. The implementation of the XInput wrapper code is entirely in the header file, so it can also be examined as an example of using the GameInput API, and/or modified as needed.

Differences between XInput and XInputOnGameInput

Generally, the XInputOnGameInput wrapper is a direct drop-in replacement for the legacy XInput API. However, there are a few minor differences:
  • For simplicity, only gamepad device support has been coded into the wrapper. If you need to support other devices, such as racing wheels or arcade sticks, use GameInput directly or add support for those devices in the XInputOnGameInput code.
  • The wrapper will return gamepad input only when the game is in focus. When the game is not in focus, any gamepad state returned is set to neutral or “rest” values, as if the user isn’t touching the gamepad. This is done regardless of any calls toXInputEnable (or lack thereof).
  • The value ofXUSER_MAX_COUNT has been increased from 4 to 8. This should generally be transparent to most legacy XInput code. However, be sure to carefully review any use of theXInputGetKeystroke function in your code to help ensure that nothing is hard-coded to assume a maximum value of 4 being returned in theUserIndex member of theXINPUT_KEYSTROKE structure. Otherwise, a buffer overrun could occur.
  • A few new functions have been added (see the following) which should be of interest only if you intend to continue using the XInput wrapper in production code.

Using XInputOnGameInput in production code

The XInputOnGameInput wrapper is written to be high-performance and lock-free, inheriting all the performance optimizations of the GameInput API, and is therefore suitable for use in production code. It also inherits GameInput’s broader device support (such as popular HID gamepads), and adds the following new functions to the API:
  • XInputSetStateEx is similar toXInputSetState but adds support for trigger motors.
  • XInputGetStateWithToken is similar toXInputGetState but allows the caller to supply a D3DX frame pipeline token to associate a specific input reading with a graphics frame for later analysis in PIX.
    [!NOTE] In the May Preview release,XInputGetStateWithToken currently behaves identically toXInputGetState, because the underlying GameInput code isn’t fully implemented.
  • XInputGetDeviceId returns theAPP_LOCAL_DEVICE_ID for the device at a given user index. Passing this ID to the FindDeviceFromId method on IGameInput returns the corresponding IGameInputDevice for that user index. This can then be used to access additional functionality in the GameInput API that’s not exposed via the XInput wrapper.

Optimizing the wrapper code

By default, the XInputOnGameInput wrapper is configured to be drop-in compatible with the legacy XInput API. Games that don’t require 100% compatible behavior can fine-tune the behavior and performance of the wrapper by defining any of the following preprocessor macros:
XINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION
By default, the XInput wrapper lazy-initializes the underlying GameInput API automatically the first time any of the wrapper functions are called. This ensures drop-in compatibility with existing XInput code, but has several minor drawbacks:
  1. The execution time of the first XInput wrapper function call will be longer than usual.
  2. Every XInput wrapper function must perform a check to see if the lazy initialization has been performed every time it is called. This is a simple test of a global variable, so the branch predictor should ameliorate the cost, but it is extra overhead.
  3. Although it should never fail, there is no way to tell if the lazy initialization of the underlying GameInput API was successful.
  4. The underlying IGameInput instance isn’t released until the XInput wrapper’s global variables are cleaned up (either due to module unload or process termination).
Games can take manual control of the wrapper’s initialization and shutdown by defining theXINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION macro. This adds two new functionsXInputOnGameInputInitialize andXInputOnGameInputUninitialize which can be called to precisely control when initialization and shut down occur.
XINPUT_ON_GAMEINPUT_NO_XINPUTENABLE
The code required to implement theXInputEnable function adds extra overhead to every call of theXInputGetState,XInputGetStateWithToken,XInputSetState,XInputSetStateEx, andXInputGetKeystroke functions. If your code doesn’t callXInputEnable, or if it can easily be eliminated from your code, defining theXINPUT_ON_GAMEINPUT_NO_XINPUTENABLE macro will remove support forXInputEnable and the associated overhead it brings. The underlying GameInput code automatically performs the functionality ofXInputEnable on focus changes anyway, so most games will want to define this macro if they can.
XINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE
The code required to implement theXInputGetKeystroke function adds a few extra functions and variables to the wrapper’s implementation. It doesn’t add overhead to any of the other XInput API functions, but if your code doesn’t callXInputGetKeystroke you can define theXINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE macro to slightly decrease the code/data size of the XInput wrapper.

Reference API documentation

See also

Overview of GameInput GameInput API reference Microsoft Game Development Kit
Last modified on August 6, 2026