/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities * * Copyright (c) 2020 Evan Hemsley * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source distribution. * * Evan "cosmonaut" Hemsley * */ #if REFRESH_DRIVER_D3D11 #define D3D11_NO_HELPERS #define CINTERFACE #define COBJMACROS #include #include #include #include "Refresh_Driver.h" #include "Refresh_Driver_D3D11_cdefines.h" #include #include /* Defines */ #define D3D11_DLL "d3d11.dll" #define DXGI_DLL "dxgi.dll" #define WINDOW_SWAPCHAIN_DATA "Refresh_D3D11Swapchain" #define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!"); /* Macros */ #define ERROR_CHECK(msg) \ if (FAILED(res)) \ { \ D3D11_INTERNAL_LogError(renderer->device, msg, res); \ } #define ERROR_CHECK_RETURN(msg, ret) \ if (FAILED(res)) \ { \ D3D11_INTERNAL_LogError(renderer->device, msg, res); \ return ret; \ } /* D3DCompile signature */ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)( LPCVOID pSrcData, SIZE_T SrcDataSize, LPCSTR pSourceName, const D3D_SHADER_MACRO* pDefines, ID3DInclude* pInclude, LPCSTR pEntrypoint, LPCSTR pTarget, UINT Flags1, UINT Flags2, ID3DBlob **ppCode, ID3DBlob **ppErrorMsgs ); /* Conversions */ static DXGI_FORMAT RefreshToD3D11_SurfaceFormat[] = { DXGI_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */ DXGI_FORMAT_B8G8R8A8_UNORM, /* B8G8R8A8 */ DXGI_FORMAT_B5G6R5_UNORM, /* R5G6B5 */ DXGI_FORMAT_B5G5R5A1_UNORM, /* A1R5G5B5 */ DXGI_FORMAT_B4G4R4A4_UNORM, /* B4G4R4A4 */ DXGI_FORMAT_BC1_UNORM, /* BC1 */ DXGI_FORMAT_BC3_UNORM, /* BC3 */ DXGI_FORMAT_BC5_UNORM, /* BC5 */ DXGI_FORMAT_R8G8_SNORM, /* R8G8_SNORM */ DXGI_FORMAT_R8G8B8A8_SNORM, /* R8G8B8A8_SNORM */ DXGI_FORMAT_R10G10B10A2_UNORM, /* A2R10G10B10 */ DXGI_FORMAT_R16G16_UNORM, /* R16G16 */ DXGI_FORMAT_R16G16B16A16_UNORM, /* R16G16B16A16 */ DXGI_FORMAT_R8_UNORM, /* R8 */ DXGI_FORMAT_R32_FLOAT, /* R32_SFLOAT */ DXGI_FORMAT_R32G32_FLOAT, /* R32G32_SFLOAT */ DXGI_FORMAT_R32G32B32A32_FLOAT, /* R32G32B32A32_SFLOAT */ DXGI_FORMAT_R16_FLOAT, /* R16_SFLOAT */ DXGI_FORMAT_R16G16_FLOAT, /* R16G16_SFLOAT */ DXGI_FORMAT_R16G16B16A16_FLOAT, /* R16G16B16A16_SFLOAT */ DXGI_FORMAT_D16_UNORM, /* D16 */ DXGI_FORMAT_D32_FLOAT, /* D32 */ DXGI_FORMAT_D24_UNORM_S8_UINT, /* D16S8 */ DXGI_FORMAT_D32_FLOAT_S8X24_UINT/* D32S8 */ }; static DXGI_FORMAT RefreshToD3D11_VertexFormat[] = { DXGI_FORMAT_R32_UINT, /* UINT */ DXGI_FORMAT_R32_FLOAT, /* FLOAT */ DXGI_FORMAT_R32G32_FLOAT, /* VECTOR2 */ DXGI_FORMAT_R32G32B32_FLOAT, /* VECTOR3 */ DXGI_FORMAT_R32G32B32A32_FLOAT, /* VECTOR4 */ DXGI_FORMAT_R8G8B8A8_UNORM, /* COLOR */ DXGI_FORMAT_R8G8B8A8_UINT, /* BYTE4 */ DXGI_FORMAT_R16G16_SINT, /* SHORT2 */ DXGI_FORMAT_R16G16B16A16_SINT, /* SHORT4 */ DXGI_FORMAT_R16G16_SNORM, /* NORMALIZEDSHORT2 */ DXGI_FORMAT_R16G16B16A16_SNORM, /* NORMALIZEDSHORT4 */ DXGI_FORMAT_R16G16_FLOAT, /* HALFVECTOR2 */ DXGI_FORMAT_R16G16B16A16_FLOAT /* HALFVECTOR4 */ }; static DXGI_FORMAT RefreshToD3D11_IndexType[] = { DXGI_FORMAT_R16_UINT, /* 16BIT */ DXGI_FORMAT_R32_UINT /* 32BIT */ }; static D3D11_PRIMITIVE_TOPOLOGY RefreshToD3D11_PrimitiveType[] = { D3D_PRIMITIVE_TOPOLOGY_POINTLIST, /* POINTLIST */ D3D_PRIMITIVE_TOPOLOGY_LINELIST, /* LINELIST */ D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, /* LINESTRIP */ D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, /* TRIANGLELIST */ D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP /* TRIANGLESTRIP */ }; static D3D11_FILL_MODE RefreshToD3D11_PolygonMode[] = { D3D11_FILL_SOLID, /* FILL */ D3D11_FILL_WIREFRAME, /* LINE */ }; static D3D11_CULL_MODE RefreshToD3D11_CullMode[] = { D3D11_CULL_NONE, /* NONE */ D3D11_CULL_FRONT, /* FRONT */ D3D11_CULL_BACK /* BACK */ }; static D3D11_BLEND RefreshToD3D11_BlendFactor[] = { D3D11_BLEND_ZERO, /* ZERO */ D3D11_BLEND_ONE, /* ONE */ D3D11_BLEND_SRC_COLOR, /* SRC_COLOR */ D3D11_BLEND_INV_SRC_COLOR, /* ONE_MINUS_SRC_COLOR */ D3D11_BLEND_DEST_COLOR, /* DST_COLOR */ D3D11_BLEND_INV_DEST_COLOR, /* ONE_MINUS_DST_COLOR */ D3D11_BLEND_SRC_ALPHA, /* SRC_ALPHA */ D3D11_BLEND_INV_SRC_ALPHA, /* ONE_MINUS_SRC_ALPHA */ D3D11_BLEND_DEST_ALPHA, /* DST_ALPHA */ D3D11_BLEND_INV_DEST_ALPHA, /* ONE_MINUS_DST_ALPHA */ D3D11_BLEND_BLEND_FACTOR, /* CONSTANT_COLOR */ D3D11_BLEND_INV_BLEND_FACTOR, /* ONE_MINUS_CONSTANT_COLOR */ D3D11_BLEND_SRC_ALPHA_SAT, /* SRC_ALPHA_SATURATE */ }; static D3D11_BLEND_OP RefreshToD3D11_BlendOp[] = { D3D11_BLEND_OP_ADD, /* ADD */ D3D11_BLEND_OP_SUBTRACT, /* SUBTRACT */ D3D11_BLEND_OP_REV_SUBTRACT, /* REVERSE_SUBTRACT */ D3D11_BLEND_OP_MIN, /* MIN */ D3D11_BLEND_OP_MAX /* MAX */ }; static D3D11_COMPARISON_FUNC RefreshToD3D11_CompareOp[] = { D3D11_COMPARISON_NEVER, /* NEVER */ D3D11_COMPARISON_LESS, /* LESS */ D3D11_COMPARISON_EQUAL, /* EQUAL */ D3D11_COMPARISON_LESS_EQUAL, /* LESS_OR_EQUAL */ D3D11_COMPARISON_GREATER, /* GREATER */ D3D11_COMPARISON_NOT_EQUAL, /* NOT_EQUAL */ D3D11_COMPARISON_GREATER_EQUAL, /* GREATER_OR_EQUAL */ D3D11_COMPARISON_ALWAYS /* ALWAYS */ }; static D3D11_STENCIL_OP RefreshToD3D11_StencilOp[] = { D3D11_STENCIL_OP_KEEP, /* KEEP */ D3D11_STENCIL_OP_ZERO, /* ZERO */ D3D11_STENCIL_OP_REPLACE, /* REPLACE */ D3D11_STENCIL_OP_INCR_SAT, /* INCREMENT_AND_CLAMP */ D3D11_STENCIL_OP_DECR_SAT, /* DECREMENT_AND_CLAMP */ D3D11_STENCIL_OP_INVERT, /* INVERT */ D3D11_STENCIL_OP_INCR, /* INCREMENT_AND_WRAP */ D3D11_STENCIL_OP_DECR /* DECREMENT_AND_WRAP */ }; static int32_t RefreshToD3D11_SampleCount[] = { 1, /* 1 */ 2, /* 2 */ 4, /* 4 */ 8, /* 8 */ 16, /* 16 */ 32, /* 32 */ 64 /* 64 */ }; static D3D11_INPUT_CLASSIFICATION RefreshToD3D11_VertexInputRate[] = { D3D11_INPUT_PER_VERTEX_DATA, /* VERTEX */ D3D11_INPUT_PER_INSTANCE_DATA /* INSTANCE */ }; static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = { D3D11_TEXTURE_ADDRESS_WRAP, /* REPEAT */ D3D11_TEXTURE_ADDRESS_MIRROR, /* MIRRORED_REPEAT */ D3D11_TEXTURE_ADDRESS_CLAMP, /* CLAMP_TO_EDGE */ D3D11_TEXTURE_ADDRESS_BORDER /* CLAMP_TO_BORDER */ }; /* Structs */ typedef struct D3D11Texture { /* 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; D3D11Texture refreshTexture; void* windowHandle; } D3D11SwapchainData; typedef struct D3D11CommandBuffer { /* 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 { ID3D11Device *device; ID3D11DeviceContext *immediateContext; IDXGIFactory1 *factory; IDXGIAdapter1* adapter; void *d3d11_dll; void *dxgi_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; D3D_FEATURE_LEVEL featureLevel; PFN_D3DCOMPILE D3DCompileFunc; } D3D11Renderer; /* Logging */ static void D3D11_INTERNAL_LogError( ID3D11Device *device, const char *msg, HRESULT res ) { #define MAX_ERROR_LEN 1024 /* FIXME: Arbitrary! */ /* Buffer for text, ensure space for \0 terminator after buffer */ char wszMsgBuff[MAX_ERROR_LEN + 1]; DWORD dwChars; /* Number of chars returned. */ if (res == DXGI_ERROR_DEVICE_REMOVED) { res = ID3D11Device_GetDeviceRemovedReason(device); } /* Try to get the message from the system errors. */ dwChars = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, res, 0, wszMsgBuff, MAX_ERROR_LEN, NULL ); /* No message? Screw it, just post the code. */ if (dwChars == 0) { Refresh_LogError("%s! Error Code: 0x%08X", msg, res); return; } /* Ensure valid range */ dwChars = SDL_min(dwChars, MAX_ERROR_LEN); /* Trim whitespace from tail of message */ while (dwChars > 0) { if (wszMsgBuff[dwChars - 1] <= ' ') { dwChars--; } else { break; } } /* Ensure null-terminated string */ wszMsgBuff[dwChars] = '\0'; Refresh_LogError("%s! Error Code: %s (0x%08X)", msg, wszMsgBuff, res); } /* Quit */ static void D3D11_DestroyDevice( Refresh_Device *device ) { NOT_IMPLEMENTED } /* Drawing */ static void D3D11_DrawInstancedPrimitives( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, uint32_t baseVertex, uint32_t startIndex, uint32_t primitiveCount, uint32_t instanceCount, uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { NOT_IMPLEMENTED } static void D3D11_DrawIndexedPrimitives( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, uint32_t baseVertex, uint32_t startIndex, uint32_t primitiveCount, uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { NOT_IMPLEMENTED } static void D3D11_DrawPrimitives( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, uint32_t vertexStart, uint32_t primitiveCount, uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { NOT_IMPLEMENTED } static void D3D11_DrawPrimitivesIndirect( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Buffer *buffer, uint32_t offsetInBytes, uint32_t drawCount, uint32_t stride, uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { NOT_IMPLEMENTED } static void D3D11_DispatchCompute( Refresh_Renderer *device, Refresh_CommandBuffer *commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, uint32_t computeParamOffset ) { NOT_IMPLEMENTED } /* State Creation */ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_Renderer *driverData, Refresh_ComputeShaderInfo *computeShaderInfo ) { NOT_IMPLEMENTED return NULL; } static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( Refresh_Renderer *driverData, Refresh_GraphicsPipelineCreateInfo *pipelineCreateInfo ) { NOT_IMPLEMENTED return NULL; } static Refresh_Sampler* D3D11_CreateSampler( Refresh_Renderer *driverData, Refresh_SamplerStateCreateInfo *samplerStateCreateInfo ) { NOT_IMPLEMENTED return NULL; } static Refresh_ShaderModule* D3D11_CreateShaderModule( Refresh_Renderer *driverData, Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo ) { NOT_IMPLEMENTED return NULL; } static Refresh_Texture* D3D11_CreateTexture( Refresh_Renderer *driverData, Refresh_TextureCreateInfo *textureCreateInfo ) { NOT_IMPLEMENTED return NULL; } static Refresh_Buffer* D3D11_CreateBuffer( Refresh_Renderer *driverData, Refresh_BufferUsageFlags usageFlags, uint32_t sizeInBytes ) { NOT_IMPLEMENTED return NULL; } /* Setters */ static void D3D11_SetTextureData( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, void *data, uint32_t dataLengthInBytes ) { NOT_IMPLEMENTED } static void D3D11_SetTextureDataYUV( Refresh_Renderer *driverData, Refresh_CommandBuffer* commandBuffer, Refresh_Texture *y, Refresh_Texture *u, Refresh_Texture *v, uint32_t yWidth, uint32_t yHeight, uint32_t uvWidth, uint32_t uvHeight, void *yDataPtr, void *uDataPtr, void *vDataPtr, uint32_t yDataLength, uint32_t uvDataLength, uint32_t yStride, uint32_t uvStride ) { NOT_IMPLEMENTED } static void D3D11_CopyTextureToTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *sourceTextureSlice, Refresh_TextureSlice *destinationTextureSlice, Refresh_Filter filter ) { NOT_IMPLEMENTED } static void D3D11_CopyTextureToBuffer( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_Buffer *buffer ) { NOT_IMPLEMENTED } static void D3D11_SetBufferData( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Buffer *buffer, uint32_t offsetInBytes, void* data, uint32_t dataLength ) { NOT_IMPLEMENTED } static uint32_t D3D11_PushVertexShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *data, uint32_t dataLengthInBytes ) { NOT_IMPLEMENTED return 0; } static uint32_t D3D11_PushFragmentShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *data, uint32_t dataLengthInBytes ) { NOT_IMPLEMENTED return 0; } static uint32_t D3D11_PushComputeShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *data, uint32_t dataLengthInBytes ) { NOT_IMPLEMENTED return 0; } static void D3D11_BindVertexSamplers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Texture **pTextures, Refresh_Sampler **pSamplers ) { NOT_IMPLEMENTED } static void D3D11_BindFragmentSamplers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Texture **pTextures, Refresh_Sampler **pSamplers ) { NOT_IMPLEMENTED } /* Getters */ static void D3D11_GetBufferData( Refresh_Renderer *driverData, Refresh_Buffer *buffer, void *data, uint32_t dataLengthInBytes ) { NOT_IMPLEMENTED } /* Disposal */ static void D3D11_QueueDestroyTexture( Refresh_Renderer *driverData, Refresh_Texture *texture ) { NOT_IMPLEMENTED } static void D3D11_QueueDestroySampler( Refresh_Renderer *driverData, Refresh_Sampler *sampler ) { NOT_IMPLEMENTED } static void D3D11_QueueDestroyBuffer( Refresh_Renderer *driverData, Refresh_Buffer *buffer ) { NOT_IMPLEMENTED } static void D3D11_QueueDestroyShaderModule( Refresh_Renderer *driverData, Refresh_ShaderModule *shaderModule ) { NOT_IMPLEMENTED } static void D3D11_QueueDestroyComputePipeline( Refresh_Renderer *driverData, Refresh_ComputePipeline *computePipeline ) { NOT_IMPLEMENTED } static void D3D11_QueueDestroyGraphicsPipeline( Refresh_Renderer *driverData, Refresh_GraphicsPipeline *graphicsPipeline ) { NOT_IMPLEMENTED } /* Graphics State */ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( Refresh_Renderer *driverData ) { NOT_IMPLEMENTED return NULL; } static void D3D11_BeginRenderPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_ColorAttachmentInfo *colorAttachmentInfos, uint32_t colorAttachmentCount, Refresh_DepthStencilAttachmentInfo *depthStencilAttachmentInfo ) { NOT_IMPLEMENTED } static void D3D11_EndRenderPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer ) { NOT_IMPLEMENTED } static void D3D11_BindGraphicsPipeline( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_GraphicsPipeline *graphicsPipeline ) { NOT_IMPLEMENTED } static void D3D11_SetViewport( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Viewport *viewport ) { NOT_IMPLEMENTED } static void D3D11_SetScissor( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Rect *scissor ) { NOT_IMPLEMENTED } static void D3D11_BindVertexBuffers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, uint32_t firstBinding, uint32_t bindingCount, Refresh_Buffer **pBuffers, uint64_t *pOffsets ) { NOT_IMPLEMENTED } static void D3D11_BindIndexBuffer( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Buffer *buffer, uint64_t offset, Refresh_IndexElementSize indexElementSize ) { NOT_IMPLEMENTED } /* Compute State */ static void D3D11_BindComputePipeline( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_ComputePipeline *computePipeline ) { NOT_IMPLEMENTED } static void D3D11_BindComputeBuffers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Buffer **pBuffers ) { NOT_IMPLEMENTED } static void D3D11_BindComputeTextures( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_Texture **pTextures ) { NOT_IMPLEMENTED } /* Window and Swapchain Management */ static uint8_t D3D11_ClaimWindow( Refresh_Renderer *driverData, void *windowHandle, Refresh_PresentMode presentMode ) { NOT_IMPLEMENTED return 0; } static uint8_t D3D11_UnclaimWindow( Refresh_Renderer *driverData, void *windowHandle ) { NOT_IMPLEMENTED return 0; } static Refresh_Texture* D3D11_AcquireSwapchainTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *windowHandle, uint32_t *pWidth, uint32_t *pHeight ) { NOT_IMPLEMENTED return NULL; } static Refresh_TextureFormat D3D11_GetSwapchainFormat( Refresh_Renderer *driverData, void *windowHandle ) { NOT_IMPLEMENTED return REFRESH_TEXTUREFORMAT_R8G8B8A8; } static void D3D11_SetSwapchainPresentMode( Refresh_Renderer *driverData, void *windowHandle, Refresh_PresentMode presentMode ) { NOT_IMPLEMENTED } /* Submission and Fences */ static void D3D11_Submit( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer ) { NOT_IMPLEMENTED } static Refresh_Fence* D3D11_SubmitAndAcquireFence( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer ) { NOT_IMPLEMENTED return NULL; } static void D3D11_Wait( Refresh_Renderer *driverData ) { NOT_IMPLEMENTED } static void D3D11_WaitForFences( Refresh_Renderer *driverData, uint8_t waitAll, uint32_t fenceCount, Refresh_Fence **pFences ) { NOT_IMPLEMENTED } static int D3D11_QueryFence( Refresh_Renderer *driverData, Refresh_Fence *fence ) { NOT_IMPLEMENTED return 0; } static void D3D11_ReleaseFence( Refresh_Renderer *driverData, Refresh_Fence *fence ) { NOT_IMPLEMENTED } /* Device Creation */ static uint8_t D3D11_PrepareDriver( uint32_t *flags ) { /* Nothing to do here. */ return 1; } static Refresh_Device* D3D11_CreateDevice( uint8_t debugMode ) { D3D11Renderer *renderer; PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 }; void* factory6; uint32_t flags; DXGI_ADAPTER_DESC1 adapterDesc; HRESULT res; Refresh_Device* result; /* Allocate and zero out the renderer */ renderer = (D3D11Renderer*) SDL_calloc(1, sizeof(D3D11Renderer)); /* Load the D3DCompiler library */ renderer->d3dcompiler_dll = SDL_LoadObject(D3DCOMPILER_DLL); if (renderer->d3dcompiler_dll == NULL) { Refresh_LogError("Could not find " D3DCOMPILER_DLL); return NULL; } /* Load the D3DCompile function pointer */ renderer->D3DCompileFunc = (PFN_D3DCOMPILE) SDL_LoadFunction( renderer->d3dcompiler_dll, "D3DCompile" ); if (renderer->D3DCompileFunc == NULL) { Refresh_LogError("Could not load D3DCompile function!"); return NULL; } /* Load the DXGI library */ renderer->dxgi_dll = SDL_LoadObject(DXGI_DLL); if (renderer->dxgi_dll == NULL) { Refresh_LogError("Could not find " DXGI_DLL); return NULL; } /* Load the CreateDXGIFactory function */ CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY) SDL_LoadFunction( renderer->dxgi_dll, "CreateDXGIFactory1" ); if (CreateDXGIFactoryFunc == NULL) { Refresh_LogError("Could not load CreateDXGIFactory1 function!"); return NULL; } /* Create the DXGI factory */ res = CreateDXGIFactoryFunc( &D3D_IID_IDXGIFactory1, &renderer->factory ); ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL); /* Get the default adapter */ res = IDXGIAdapter1_QueryInterface( renderer->factory, &D3D_IID_IDXGIFactory6, (void**) &factory6 ); if (SUCCEEDED(res)) { IDXGIFactory6_EnumAdapterByGpuPreference( (IDXGIFactory6*) factory6, 0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, &D3D_IID_IDXGIAdapter1, &renderer->adapter ); } else { IDXGIFactory1_EnumAdapters1( renderer->factory, 0, &renderer->adapter ); } /* Get information about the selected adapter. Used for logging info. */ IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc); /* Load the D3D library */ renderer->d3d11_dll = SDL_LoadObject(D3D11_DLL); if (renderer->d3d11_dll == NULL) { Refresh_LogError("Could not find " D3D11_DLL); return NULL; } /* Load the CreateDevice function */ D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE) SDL_LoadFunction( renderer->d3d11_dll, "D3D11CreateDevice" ); if (D3D11CreateDeviceFunc == NULL) { Refresh_LogError("Could not load D3D11CreateDevice function!"); return NULL; } /* Set up device flags */ flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; if (debugMode) { flags |= D3D11_CREATE_DEVICE_DEBUG; } /* Create the device */ tryCreateDevice: res = D3D11CreateDeviceFunc( (IDXGIAdapter*)renderer->adapter, D3D_DRIVER_TYPE_UNKNOWN, /* Must be UNKNOWN if adapter is non-null according to spec */ NULL, flags, levels, SDL_arraysize(levels), D3D11_SDK_VERSION, &renderer->device, &renderer->featureLevel, &renderer->immediateContext ); if (FAILED(res) && debugMode) { /* If device creation failed, and we're in debug mode, remove the debug flag and try again. */ Refresh_LogWarn("Creating device in debug mode failed with error %08X. Trying non-debug.", res); flags &= ~D3D11_CREATE_DEVICE_DEBUG; debugMode = 0; goto tryCreateDevice; } ERROR_CHECK_RETURN("Could not create D3D11 device", NULL); /* Print driver info */ Refresh_LogInfo("Refresh Driver: D3D11"); 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 */ 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 */ result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); ASSIGN_DRIVER(D3D11) result->driverData = (Refresh_Renderer*) renderer; return result; } Refresh_Driver D3D11Driver = { "D3D11", D3D11_PrepareDriver, D3D11_CreateDevice }; #endif //REFRESH_DRIVER_D3D11