SetSwapchainPresentMode + other swapchain-y features from FNA3D D3D11

d3d11
Caleb Cornett 2024-02-10 17:07:56 -06:00 committed by cosmonaut
parent a5284ba0cd
commit 17f9322698
2 changed files with 87 additions and 18 deletions

View File

@ -389,12 +389,13 @@ typedef struct D3D11SwapchainData
{ {
IDXGISwapChain *swapchain; IDXGISwapChain *swapchain;
D3D11Texture texture; D3D11Texture texture;
Refresh_PresentMode presentMode;
} D3D11SwapchainData; } D3D11SwapchainData;
/* FIXME: Why do we have WindowData separate from SwapchainData? */
typedef struct D3D11WindowData typedef struct D3D11WindowData
{ {
void* windowHandle; void* windowHandle;
uint8_t allowTearing;
D3D11SwapchainData *swapchainData; D3D11SwapchainData *swapchainData;
} D3D11WindowData; } D3D11WindowData;
@ -517,7 +518,8 @@ typedef struct D3D11Renderer
void *d3dcompiler_dll; void *d3dcompiler_dll;
uint8_t debugMode; uint8_t debugMode;
D3D_FEATURE_LEVEL featureLevel; /* FIXME: Do we need this? */ BOOL supportsTearing;
PFN_D3DCOMPILE D3DCompileFunc; PFN_D3DCOMPILE D3DCompileFunc;
D3D11WindowData **claimedWindows; D3D11WindowData **claimedWindows;
@ -3296,12 +3298,14 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture(
static uint8_t D3D11_INTERNAL_CreateSwapchain( static uint8_t D3D11_INTERNAL_CreateSwapchain(
D3D11Renderer *renderer, D3D11Renderer *renderer,
D3D11WindowData *windowData D3D11WindowData *windowData,
Refresh_PresentMode presentMode
) { ) {
SDL_SysWMinfo info; SDL_SysWMinfo info;
HWND dxgiHandle; HWND dxgiHandle;
int width, height; int width, height;
DXGI_SWAP_CHAIN_DESC swapchainDesc; DXGI_SWAP_CHAIN_DESC swapchainDesc;
IDXGIFactory4 *factory4;
IDXGIFactory1 *pParent; IDXGIFactory1 *pParent;
IDXGISwapChain *swapchain; IDXGISwapChain *swapchain;
D3D11SwapchainData *swapchainData; D3D11SwapchainData *swapchainData;
@ -3328,12 +3332,36 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain(
swapchainDesc.SampleDesc.Count = 1; swapchainDesc.SampleDesc.Count = 1;
swapchainDesc.SampleDesc.Quality = 0; swapchainDesc.SampleDesc.Quality = 0;
swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapchainDesc.BufferCount = 3; swapchainDesc.BufferCount = 2;
swapchainDesc.OutputWindow = dxgiHandle; swapchainDesc.OutputWindow = dxgiHandle;
swapchainDesc.Windowed = 1; swapchainDesc.Windowed = 1;
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
if (renderer->supportsTearing)
{
swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
}
else
{
swapchainDesc.Flags = 0; swapchainDesc.Flags = 0;
/* For Windows 10+, use a better form of discard swap behavior */
res = IDXGIFactory1_QueryInterface(
renderer->factory,
&D3D_IID_IDXGIFactory4,
&factory4
);
if (SUCCEEDED(res))
{
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
IDXGIFactory4_Release(factory4);
}
else
{
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
}
}
/* Create the swapchain! */ /* Create the swapchain! */
res = IDXGIFactory1_CreateSwapChain( res = IDXGIFactory1_CreateSwapChain(
(IDXGIFactory1*) renderer->factory, (IDXGIFactory1*) renderer->factory,
@ -3341,7 +3369,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain(
&swapchainDesc, &swapchainDesc,
&swapchain &swapchain
); );
ERROR_CHECK("Could not create swapchain"); ERROR_CHECK("Could not create swapchain", 0);
/* /*
* The swapchain's parent is a separate factory from the factory that * The swapchain's parent is a separate factory from the factory that
@ -3385,6 +3413,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain(
/* Create the swapchain data */ /* Create the swapchain data */
swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData)); swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData));
swapchainData->swapchain = swapchain; swapchainData->swapchain = swapchain;
swapchainData->presentMode = presentMode;
if (!D3D11_INTERNAL_InitializeSwapchainTexture( if (!D3D11_INTERNAL_InitializeSwapchainTexture(
renderer, renderer,
@ -3419,7 +3448,7 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain(
width, width,
height, height,
DXGI_FORMAT_UNKNOWN, /* Keep the old format */ DXGI_FORMAT_UNKNOWN, /* Keep the old format */
0 renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0
); );
ERROR_CHECK_RETURN("Could not resize swapchain buffers", 0); ERROR_CHECK_RETURN("Could not resize swapchain buffers", 0);
@ -3470,9 +3499,8 @@ static uint8_t D3D11_ClaimWindow(
{ {
windowData = (D3D11WindowData*) SDL_malloc(sizeof(D3D11WindowData)); windowData = (D3D11WindowData*) SDL_malloc(sizeof(D3D11WindowData));
windowData->windowHandle = windowHandle; windowData->windowHandle = windowHandle;
windowData->allowTearing = presentMode == REFRESH_PRESENTMODE_IMMEDIATE;
if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData)) if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData, presentMode))
{ {
SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_DATA, windowData); SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_DATA, windowData);
@ -3604,7 +3632,9 @@ static void D3D11_SetSwapchainPresentMode(
void *windowHandle, void *windowHandle,
Refresh_PresentMode presentMode Refresh_PresentMode presentMode
) { ) {
NOT_IMPLEMENTED D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle);
D3D11SwapchainData *swapchainData = windowData->swapchainData;
swapchainData->presentMode = presentMode;
} }
/* Submission and Fences */ /* Submission and Fences */
@ -3737,7 +3767,7 @@ static void D3D11_Submit(
ID3D11CommandList_Release(commandList); ID3D11CommandList_Release(commandList);
/* Mark the command buffer as submitted */ /* Mark the command buffer as submitted */
if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) if (renderer->submittedCommandBufferCount >= renderer->submittedCommandBufferCapacity)
{ {
renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1; renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
@ -3753,10 +3783,24 @@ static void D3D11_Submit(
/* Present, if applicable */ /* Present, if applicable */
if (d3d11CommandBuffer->swapchainData) if (d3d11CommandBuffer->swapchainData)
{ {
uint32_t syncInterval = 1;
if (d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE)
{
syncInterval = 0;
}
uint32_t presentFlags = 0;
if ( renderer->supportsTearing &&
(d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE ||
d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_FIFO_RELAXED)
) {
presentFlags = DXGI_PRESENT_ALLOW_TEARING;
}
IDXGISwapChain_Present( IDXGISwapChain_Present(
d3d11CommandBuffer->swapchainData->swapchain, d3d11CommandBuffer->swapchainData->swapchain,
1, /* FIXME: Assumes vsync! */ syncInterval,
0 presentFlags
); );
} }
@ -4040,6 +4084,7 @@ static Refresh_Device* D3D11_CreateDevice(
PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc; PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 }; D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 };
IDXGIFactory5 *factory5;
IDXGIFactory6 *factory6; IDXGIFactory6 *factory6;
uint32_t flags; uint32_t flags;
DXGI_ADAPTER_DESC1 adapterDesc; DXGI_ADAPTER_DESC1 adapterDesc;
@ -4094,7 +4139,28 @@ static Refresh_Device* D3D11_CreateDevice(
); );
ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL); ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL);
/* Get the default adapter */ /* Check for explicit tearing support */
res = IDXGIFactory1_QueryInterface(
renderer->factory,
&D3D_IID_IDXGIFactory5,
(void**) &factory5
);
if (SUCCEEDED(res))
{
res = IDXGIFactory5_CheckFeatureSupport(
factory5,
DXGI_FEATURE_PRESENT_ALLOW_TEARING,
&renderer->supportsTearing,
sizeof(renderer->supportsTearing)
);
if (FAILED(res))
{
renderer->supportsTearing = FALSE;
}
IDXGIFactory5_Release(factory5);
}
/* Select the appropriate device for rendering */
res = IDXGIAdapter1_QueryInterface( res = IDXGIAdapter1_QueryInterface(
renderer->factory, renderer->factory,
&D3D_IID_IDXGIFactory6, &D3D_IID_IDXGIFactory6,
@ -4109,6 +4175,7 @@ static Refresh_Device* D3D11_CreateDevice(
&D3D_IID_IDXGIAdapter1, &D3D_IID_IDXGIAdapter1,
&renderer->adapter &renderer->adapter
); );
IDXGIFactory6_Release(factory6);
} }
else else
{ {
@ -4166,7 +4233,7 @@ tryCreateDevice:
SDL_arraysize(levels), SDL_arraysize(levels),
D3D11_SDK_VERSION, D3D11_SDK_VERSION,
&d3d11Device, &d3d11Device,
&renderer->featureLevel, NULL,
&renderer->immediateContext &renderer->immediateContext
); );
if (FAILED(res) && debugMode) if (FAILED(res) && debugMode)

