Compare commits

..

2 Commits

2 changed files with 309 additions and 145 deletions

View File

@ -43,7 +43,10 @@
#define D3D11_DLL "d3d11.dll" #define D3D11_DLL "d3d11.dll"
#define DXGI_DLL "dxgi.dll" #define DXGI_DLL "dxgi.dll"
#define WINDOW_SWAPCHAIN_DATA "Refresh_D3D11Swapchain" #define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice"
#define D3DCOMPILE_FUNC "D3DCompile"
#define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1"
#define WINDOW_DATA "Refresh_D3D11WindowData"
#define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!"); #define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!");
@ -80,7 +83,7 @@ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)(
/* Conversions */ /* Conversions */
static DXGI_FORMAT RefreshToD3D11_SurfaceFormat[] = static DXGI_FORMAT RefreshToD3D11_TextureFormat[] =
{ {
DXGI_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */ DXGI_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */
DXGI_FORMAT_B8G8R8A8_UNORM, /* B8G8R8A8 */ DXGI_FORMAT_B8G8R8A8_UNORM, /* B8G8R8A8 */
@ -230,109 +233,18 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] =
/* Structs */ /* Structs */
typedef struct D3D11Texture typedef struct SwapchainData
{
/* D3D Handles */
ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */
ID3D11ShaderResourceView *shaderView;
/* Basic Info */
int32_t levelCount;
uint8_t isRenderTarget;
/* Dimensions */
#define REFRESH_D3D11_RENDERTARGET_2D 0
#define REFRESH_D3D11_RENDERTARGET_3D 1
#define REFRESH_D3D11_RENDERTARGET_CUBE 2
uint8_t rtType;
REFRESHNAMELESS union
{
struct
{
int32_t width;
int32_t height;
ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */
} twod;
struct
{
int32_t width;
int32_t height;
int32_t depth;
} threed;
struct
{
int32_t size;
ID3D11RenderTargetView **rtViews;
} cube;
};
} D3D11Texture;
typedef struct D3D11Buffer
{
ID3D11Buffer *handle;
} D3D11Buffer;
typedef struct D3D11SwapchainData
{ {
IDXGISwapChain *swapchain; IDXGISwapChain *swapchain;
D3D11Texture refreshTexture; ID3D11RenderTargetView *swapchainRTView;
} SwapchainData;
typedef struct WindowData
{
void* windowHandle; void* windowHandle;
} D3D11SwapchainData; uint8_t allowTearing;
SwapchainData *swapchainData;
typedef struct D3D11CommandBuffer } WindowData;
{
/* D3D11 Object References */
ID3D11DeviceContext *context;
ID3D11CommandList *commandList;
D3D11SwapchainData *swapchainData;
/* Render Pass */
uint8_t numBoundColorAttachments;
ID3D11RenderTargetView *rtViews[MAX_COLOR_TARGET_BINDINGS];
ID3D11DepthStencilView* dsView;
/* State */
SDL_threadID threadID;
uint8_t recording;
} D3D11CommandBuffer;
typedef struct D3D11CommandBufferPool
{
D3D11CommandBuffer **elements;
uint32_t count;
uint32_t capacity;
} D3D11CommandBufferPool;
typedef struct D3D11ShaderModule
{
ID3D11DeviceChild *shader; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */
ID3D10Blob *blob;
char *shaderSource;
size_t shaderSourceLength;
} D3D11ShaderModule;
typedef struct D3D11GraphicsPipeline
{
float blendConstants[4];
int32_t numColorAttachments;
int32_t colorAttachmentSampleCounts[MAX_COLOR_TARGET_BINDINGS];
DXGI_FORMAT colorAttachmentFormats[MAX_COLOR_TARGET_BINDINGS];
ID3D11BlendState *colorAttachmentBlendState;
uint8_t hasDepthStencilAttachment;
DXGI_FORMAT depthStencilAttachmentFormat;
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology;
uint32_t stencilRef;
ID3D11DepthStencilState *depthStencilState;
ID3D11RasterizerState *rasterizerState;
ID3D11InputLayout *inputLayout;
Refresh_MultisampleState multisampleState;
ID3D11VertexShader *vertexShader;
ID3D11PixelShader *fragmentShader;
} D3D11GraphicsPipeline;
typedef struct D3D11Renderer typedef struct D3D11Renderer
{ {
@ -343,20 +255,14 @@ typedef struct D3D11Renderer
void *d3d11_dll; void *d3d11_dll;
void *dxgi_dll; void *dxgi_dll;
void *d3dcompiler_dll; void *d3dcompiler_dll;
SDL_mutex *contextLock;
D3D11CommandBufferPool *commandBufferPool;
SDL_mutex *commandBufferAcquisitionMutex;
D3D11SwapchainData** swapchainDatas;
uint32_t swapchainDataCount;
uint32_t swapchainDataCapacity;
Refresh_Vec4 blendFactor;
uint8_t debugMode; uint8_t debugMode;
D3D_FEATURE_LEVEL featureLevel; D3D_FEATURE_LEVEL featureLevel; /* FIXME: Do we need this? */
PFN_D3DCOMPILE D3DCompileFunc; PFN_D3DCOMPILE D3DCompileFunc;
WindowData **claimedWindows;
uint32_t claimedWindowCount;
uint32_t claimedWindowCapacity;
} D3D11Renderer; } D3D11Renderer;
/* Logging */ /* Logging */
@ -804,14 +710,196 @@ static void D3D11_BindComputeTextures(
/* Window and Swapchain Management */ /* Window and Swapchain Management */
static WindowData* D3D11_INTERNAL_FetchWindowData(
void *windowHandle
) {
return (WindowData*) SDL_GetWindowData(windowHandle, WINDOW_DATA);
}
static void D3D11_INTERNAL_ResolveSwapChainModeDescription(
IUnknown *device,
IDXGIAdapter *adapter,
IDXGIFactory1 *factory,
HWND window,
DXGI_MODE_DESC *modeDescription,
DXGI_MODE_DESC *swapChainDescription
) {
HMONITOR monitor;
int iAdapter = 0, iOutput;
IDXGIAdapter1* pAdapter;
IDXGIOutput *output;
DXGI_OUTPUT_DESC description;
/* Find the output (on any adapter) attached to the monitor that holds our window */
monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
while (SUCCEEDED(IDXGIFactory1_EnumAdapters1(factory, iAdapter++, &pAdapter)))
{
iOutput = 0;
while (SUCCEEDED(IDXGIAdapter_EnumOutputs(pAdapter, iOutput++, &output)))
{
IDXGIOutput_GetDesc(output, &description);
if (description.Monitor == monitor)
{
if (SUCCEEDED(IDXGIOutput_FindClosestMatchingMode(output, modeDescription, swapChainDescription, device)))
{
IDXGIOutput_Release(output);
IDXGIAdapter1_Release(pAdapter);
return;
}
}
IDXGIOutput_Release(output);
}
IDXGIAdapter1_Release(pAdapter);
}
}
static uint8_t D3D11_INTERNAL_CreateSwapchain(
D3D11Renderer *renderer,
WindowData *windowData
) {
SDL_SysWMinfo info;
HWND dxgiHandle;
DXGI_MODE_DESC swapchainBufferDesc;
DXGI_SWAP_CHAIN_DESC swapchainDesc;
IDXGIFactory1 *pParent;
IDXGISwapChain *swapchain;
SwapchainData *swapchainData;
HRESULT res;
/* Get the DXGI handle */
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo((SDL_Window*) windowData->windowHandle, &info);
dxgiHandle = info.info.win.window;
/* Initialize the swapchain buffer descriptor */
swapchainBufferDesc.Width = 0;
swapchainBufferDesc.Height = 0;
swapchainBufferDesc.RefreshRate.Numerator = 0;
swapchainBufferDesc.RefreshRate.Denominator = 0;
swapchainBufferDesc.Format = RefreshToD3D11_TextureFormat[REFRESH_TEXTUREFORMAT_R8G8B8A8];
swapchainBufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapchainBufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
/* Get the closest matching mode we can from the current monitor */
D3D11_INTERNAL_ResolveSwapChainModeDescription(
(IUnknown*) renderer->device,
(IDXGIAdapter*) renderer->adapter,
(IDXGIFactory1*) renderer->factory,
dxgiHandle,
&swapchainBufferDesc,
&swapchainDesc.BufferDesc
);
/* Initialize the swapchain descriptor */
swapchainDesc.BufferDesc = swapchainBufferDesc; /* FIXME: I think this is wrong, and it's wrong in FNA3D too! */
swapchainDesc.SampleDesc.Count = 1;
swapchainDesc.SampleDesc.Quality = 0;
swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapchainDesc.BufferCount = 3;
swapchainDesc.OutputWindow = dxgiHandle;
swapchainDesc.Windowed = 1;
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapchainDesc.Flags = 0;
/* Create the swapchain! */
res = IDXGIFactory1_CreateSwapChain(
(IDXGIFactory1*) renderer->factory,
(IUnknown*) renderer->device,
&swapchainDesc,
&swapchain
);
ERROR_CHECK("Could not create swapchain");
/*
* The swapchain's parent is a separate factory from the factory that
* we used to create the swapchain, and only that parent can be used to
* set the window association. Trying to set an association on our factory
* will silently fail and doesn't even verify arguments or return errors.
* See https://gamedev.net/forums/topic/634235-dxgidisabling-altenter/4999955/
*/
res = IDXGISwapChain_GetParent(
swapchain,
&D3D_IID_IDXGIFactory1,
(void**) &pParent
);
if (FAILED(res))
{
Refresh_LogWarn(
"Could not get swapchain parent! Error Code: %08X",
res
);
}
else
{
/* Disable DXGI window crap */
res = IDXGIFactory1_MakeWindowAssociation(
pParent,
dxgiHandle,
DXGI_MWA_NO_WINDOW_CHANGES
);
if (FAILED(res))
{
Refresh_LogWarn(
"MakeWindowAssociation failed! Error Code: %08X",
res
);
}
}
/* Create the swapchain data */
swapchainData = (SwapchainData*) SDL_malloc(sizeof(SwapchainData));
swapchainData->swapchain = swapchain;
swapchainData->swapchainRTView = NULL;
windowData->swapchainData = swapchainData;
return 1;
}
static uint8_t D3D11_ClaimWindow( static uint8_t D3D11_ClaimWindow(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
void *windowHandle, void *windowHandle,
Refresh_PresentMode presentMode Refresh_PresentMode presentMode
) { ) {
NOT_IMPLEMENTED D3D11Renderer *renderer = (D3D11Renderer*) driverData;
WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle);
if (windowData == NULL)
{
windowData = (WindowData*) SDL_malloc(sizeof(WindowData));
windowData->windowHandle = windowHandle;
windowData->allowTearing = presentMode == REFRESH_PRESENTMODE_IMMEDIATE;
if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData))
{
SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_DATA, windowData);
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity)
{
renderer->claimedWindowCapacity *= 2;
renderer->claimedWindows = SDL_realloc(
renderer->claimedWindows,
renderer->claimedWindowCapacity * sizeof(WindowData*)
);
}
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
renderer->claimedWindowCount += 1;
return 1;
}
else
{
Refresh_LogError("Could not create swapchain, failed to claim window!");
SDL_free(windowData);
return 0; return 0;
} }
}
else
{
Refresh_LogWarn("Window already claimed!");
return 0;
}
}
static uint8_t D3D11_UnclaimWindow( static uint8_t D3D11_UnclaimWindow(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
@ -836,7 +924,6 @@ static Refresh_TextureFormat D3D11_GetSwapchainFormat(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
void *windowHandle void *windowHandle
) { ) {
NOT_IMPLEMENTED
return REFRESH_TEXTUREFORMAT_R8G8B8A8; return REFRESH_TEXTUREFORMAT_R8G8B8A8;
} }
@ -900,7 +987,99 @@ static void D3D11_ReleaseFence(
static uint8_t D3D11_PrepareDriver( static uint8_t D3D11_PrepareDriver(
uint32_t *flags uint32_t *flags
) { ) {
/* Nothing to do here. */ void *d3d11_dll, *d3dcompiler_dll, *dxgi_dll;
PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 };
PFN_D3DCOMPILE D3DCompileFunc;
PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
HRESULT res;
/* Can we load D3D11? */
d3d11_dll = SDL_LoadObject(D3D11_DLL);
if (d3d11_dll == NULL)
{
Refresh_LogWarn("D3D11: Could not find " D3D11_DLL);
return 0;
}
D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE) SDL_LoadFunction(
d3d11_dll,
D3D11_CREATE_DEVICE_FUNC
);
if (D3D11CreateDeviceFunc == NULL)
{
Refresh_LogWarn("D3D11: Could not find function " D3D11_CREATE_DEVICE_FUNC " in " D3D11_DLL);
SDL_UnloadObject(d3d11_dll);
return 0;
}
/* Can we create a device? */
res = D3D11CreateDeviceFunc(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
levels,
SDL_arraysize(levels),
D3D11_SDK_VERSION,
NULL,
NULL,
NULL
);
SDL_UnloadObject(d3d11_dll);
if (FAILED(res))
{
Refresh_LogWarn("D3D11: Could not create D3D11Device with feature level 11_0");
return 0;
}
/* Can we load D3DCompiler? */
d3dcompiler_dll = SDL_LoadObject(D3DCOMPILER_DLL);
if (d3dcompiler_dll == NULL)
{
Refresh_LogWarn("D3D11: Could not find " D3DCOMPILER_DLL);
return 0;
}
D3DCompileFunc = (PFN_D3DCOMPILE) SDL_LoadFunction(
d3dcompiler_dll,
D3DCOMPILE_FUNC
);
SDL_UnloadObject(d3dcompiler_dll); /* We're not going to call this function, so we can just unload now. */
if (D3DCompileFunc == NULL)
{
Refresh_LogWarn("D3D11: Could not find function " D3DCOMPILE_FUNC " in " D3DCOMPILER_DLL);
return 0;
}
/* Can we load DXGI? */
dxgi_dll = SDL_LoadObject(DXGI_DLL);
if (dxgi_dll == NULL)
{
Refresh_LogWarn("D3D11: Could not find " DXGI_DLL);
return 0;
}
CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1) SDL_LoadFunction(
dxgi_dll,
CREATE_DXGI_FACTORY1_FUNC
);
SDL_UnloadObject(dxgi_dll); /* We're not going to call this function, so we can just unload now. */
if (CreateDXGIFactoryFunc == NULL)
{
Refresh_LogWarn("D3D11: Could not find function " CREATE_DXGI_FACTORY1_FUNC " in " DXGI_DLL);
return 0;
}
/* No window flags required */
SDL_SetHint(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, "1");
return 1; return 1;
} }
@ -908,10 +1087,10 @@ static Refresh_Device* D3D11_CreateDevice(
uint8_t debugMode uint8_t debugMode
) { ) {
D3D11Renderer *renderer; D3D11Renderer *renderer;
PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc; PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 }; D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 };
void* factory6; IDXGIFactory6 *factory6;
uint32_t flags; uint32_t flags;
DXGI_ADAPTER_DESC1 adapterDesc; DXGI_ADAPTER_DESC1 adapterDesc;
HRESULT res; HRESULT res;
@ -931,11 +1110,11 @@ static Refresh_Device* D3D11_CreateDevice(
/* Load the D3DCompile function pointer */ /* Load the D3DCompile function pointer */
renderer->D3DCompileFunc = (PFN_D3DCOMPILE) SDL_LoadFunction( renderer->D3DCompileFunc = (PFN_D3DCOMPILE) SDL_LoadFunction(
renderer->d3dcompiler_dll, renderer->d3dcompiler_dll,
"D3DCompile" D3DCOMPILE_FUNC
); );
if (renderer->D3DCompileFunc == NULL) if (renderer->D3DCompileFunc == NULL)
{ {
Refresh_LogError("Could not load D3DCompile function!"); Refresh_LogError("Could not load function: " D3DCOMPILE_FUNC);
return NULL; return NULL;
} }
@ -947,14 +1126,14 @@ static Refresh_Device* D3D11_CreateDevice(
return NULL; return NULL;
} }
/* Load the CreateDXGIFactory function */ /* Load the CreateDXGIFactory1 function */
CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY) SDL_LoadFunction( CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1) SDL_LoadFunction(
renderer->dxgi_dll, renderer->dxgi_dll,
"CreateDXGIFactory1" CREATE_DXGI_FACTORY1_FUNC
); );
if (CreateDXGIFactoryFunc == NULL) if (CreateDXGIFactoryFunc == NULL)
{ {
Refresh_LogError("Could not load CreateDXGIFactory1 function!"); Refresh_LogError("Could not load function: " CREATE_DXGI_FACTORY1_FUNC);
return NULL; return NULL;
} }
@ -974,7 +1153,7 @@ static Refresh_Device* D3D11_CreateDevice(
if (SUCCEEDED(res)) if (SUCCEEDED(res))
{ {
IDXGIFactory6_EnumAdapterByGpuPreference( IDXGIFactory6_EnumAdapterByGpuPreference(
(IDXGIFactory6*) factory6, factory6,
0, 0,
DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
&D3D_IID_IDXGIAdapter1, &D3D_IID_IDXGIAdapter1,
@ -1004,11 +1183,11 @@ static Refresh_Device* D3D11_CreateDevice(
/* Load the CreateDevice function */ /* Load the CreateDevice function */
D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE) SDL_LoadFunction( D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE) SDL_LoadFunction(
renderer->d3d11_dll, renderer->d3d11_dll,
"D3D11CreateDevice" D3D11_CREATE_DEVICE_FUNC
); );
if (D3D11CreateDeviceFunc == NULL) if (D3D11CreateDeviceFunc == NULL)
{ {
Refresh_LogError("Could not load D3D11CreateDevice function!"); Refresh_LogError("Could not load function: " D3D11_CREATE_DEVICE_FUNC);
return NULL; return NULL;
} }
@ -1048,27 +1227,12 @@ tryCreateDevice:
Refresh_LogInfo("Refresh Driver: D3D11"); Refresh_LogInfo("Refresh Driver: D3D11");
Refresh_LogInfo("D3D11 Adapter: %S", adapterDesc.Description); Refresh_LogInfo("D3D11 Adapter: %S", adapterDesc.Description);
/* Create the command buffer pool */
renderer->commandBufferPool = (D3D11CommandBufferPool*) SDL_calloc(
1,
sizeof(D3D11CommandBufferPool)
);
/* Create mutexes */
renderer->contextLock = SDL_CreateMutex();
renderer->commandBufferAcquisitionMutex = SDL_CreateMutex();
/* Initialize miscellaneous renderer members */ /* Initialize miscellaneous renderer members */
renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG);
renderer->blendFactor.x = 1.0f;
renderer->blendFactor.y = 1.0f;
renderer->blendFactor.z = 1.0f;
renderer->blendFactor.w = 1.0f;
/* Create the Refresh Device */ /* Create the Refresh Device */
result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device));
ASSIGN_DRIVER(D3D11) ASSIGN_DRIVER(D3D11)
result->driverData = (Refresh_Renderer*) renderer; result->driverData = (Refresh_Renderer*) renderer;
return result; return result;

View File

@ -25,7 +25,7 @@
*/ */
/* Function Pointer Signatures */ /* Function Pointer Signatures */
typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY)(const GUID* riid, void** ppFactory); typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY1)(const GUID* riid, void** ppFactory);
/* IIDs (from https://magnumdb.com) */ /* IIDs (from https://magnumdb.com) */