mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-27 21:48:29 +00:00
Xbox GDKX support (#5869)
* Xbox GDK support (14 squashed commits) * Added basic keyboard testing * Update readme * Code review fixes * Fixed issue where controller add/removal wasn't working (since the device notification events don't work on Xbox, have to use the joystick thread to poll XInput)
This commit is contained in:
@@ -38,10 +38,17 @@
|
||||
#include "../SDL_sysrender.h"
|
||||
#include "../SDL_d3dmath.h"
|
||||
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
#include "SDL_render_d3d12_xbox.h"
|
||||
#ifndef D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
|
||||
#define D3D12_TEXTURE_DATA_PITCH_ALIGNMENT 256
|
||||
#endif
|
||||
#else
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <dxgidebug.h>
|
||||
#include <d3d12sdklayers.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_shaders_d3d12.h"
|
||||
|
||||
@@ -153,14 +160,18 @@ typedef struct
|
||||
{
|
||||
void *hDXGIMod;
|
||||
void *hD3D12Mod;
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
UINT64 frameToken;
|
||||
#else
|
||||
IDXGIFactory6 *dxgiFactory;
|
||||
IDXGIAdapter4 *dxgiAdapter;
|
||||
IDXGIDebug *dxgiDebug;
|
||||
IDXGISwapChain4 *swapChain;
|
||||
#endif
|
||||
ID3D12Device1 *d3dDevice;
|
||||
ID3D12Debug *debugInterface;
|
||||
IDXGIDebug *dxgiDebug;
|
||||
ID3D12CommandQueue *commandQueue;
|
||||
ID3D12GraphicsCommandList2 *commandList;
|
||||
IDXGISwapChain4 *swapChain;
|
||||
DXGI_SWAP_EFFECT swapEffect;
|
||||
|
||||
/* Descriptor heaps */
|
||||
@@ -231,7 +242,7 @@ typedef struct
|
||||
static const GUID SDL_IID_IDXGIFactory6 = { 0xc1b6694f, 0xff09, 0x44a9, { 0xb0, 0x3c, 0x77, 0x90, 0x0a, 0x0a, 0x1d, 0x17 } };
|
||||
static const GUID SDL_IID_IDXGIAdapter4 = { 0x3c8d99d1, 0x4fbf, 0x4181, { 0xa8, 0x2c, 0xaf, 0x66, 0xbf, 0x7b, 0xd2, 0x4e } };
|
||||
static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
|
||||
static const GUID SDL_IID_ID3D12Device5 = { 0x8b4f173b, 0x2fea, 0x4b80, { 0x8f, 0x58, 0x43, 0x07, 0x19, 0x1a, 0xb9, 0x5d } };
|
||||
static const GUID SDL_IID_ID3D12Device1 = { 0x77acce80, 0x638e, 0x4e65, { 0x88, 0x95, 0xc1, 0xf2, 0x33, 0x86, 0x86, 0x3e } };
|
||||
static const GUID SDL_IID_IDXGISwapChain4 = { 0x3D585D5A, 0xBD4A, 0x489E, { 0xB1, 0xF4, 0x3D, 0xBC, 0xB6, 0x45, 0x2F, 0xFB } };
|
||||
static const GUID SDL_IID_IDXGIDebug1 = { 0xc5a05f0c, 0x16f2, 0x4adf, { 0x9f, 0x4d, 0xa8, 0xc4, 0xd5, 0x8a, 0xc5, 0x50 } };
|
||||
static const GUID SDL_IID_IDXGIInfoQueue = { 0xD67441C7,0x672A,0x476f, { 0x9E,0x82,0xCD,0x55,0xB4,0x49,0x49,0xCE } };
|
||||
@@ -307,8 +318,11 @@ D3D12_ReleaseAll(SDL_Renderer * renderer)
|
||||
if (data) {
|
||||
int i;
|
||||
|
||||
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
SAFE_RELEASE(data->dxgiFactory);
|
||||
SAFE_RELEASE(data->dxgiAdapter);
|
||||
SAFE_RELEASE(data->swapChain);
|
||||
#endif
|
||||
SAFE_RELEASE(data->d3dDevice);
|
||||
SAFE_RELEASE(data->debugInterface);
|
||||
SAFE_RELEASE(data->commandQueue);
|
||||
@@ -317,7 +331,6 @@ D3D12_ReleaseAll(SDL_Renderer * renderer)
|
||||
SAFE_RELEASE(data->textureRTVDescriptorHeap);
|
||||
SAFE_RELEASE(data->srvDescriptorHeap);
|
||||
SAFE_RELEASE(data->samplerDescriptorHeap);
|
||||
SAFE_RELEASE(data->swapChain);
|
||||
SAFE_RELEASE(data->fence);
|
||||
|
||||
for (i = 0; i < SDL_D3D12_NUM_BUFFERS; ++i) {
|
||||
@@ -345,12 +358,14 @@ D3D12_ReleaseAll(SDL_Renderer * renderer)
|
||||
data->currentRenderTargetView.ptr = 0;
|
||||
data->currentSampler.ptr = 0;
|
||||
|
||||
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
/* Check for any leaks if in debug mode */
|
||||
if (data->dxgiDebug) {
|
||||
DXGI_DEBUG_RLO_FLAGS rloFlags = (DXGI_DEBUG_RLO_FLAGS)(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL);
|
||||
D3D_CALL(data->dxgiDebug, ReportLiveObjects, SDL_DXGI_DEBUG_ALL, rloFlags);
|
||||
SAFE_RELEASE(data->dxgiDebug);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Unload the D3D libraries. This should be done last, in order
|
||||
* to prevent IUnknown::Release() calls from crashing.
|
||||
@@ -700,10 +715,12 @@ D3D12_CreateVertexBuffer(D3D12_RenderData *data, size_t vbidx, size_t size)
|
||||
static HRESULT
|
||||
D3D12_CreateDeviceResources(SDL_Renderer* renderer)
|
||||
{
|
||||
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY)(UINT flags, REFIID riid, void** ppFactory);
|
||||
PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc;
|
||||
D3D12_RenderData* data = (D3D12_RenderData*)renderer->driverdata;
|
||||
PFN_D3D12_CREATE_DEVICE D3D12CreateDeviceFunc;
|
||||
#endif
|
||||
D3D12_RenderData* data = (D3D12_RenderData*)renderer->driverdata;
|
||||
ID3D12Device* d3dDevice = NULL;
|
||||
HRESULT result = S_OK;
|
||||
UINT creationFlags = 0;
|
||||
@@ -728,6 +745,10 @@ D3D12_CreateDeviceResources(SDL_Renderer* renderer)
|
||||
DXGI_FORMAT_R8_UNORM
|
||||
};
|
||||
|
||||
/* See if we need debug interfaces */
|
||||
createDebug = SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_FALSE);
|
||||
|
||||
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
data->hDXGIMod = SDL_LoadObject("dxgi.dll");
|
||||
if (!data->hDXGIMod) {
|
||||
result = E_FAIL;
|
||||
@@ -752,9 +773,6 @@ D3D12_CreateDeviceResources(SDL_Renderer* renderer)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* See if we need debug interfaces */
|
||||
createDebug = SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_FALSE);
|
||||
|
||||
if (createDebug) {
|
||||
PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterfaceFunc;
|
||||
|
||||
@@ -766,7 +784,15 @@ D3D12_CreateDeviceResources(SDL_Renderer* renderer)
|
||||
D3D12GetDebugInterfaceFunc(D3D_GUID(SDL_IID_ID3D12Debug), (void**)&data->debugInterface);
|
||||
D3D_CALL(data->debugInterface, EnableDebugLayer);
|
||||
}
|
||||
#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/
|
||||
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
result = D3D12_XBOX_CreateDevice(&d3dDevice, createDebug);
|
||||
if (FAILED(result)) {
|
||||
/* SDL Error is set by D3D12_XBOX_CreateDevice */
|
||||
goto done;
|
||||
}
|
||||
#else
|
||||
if (createDebug) {
|
||||
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
|
||||
IDXGIInfoQueue *dxgiInfoQueue = NULL;
|
||||
@@ -818,7 +844,7 @@ D3D12_CreateDeviceResources(SDL_Renderer* renderer)
|
||||
|
||||
result = D3D12CreateDeviceFunc((IUnknown *)data->dxgiAdapter,
|
||||
D3D_FEATURE_LEVEL_11_0, /* Request minimum feature level 11.0 for maximum compatibility */
|
||||
D3D_GUID(SDL_IID_ID3D12Device5),
|
||||
D3D_GUID(SDL_IID_ID3D12Device1),
|
||||
(void **)&d3dDevice
|
||||
);
|
||||
if (FAILED(result)) {
|
||||
@@ -848,10 +874,11 @@ D3D12_CreateDeviceResources(SDL_Renderer* renderer)
|
||||
|
||||
SAFE_RELEASE(infoQueue);
|
||||
}
|
||||
#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/
|
||||
|
||||
result = D3D_CALL(d3dDevice, QueryInterface, D3D_GUID(SDL_IID_ID3D12Device5), (void **)&data->d3dDevice);
|
||||
result = D3D_CALL(d3dDevice, QueryInterface, D3D_GUID(SDL_IID_ID3D12Device1), (void **)&data->d3dDevice);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device to ID3D12Device5"), result);
|
||||
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device to ID3D12Device1"), result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1120,6 +1147,7 @@ D3D12_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRec
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
static HRESULT
|
||||
D3D12_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
|
||||
{
|
||||
@@ -1187,6 +1215,7 @@ done:
|
||||
SAFE_RELEASE(swapChain);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer * renderer);
|
||||
|
||||
@@ -1246,6 +1275,7 @@ D3D12_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
||||
h = tmp;
|
||||
}
|
||||
|
||||
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
if (data->swapChain) {
|
||||
/* If the swap chain already exists, resize it. */
|
||||
result = D3D_CALL(data->swapChain, ResizeBuffers,
|
||||
@@ -1283,9 +1313,17 @@ D3D12_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/
|
||||
|
||||
/* Get each back buffer render target and create render target views */
|
||||
for (i = 0; i < SDL_D3D12_NUM_BUFFERS; ++i) {
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
result = D3D12_XBOX_CreateBackBufferTarget(data->d3dDevice, renderer->window->w, renderer->window->h, (void **) &data->renderTargets[i]);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("D3D12_XBOX_CreateBackBufferTarget"), result);
|
||||
goto done;
|
||||
}
|
||||
#else
|
||||
result = D3D_CALL(data->swapChain, GetBuffer,
|
||||
i,
|
||||
D3D_GUID(SDL_IID_ID3D12Resource),
|
||||
@@ -1295,6 +1333,7 @@ D3D12_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
||||
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain4::GetBuffer"), result);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_zero(rtvDesc);
|
||||
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
@@ -1307,7 +1346,11 @@ D3D12_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
||||
}
|
||||
|
||||
/* Set back buffer index to current buffer */
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
data->currentBackBufferIndex = 0;
|
||||
#else
|
||||
data->currentBackBufferIndex = D3D_CALL(data->swapChain, GetCurrentBackBufferIndex);
|
||||
#endif
|
||||
|
||||
/* Set the swap chain target immediately, so that a target is always set
|
||||
* even before we get to SetDrawState. Without this it's possible to hit
|
||||
@@ -1323,6 +1366,10 @@ D3D12_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
||||
|
||||
data->viewportDirty = SDL_TRUE;
|
||||
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
D3D12_XBOX_StartFrame(data->d3dDevice, &data->frameToken);
|
||||
#endif
|
||||
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
@@ -2870,8 +2917,10 @@ static void
|
||||
D3D12_RenderPresent(SDL_Renderer * renderer)
|
||||
{
|
||||
D3D12_RenderData *data = (D3D12_RenderData *) renderer->driverdata;
|
||||
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
UINT syncInterval;
|
||||
UINT presentFlags;
|
||||
#endif
|
||||
HRESULT result;
|
||||
|
||||
/* Transition the render target to present state */
|
||||
@@ -2885,6 +2934,9 @@ D3D12_RenderPresent(SDL_Renderer * renderer)
|
||||
result = D3D_CALL(data->commandList, Close);
|
||||
D3D_CALL(data->commandQueue, ExecuteCommandLists, 1, (ID3D12CommandList * const *)&data->commandList);
|
||||
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
result = D3D12_XBOX_PresentFrame(data->commandQueue, data->frameToken, data->renderTargets[data->currentBackBufferIndex]);
|
||||
#else
|
||||
if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
|
||||
syncInterval = 1;
|
||||
presentFlags = 0;
|
||||
@@ -2897,6 +2949,7 @@ D3D12_RenderPresent(SDL_Renderer * renderer)
|
||||
* rects to improve efficiency in certain scenarios.
|
||||
*/
|
||||
result = D3D_CALL(data->swapChain, Present, syncInterval, presentFlags);
|
||||
#endif
|
||||
|
||||
if (FAILED(result) && result != DXGI_ERROR_WAS_STILL_DRAWING) {
|
||||
/* If the device was removed either by a disconnect or a driver upgrade, we
|
||||
@@ -2923,7 +2976,12 @@ D3D12_RenderPresent(SDL_Renderer * renderer)
|
||||
}
|
||||
|
||||
data->fenceValue++;
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
data->currentBackBufferIndex++;
|
||||
data->currentBackBufferIndex %= SDL_D3D12_NUM_BUFFERS;
|
||||
#else
|
||||
data->currentBackBufferIndex = D3D_CALL(data->swapChain, GetCurrentBackBufferIndex);
|
||||
#endif
|
||||
|
||||
/* Reset the command allocator and command list, and transition back to render target */
|
||||
D3D12_ResetCommandList(data);
|
||||
@@ -2932,6 +2990,10 @@ D3D12_RenderPresent(SDL_Renderer * renderer)
|
||||
D3D12_RESOURCE_STATE_PRESENT,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET
|
||||
);
|
||||
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
D3D12_XBOX_StartFrame(data->d3dDevice, &data->frameToken);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user