View File

@ -30,6 +30,8 @@ typedef HRESULT(WINAPI* PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID* riid, void** p
/* IIDs (from https://magnumdb.com) */ /* IIDs (from https://magnumdb.com) */
static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78,0xf26f,0x4dba,{0xa8,0x29,0x25,0x3c,0x83,0xd1,0xb3,0x87} }; static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78,0xf26f,0x4dba,{0xa8,0x29,0x25,0x3c,0x83,0xd1,0xb3,0x87} };
static const IID D3D_IID_IDXGIFactory4 = { 0x1bc6ea02,0xef36,0x464f,{0xbf,0x0c,0x21,0xca,0x39,0xe5,0x16,0x8a} };
static const IID D3D_IID_IDXGIFactory5 = { 0x7632e1f5,0xee65,0x4dca,{0x87,0xfd,0x84,0xcd,0x75,0xf8,0x83,0x8d} };
static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f,0xff09,0x44a9,{0xb0,0x3c,0x77,0x90,0x0a,0x0a,0x1d,0x17} }; static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f,0xff09,0x44a9,{0xb0,0x3c,0x77,0x90,0x0a,0x0a,0x1d,0x17} };
static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61,0x3839,0x4626,{0x91,0xfd,0x08,0x68,0x79,0x01,0x1a,0x05} }; static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61,0x3839,0x4626,{0x91,0xfd,0x08,0x68,0x79,0x01,0x1a,0x05} };
static const IID D3D_IID_ID3D11Texture2D = { 0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c} }; static const IID D3D_IID_ID3D11Texture2D = { 0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c} };