From 547ed523055408c08cee59b4d9ca58a9539dfe04 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 22 Sep 2023 20:44:20 -0500 Subject: [PATCH 01/69] Groundwork for D3D11. Yoinked most of this from the prior work, but updated the ABI --- CMakeLists.txt | 7 + include/Refresh.h | 1 + src/Refresh.c | 7 + src/Refresh_Driver.h | 1 + src/Refresh_Driver_D3D11.c | 1083 +++++++++++++++++++++++++++ src/Refresh_Driver_D3D11_cdefines.h | 215 ++++++ visualc/Refresh.vcxproj | 6 +- visualc/Refresh.vcxproj.filters | 6 + 8 files changed, 1324 insertions(+), 2 deletions(-) create mode 100644 src/Refresh_Driver_D3D11.c create mode 100644 src/Refresh_Driver_D3D11_cdefines.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7095da0..ab91e45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,12 @@ add_definitions( -DREFRESH_DRIVER_VULKAN ) +if (WIN32) + add_definitions( + -DREFRESH_DRIVER_D3D11 + ) +endif() + # Source lists add_library(Refresh # Public Headers @@ -51,6 +57,7 @@ add_library(Refresh src/Refresh_Driver_Vulkan_vkfuncs.h # Source Files src/Refresh.c + src/Refresh_Driver_D3D11.c src/Refresh_Driver_Vulkan.c src/Refresh_Image.c ) diff --git a/include/Refresh.h b/include/Refresh.h index 9c173bb..a7338d8 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -330,6 +330,7 @@ typedef enum Refresh_Backend { REFRESH_BACKEND_DONTCARE, REFRESH_BACKEND_VULKAN, + REFRESH_BACKEND_D3D11, REFRESH_BACKEND_PS5, REFRESH_BACKEND_INVALID } Refresh_Backend; diff --git a/src/Refresh.c b/src/Refresh.c index ec8d7cd..b495fd2 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -39,6 +39,12 @@ #define VULKAN_DRIVER NULL #endif +#ifdef REFRESH_DRIVER_D3D11 + #define D3D11_DRIVER &D3D11Driver +#else + #define D3D11_DRIVER NULL +#endif + #ifdef REFRESH_DRIVER_PS5 #define PS5_DRIVER &PS5Driver #else @@ -47,6 +53,7 @@ static const Refresh_Driver *backends[] = { NULL, + D3D11_DRIVER, VULKAN_DRIVER, PS5_DRIVER }; diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index 5605d86..679539d 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -597,6 +597,7 @@ typedef struct Refresh_Driver } Refresh_Driver; extern Refresh_Driver VulkanDriver; +extern Refresh_Driver D3D11Driver; extern Refresh_Driver PS5Driver; #endif /* REFRESH_DRIVER_H */ diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c new file mode 100644 index 0000000..5d5e8b9 --- /dev/null +++ b/src/Refresh_Driver_D3D11.c @@ -0,0 +1,1083 @@ +/* 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 diff --git a/src/Refresh_Driver_D3D11_cdefines.h b/src/Refresh_Driver_D3D11_cdefines.h new file mode 100644 index 0000000..e269212 --- /dev/null +++ b/src/Refresh_Driver_D3D11_cdefines.h @@ -0,0 +1,215 @@ +/* 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 + * + */ + +/* Function Pointer Signatures */ +typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY)(const GUID* riid, void** ppFactory); + + /* 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_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_ID3D11Texture2D = { 0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c} }; + +/* IDXGIFactory6 (taken from dxgi1_6.h, cleaned up a bit) */ +typedef enum +{ + DXGI_FEATURE_PRESENT_ALLOW_TEARING = 0 +} DXGI_FEATURE; + +typedef enum +{ + DXGI_GPU_PREFERENCE_UNSPECIFIED = 0, + DXGI_GPU_PREFERENCE_MINIMUM_POWER = (DXGI_GPU_PREFERENCE_UNSPECIFIED + 1), + DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE = (DXGI_GPU_PREFERENCE_MINIMUM_POWER + 1) +} DXGI_GPU_PREFERENCE; + +typedef struct IDXGIFactory6 IDXGIFactory6; +typedef struct IDXGIFactory6Vtbl +{ + HRESULT(STDMETHODCALLTYPE* QueryInterface)( + IDXGIFactory6* This, + REFIID riid, + void** ppvObject); + + ULONG(STDMETHODCALLTYPE* AddRef)( + IDXGIFactory6* This); + + ULONG(STDMETHODCALLTYPE* Release)( + IDXGIFactory6* This); + + HRESULT(STDMETHODCALLTYPE* SetPrivateData)( + IDXGIFactory6* This, + REFGUID Name, + UINT DataSize, + const void* pData); + + HRESULT(STDMETHODCALLTYPE* SetPrivateDataInterface)( + IDXGIFactory6* This, + REFGUID Name, + const IUnknown* pUnknown); + + HRESULT(STDMETHODCALLTYPE* GetPrivateData)( + IDXGIFactory6* This, + REFGUID Name, + UINT* pDataSize, + void* pData); + + HRESULT(STDMETHODCALLTYPE* GetParent)( + IDXGIFactory6* This, + REFIID riid, + void** ppParent); + + HRESULT(STDMETHODCALLTYPE* EnumAdapters)( + IDXGIFactory6* This, + UINT Adapter, + IDXGIAdapter** ppAdapter); + + HRESULT(STDMETHODCALLTYPE* MakeWindowAssociation)( + IDXGIFactory6* This, + HWND WindowHandle, + UINT Flags); + + HRESULT(STDMETHODCALLTYPE* GetWindowAssociation)( + IDXGIFactory6* This, + HWND* pWindowHandle); + + HRESULT(STDMETHODCALLTYPE* CreateSwapChain)( + IDXGIFactory6* This, + IUnknown* pDevice, + DXGI_SWAP_CHAIN_DESC* pDesc, + IDXGISwapChain** ppSwapChain); + + HRESULT(STDMETHODCALLTYPE* CreateSoftwareAdapter)( + IDXGIFactory6* This, + HMODULE Module, + IDXGIAdapter** ppAdapter); + + HRESULT(STDMETHODCALLTYPE* EnumAdapters1)( + IDXGIFactory6* This, + UINT Adapter, + IDXGIAdapter1** ppAdapter); + + BOOL(STDMETHODCALLTYPE* IsCurrent)( + IDXGIFactory6* This); + + BOOL(STDMETHODCALLTYPE* IsWindowedStereoEnabled)( + IDXGIFactory6* This); + + HRESULT(STDMETHODCALLTYPE* CreateSwapChainForHwnd)( + IDXGIFactory6* This, + IUnknown* pDevice, + HWND hWnd, + void* pDesc, + void* pFullscreenDesc, + void* pRestrictToOutput, + void** ppSwapChain); + + HRESULT(STDMETHODCALLTYPE* CreateSwapChainForCoreWindow)( + IDXGIFactory6* This, + IUnknown* pDevice, + IUnknown* pWindow, + void* pDesc, + void* pRestrictToOutput, + void** ppSwapChain); + + HRESULT(STDMETHODCALLTYPE* GetSharedResourceAdapterLuid)( + IDXGIFactory6* This, + HANDLE hResource, + LUID* pLuid); + + HRESULT(STDMETHODCALLTYPE* RegisterStereoStatusWindow)( + IDXGIFactory6* This, + HWND WindowHandle, + UINT wMsg, + DWORD* pdwCookie); + + HRESULT(STDMETHODCALLTYPE* RegisterStereoStatusEvent)( + IDXGIFactory6* This, + HANDLE hEvent, + DWORD* pdwCookie); + + void (STDMETHODCALLTYPE* UnregisterStereoStatus)( + IDXGIFactory6* This, + DWORD dwCookie); + + HRESULT(STDMETHODCALLTYPE* RegisterOcclusionStatusWindow)( + IDXGIFactory6* This, + HWND WindowHandle, + UINT wMsg, + DWORD* pdwCookie); + + HRESULT(STDMETHODCALLTYPE* RegisterOcclusionStatusEvent)( + IDXGIFactory6* This, + HANDLE hEvent, + DWORD* pdwCookie); + + void (STDMETHODCALLTYPE* UnregisterOcclusionStatus)( + IDXGIFactory6* This, + DWORD dwCookie); + + HRESULT(STDMETHODCALLTYPE* CreateSwapChainForComposition)( + IDXGIFactory6* This, + IUnknown* pDevice, + void* pDesc, + void* pRestrictToOutput, + void** ppSwapChain); + + UINT(STDMETHODCALLTYPE* GetCreationFlags)( + IDXGIFactory6* This); + + HRESULT(STDMETHODCALLTYPE* EnumAdapterByLuid)( + IDXGIFactory6* This, + LUID AdapterLuid, + REFIID riid, + void** ppvAdapter); + + HRESULT(STDMETHODCALLTYPE* EnumWarpAdapter)( + IDXGIFactory6* This, + REFIID riid, + void** ppvAdapter); + + HRESULT(STDMETHODCALLTYPE* CheckFeatureSupport)( + IDXGIFactory6* This, + DXGI_FEATURE Feature, + void* pFeatureSupportData, + UINT FeatureSupportDataSize); + + HRESULT(STDMETHODCALLTYPE* EnumAdapterByGpuPreference)( + IDXGIFactory6* This, + UINT Adapter, + DXGI_GPU_PREFERENCE GpuPreference, + REFIID riid, + void** ppvAdapter); +} IDXGIFactory6Vtbl; + +struct IDXGIFactory6 +{ + struct IDXGIFactory6Vtbl* lpVtbl; +}; + +#define IDXGIFactory6_EnumAdapterByGpuPreference(This,Adapter,GpuPreference,riid,ppvAdapter) \ + ( (This)->lpVtbl -> EnumAdapterByGpuPreference(This,Adapter,GpuPreference,riid,ppvAdapter) ) diff --git a/visualc/Refresh.vcxproj b/visualc/Refresh.vcxproj index d73b03c..52fd6af 100644 --- a/visualc/Refresh.vcxproj +++ b/visualc/Refresh.vcxproj @@ -61,7 +61,7 @@ Level3 Disabled - REFRESH_DRIVER_VULKAN;%(PreprocessorDefinitions) + REFRESH_DRIVER_VULKAN;REFRESH_DRIVER_D3D11;%(PreprocessorDefinitions) DebugFull @@ -72,7 +72,7 @@ Level3 MaxSpeed - REFRESH_DRIVER_VULKAN;%(PreprocessorDefinitions) + REFRESH_DRIVER_VULKAN;REFRESH_DRIVER_D3D11;%(PreprocessorDefinitions) true true @@ -84,6 +84,7 @@ + @@ -91,6 +92,7 @@ + diff --git a/visualc/Refresh.vcxproj.filters b/visualc/Refresh.vcxproj.filters index 67135bd..769e63a 100644 --- a/visualc/Refresh.vcxproj.filters +++ b/visualc/Refresh.vcxproj.filters @@ -10,6 +10,9 @@ Source Files + + Source Files + @@ -24,6 +27,9 @@ Header Files + + Header Files + -- 2.25.1 From 951f124662279b55f8cdc5b053485a5d6ff5cc13 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 24 Sep 2023 19:25:49 -0500 Subject: [PATCH 02/69] Remove old stuff, flesh out PrepareDriver --- src/Refresh_Driver_D3D11.c | 252 ++++++++++++---------------- src/Refresh_Driver_D3D11_cdefines.h | 2 +- 2 files changed, 110 insertions(+), 144 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 5d5e8b9..e0a1178 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -43,6 +43,9 @@ #define D3D11_DLL "d3d11.dll" #define DXGI_DLL "dxgi.dll" +#define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice" +#define D3DCOMPILE_FUNC "D3DCompile" +#define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" #define WINDOW_SWAPCHAIN_DATA "Refresh_D3D11Swapchain" #define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!"); @@ -230,129 +233,15 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = /* 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; + 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; @@ -900,7 +789,99 @@ static void D3D11_ReleaseFence( static uint8_t D3D11_PrepareDriver( 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; } @@ -908,10 +889,10 @@ static Refresh_Device* D3D11_CreateDevice( uint8_t debugMode ) { D3D11Renderer *renderer; - PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc; + PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 }; - void* factory6; + IDXGIFactory6 *factory6; uint32_t flags; DXGI_ADAPTER_DESC1 adapterDesc; HRESULT res; @@ -931,11 +912,11 @@ static Refresh_Device* D3D11_CreateDevice( /* Load the D3DCompile function pointer */ renderer->D3DCompileFunc = (PFN_D3DCOMPILE) SDL_LoadFunction( renderer->d3dcompiler_dll, - "D3DCompile" + D3DCOMPILE_FUNC ); if (renderer->D3DCompileFunc == NULL) { - Refresh_LogError("Could not load D3DCompile function!"); + Refresh_LogError("Could not load function: " D3DCOMPILE_FUNC); return NULL; } @@ -947,14 +928,14 @@ static Refresh_Device* D3D11_CreateDevice( return NULL; } - /* Load the CreateDXGIFactory function */ - CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY) SDL_LoadFunction( + /* Load the CreateDXGIFactory1 function */ + CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1) SDL_LoadFunction( renderer->dxgi_dll, - "CreateDXGIFactory1" + CREATE_DXGI_FACTORY1_FUNC ); if (CreateDXGIFactoryFunc == NULL) { - Refresh_LogError("Could not load CreateDXGIFactory1 function!"); + Refresh_LogError("Could not load function: " CREATE_DXGI_FACTORY1_FUNC); return NULL; } @@ -974,7 +955,7 @@ static Refresh_Device* D3D11_CreateDevice( if (SUCCEEDED(res)) { IDXGIFactory6_EnumAdapterByGpuPreference( - (IDXGIFactory6*) factory6, + factory6, 0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, &D3D_IID_IDXGIAdapter1, @@ -1004,11 +985,11 @@ static Refresh_Device* D3D11_CreateDevice( /* Load the CreateDevice function */ D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE) SDL_LoadFunction( renderer->d3d11_dll, - "D3D11CreateDevice" + D3D11_CREATE_DEVICE_FUNC ); if (D3D11CreateDeviceFunc == NULL) { - Refresh_LogError("Could not load D3D11CreateDevice function!"); + Refresh_LogError("Could not load function: " D3D11_CREATE_DEVICE_FUNC); return NULL; } @@ -1022,7 +1003,7 @@ static Refresh_Device* D3D11_CreateDevice( /* Create the device */ tryCreateDevice: res = D3D11CreateDeviceFunc( - (IDXGIAdapter*)renderer->adapter, + (IDXGIAdapter*) renderer->adapter, D3D_DRIVER_TYPE_UNKNOWN, /* Must be UNKNOWN if adapter is non-null according to spec */ NULL, flags, @@ -1048,27 +1029,12 @@ tryCreateDevice: 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; diff --git a/src/Refresh_Driver_D3D11_cdefines.h b/src/Refresh_Driver_D3D11_cdefines.h index e269212..aac92d2 100644 --- a/src/Refresh_Driver_D3D11_cdefines.h +++ b/src/Refresh_Driver_D3D11_cdefines.h @@ -25,7 +25,7 @@ */ /* 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) */ -- 2.25.1 From 13ae5dee54976fe6540d75b0bcace0a33379d1e6 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 24 Sep 2023 21:20:04 -0500 Subject: [PATCH 03/69] Implement ClaimWindow, mostly copied from Vulkan and FNA3D D3D11 --- src/Refresh_Driver_D3D11.c | 210 +++++++++++++++++++++++++++++++++++-- 1 file changed, 204 insertions(+), 6 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index e0a1178..e6cdc6a 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -46,7 +46,7 @@ #define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice" #define D3DCOMPILE_FUNC "D3DCompile" #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" -#define WINDOW_SWAPCHAIN_DATA "Refresh_D3D11Swapchain" +#define WINDOW_DATA "Refresh_D3D11WindowData" #define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!"); @@ -83,7 +83,7 @@ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)( /* Conversions */ -static DXGI_FORMAT RefreshToD3D11_SurfaceFormat[] = +static DXGI_FORMAT RefreshToD3D11_TextureFormat[] = { DXGI_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */ DXGI_FORMAT_B8G8R8A8_UNORM, /* B8G8R8A8 */ @@ -233,6 +233,19 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = /* Structs */ +typedef struct SwapchainData +{ + IDXGISwapChain *swapchain; + ID3D11RenderTargetView *swapchainRTView; +} SwapchainData; + +typedef struct WindowData +{ + void* windowHandle; + uint8_t allowTearing; + SwapchainData *swapchainData; +} WindowData; + typedef struct D3D11Renderer { ID3D11Device *device; @@ -244,8 +257,12 @@ typedef struct D3D11Renderer void *d3dcompiler_dll; uint8_t debugMode; - D3D_FEATURE_LEVEL featureLevel; + D3D_FEATURE_LEVEL featureLevel; /* FIXME: Do we need this? */ PFN_D3DCOMPILE D3DCompileFunc; + + WindowData **claimedWindows; + uint32_t claimedWindowCount; + uint32_t claimedWindowCapacity; } D3D11Renderer; /* Logging */ @@ -693,13 +710,195 @@ static void D3D11_BindComputeTextures( /* 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( Refresh_Renderer *driverData, void *windowHandle, Refresh_PresentMode presentMode ) { - NOT_IMPLEMENTED - return 0; + 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; + } + } + else + { + Refresh_LogWarn("Window already claimed!"); + return 0; + } } static uint8_t D3D11_UnclaimWindow( @@ -725,7 +924,6 @@ static Refresh_TextureFormat D3D11_GetSwapchainFormat( Refresh_Renderer *driverData, void *windowHandle ) { - NOT_IMPLEMENTED return REFRESH_TEXTUREFORMAT_R8G8B8A8; } -- 2.25.1 From 49c64a230f2bfe8d88ec17d32284c49d4b2c856c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 24 Sep 2023 21:29:11 -0500 Subject: [PATCH 04/69] Implemented AcquireCommandBuffer (from old D3D11 work) --- src/Refresh_Driver_D3D11.c | 150 +++++++++++++++++++++++++++++++++---- 1 file changed, 134 insertions(+), 16 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index e6cdc6a..b63347e 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -65,6 +65,24 @@ return ret; \ } +#define EXPAND_ELEMENTS_IF_NEEDED(arr, initialValue, type) \ + if (arr->count == arr->capacity) \ + { \ + if (arr->capacity == 0) \ + { \ + arr->capacity = initialValue; \ + } \ + else \ + { \ + arr->capacity *= 2; \ + } \ + arr->elements = (type*) SDL_realloc( \ + arr->elements, \ + arr->capacity * sizeof(type) \ + ); \ + } + + /* D3DCompile signature */ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)( @@ -233,18 +251,42 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = /* Structs */ -typedef struct SwapchainData +typedef struct D3D11SwapchainData { IDXGISwapChain *swapchain; ID3D11RenderTargetView *swapchainRTView; -} SwapchainData; +} D3D11SwapchainData; -typedef struct WindowData +typedef struct D3D11WindowData { void* windowHandle; uint8_t allowTearing; - SwapchainData *swapchainData; -} WindowData; + D3D11SwapchainData *swapchainData; +} D3D11WindowData; + +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 D3D11Renderer { @@ -260,9 +302,12 @@ typedef struct D3D11Renderer D3D_FEATURE_LEVEL featureLevel; /* FIXME: Do we need this? */ PFN_D3DCOMPILE D3DCompileFunc; - WindowData **claimedWindows; + D3D11WindowData **claimedWindows; uint32_t claimedWindowCount; uint32_t claimedWindowCapacity; + + D3D11CommandBufferPool *commandBufferPool; + SDL_mutex *commandBufferAcquisitionMutex; } D3D11Renderer; /* Logging */ @@ -616,8 +661,72 @@ static void D3D11_QueueDestroyGraphicsPipeline( static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( Refresh_Renderer *driverData ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *commandBuffer = NULL; + uint32_t i; + HRESULT res; + + /* Make sure multiple threads can't acquire the same command buffer. */ + SDL_LockMutex(renderer->commandBufferAcquisitionMutex); + + /* Try to use an existing command buffer, if one is available. */ + for (i = 0; i < renderer->commandBufferPool->count; i += 1) + { + /* Search for a command buffer in the pool that is not recording. */ + if (!renderer->commandBufferPool->elements[i]->recording) + { + commandBuffer = renderer->commandBufferPool->elements[i]; + break; + } + } + + /* If there are no free command buffers, make a new one. */ + if (commandBuffer == NULL) + { + /* Expand the capacity as needed */ + EXPAND_ELEMENTS_IF_NEEDED( + renderer->commandBufferPool, + 2, + D3D11CommandBuffer* + ); + + /* Create a new command buffer */ + renderer->commandBufferPool->elements[i] = (D3D11CommandBuffer*) SDL_malloc( + sizeof(D3D11CommandBuffer) + ); + + /* Assign it a new deferred context */ + res = ID3D11Device_CreateDeferredContext( + renderer->device, + 0, + &renderer->commandBufferPool->elements[i]->context + ); + if (FAILED(res)) + { + SDL_UnlockMutex(renderer->commandBufferAcquisitionMutex); + ERROR_CHECK_RETURN("Could not create deferred context for command buffer", NULL); + } + + /* Now we have a new command buffer we can use! */ + commandBuffer = renderer->commandBufferPool->elements[i]; + renderer->commandBufferPool->count += 1; + } + + /* Set up the command buffer */ + commandBuffer->threadID = SDL_ThreadID(); + commandBuffer->recording = 1; + commandBuffer->swapchainData = NULL; + commandBuffer->commandList = NULL; + commandBuffer->dsView = NULL; + commandBuffer->numBoundColorAttachments = 0; + for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) + { + commandBuffer->rtViews[i] = NULL; + } + + SDL_UnlockMutex(renderer->commandBufferAcquisitionMutex); + + return (Refresh_CommandBuffer*) commandBuffer; } static void D3D11_BeginRenderPass( @@ -710,10 +819,10 @@ static void D3D11_BindComputeTextures( /* Window and Swapchain Management */ -static WindowData* D3D11_INTERNAL_FetchWindowData( +static D3D11WindowData* D3D11_INTERNAL_FetchWindowData( void *windowHandle ) { - return (WindowData*) SDL_GetWindowData(windowHandle, WINDOW_DATA); + return (D3D11WindowData*) SDL_GetWindowData(windowHandle, WINDOW_DATA); } static void D3D11_INTERNAL_ResolveSwapChainModeDescription( @@ -755,7 +864,7 @@ static void D3D11_INTERNAL_ResolveSwapChainModeDescription( static uint8_t D3D11_INTERNAL_CreateSwapchain( D3D11Renderer *renderer, - WindowData *windowData + D3D11WindowData *windowData ) { SDL_SysWMinfo info; HWND dxgiHandle; @@ -763,7 +872,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( DXGI_SWAP_CHAIN_DESC swapchainDesc; IDXGIFactory1 *pParent; IDXGISwapChain *swapchain; - SwapchainData *swapchainData; + D3D11SwapchainData *swapchainData; HRESULT res; /* Get the DXGI handle */ @@ -847,7 +956,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( } /* Create the swapchain data */ - swapchainData = (SwapchainData*) SDL_malloc(sizeof(SwapchainData)); + swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData)); swapchainData->swapchain = swapchain; swapchainData->swapchainRTView = NULL; @@ -861,11 +970,11 @@ static uint8_t D3D11_ClaimWindow( Refresh_PresentMode presentMode ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle); + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle); if (windowData == NULL) { - windowData = (WindowData*) SDL_malloc(sizeof(WindowData)); + windowData = (D3D11WindowData*) SDL_malloc(sizeof(D3D11WindowData)); windowData->windowHandle = windowHandle; windowData->allowTearing = presentMode == REFRESH_PRESENTMODE_IMMEDIATE; @@ -878,7 +987,7 @@ static uint8_t D3D11_ClaimWindow( renderer->claimedWindowCapacity *= 2; renderer->claimedWindows = SDL_realloc( renderer->claimedWindows, - renderer->claimedWindowCapacity * sizeof(WindowData*) + renderer->claimedWindowCapacity * sizeof(D3D11WindowData*) ); } @@ -1227,6 +1336,15 @@ tryCreateDevice: 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->commandBufferAcquisitionMutex = SDL_CreateMutex(); + /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); -- 2.25.1 From 1637401a8ace918b05d9d7c5fc04cc4369a794f4 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Mon, 25 Sep 2023 21:24:01 -0500 Subject: [PATCH 05/69] Apply swapchainDesc fix from FNA3D, add cdefines.h to CMakeLists --- CMakeLists.txt | 1 + src/Refresh_Driver_D3D11.c | 65 +++++--------------------------------- 2 files changed, 9 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab91e45..8aecf23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ add_library(Refresh # Internal Headers src/Refresh_Driver.h src/Refresh_Driver_Vulkan_vkfuncs.h + Refresh_Driver_D3D11_cdefines.h # Source Files src/Refresh.c src/Refresh_Driver_D3D11.c diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b63347e..7f11b26 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -825,50 +825,12 @@ static D3D11WindowData* D3D11_INTERNAL_FetchWindowData( return (D3D11WindowData*) 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, D3D11WindowData *windowData ) { SDL_SysWMinfo info; HWND dxgiHandle; - DXGI_MODE_DESC swapchainBufferDesc; DXGI_SWAP_CHAIN_DESC swapchainDesc; IDXGIFactory1 *pParent; IDXGISwapChain *swapchain; @@ -881,26 +843,15 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( 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; + swapchainDesc.BufferDesc.Width = 0; + swapchainDesc.BufferDesc.Height = 0; + swapchainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapchainDesc.BufferDesc.RefreshRate.Denominator = 0; + swapchainDesc.BufferDesc.Format = RefreshToD3D11_TextureFormat[REFRESH_TEXTUREFORMAT_R8G8B8A8]; + swapchainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchainDesc.BufferDesc.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! */ + /* Initialize the rest of the swapchain descriptor */ swapchainDesc.SampleDesc.Count = 1; swapchainDesc.SampleDesc.Quality = 0; swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; -- 2.25.1 From f4c332f4e3386473889e547b9d0bd63b14c5779d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Mon, 25 Sep 2023 22:10:36 -0500 Subject: [PATCH 06/69] More swapchain setup --- src/Refresh_Driver_D3D11.c | 177 +++++++++++++++++++++++++++++++++++-- 1 file changed, 172 insertions(+), 5 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 7f11b26..c470673 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -251,10 +251,36 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = /* Structs */ +typedef struct D3D11Texture +{ + /* D3D Handles */ + ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ + ID3D11ShaderResourceView *shaderView; + + /* Basic Info */ + uint32_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 + { + uint32_t width; + uint32_t height; + ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ + } twod; + }; +} D3D11Texture; + typedef struct D3D11SwapchainData { IDXGISwapChain *swapchain; - ID3D11RenderTargetView *swapchainRTView; + D3D11Texture texture; } D3D11SwapchainData; typedef struct D3D11WindowData @@ -825,12 +851,73 @@ static D3D11WindowData* D3D11_INTERNAL_FetchWindowData( return (D3D11WindowData*) SDL_GetWindowData(windowHandle, WINDOW_DATA); } +static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( + D3D11Renderer *renderer, + IDXGISwapChain *swapchain, + D3D11Texture *pTexture +) { + ID3D11Texture2D *swapchainTexture; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + D3D11_TEXTURE2D_DESC textureDesc; + HRESULT res; + + /* Clear all the texture data */ + SDL_zerop(pTexture); + + /* Grab the buffer from the swapchain */ + res = IDXGISwapChain_GetBuffer( + swapchain, + 0, + &D3D_IID_ID3D11Texture2D, + (void**) &swapchainTexture + ); + ERROR_CHECK_RETURN("Could not get buffer from swapchain!", 0); + + /* Create the RTV for the swapchain */ + rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = 0; + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + (ID3D11Resource*) swapchainTexture, + &rtvDesc, + (ID3D11RenderTargetView**) &pTexture->twod.targetView + ); + if (FAILED(res)) + { + Refresh_LogError( + "Swapchain RTV creation failed. Error Code: %08X", + res + ); + ID3D11Texture2D_Release(swapchainTexture); + return 0; + } + + /* Fill out the rest of the texture struct */ + pTexture->handle = NULL; + pTexture->shaderView = NULL; + pTexture->isRenderTarget = 1; + pTexture->rtType = REFRESH_D3D11_RENDERTARGET_2D; + + ID3D11Texture2D_GetDesc(swapchainTexture, &textureDesc); + pTexture->levelCount = textureDesc.MipLevels; + pTexture->twod.width = textureDesc.Width; + pTexture->twod.height = textureDesc.Height; + + /* Cleanup */ + ID3D11Texture2D_Release(swapchainTexture); + + return 1; +} + static uint8_t D3D11_INTERNAL_CreateSwapchain( D3D11Renderer *renderer, D3D11WindowData *windowData ) { SDL_SysWMinfo info; HWND dxgiHandle; + int width, height; DXGI_SWAP_CHAIN_DESC swapchainDesc; IDXGIFactory1 *pParent; IDXGISwapChain *swapchain; @@ -842,6 +929,9 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( SDL_GetWindowWMInfo((SDL_Window*) windowData->windowHandle, &info); dxgiHandle = info.info.win.window; + /* Get the window size */ + SDL_GetWindowSize((SDL_Window*) windowData->windowHandle, &width, &height); + /* Initialize the swapchain buffer descriptor */ swapchainDesc.BufferDesc.Width = 0; swapchainDesc.BufferDesc.Height = 0; @@ -880,7 +970,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( res = IDXGISwapChain_GetParent( swapchain, &D3D_IID_IDXGIFactory1, - (void**) &pParent + (void**) &pParent /* FIXME: Does pParent need to get released? (Same for FNA3D) */ ); if (FAILED(res)) { @@ -909,12 +999,52 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( /* Create the swapchain data */ swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData)); swapchainData->swapchain = swapchain; - swapchainData->swapchainRTView = NULL; + + if (!D3D11_INTERNAL_InitializeSwapchainTexture( + renderer, + swapchain, + &swapchainData->texture + )) { + SDL_free(swapchainData); + IDXGISwapChain_Release(swapchain); + return 0; + } windowData->swapchainData = swapchainData; return 1; } +static uint8_t D3D11_INTERNAL_ResizeSwapchain( + D3D11Renderer *renderer, + D3D11SwapchainData *swapchainData, + int32_t width, + int32_t height +) { + HRESULT res; + + /* Release the old RTV */ + ID3D11RenderTargetView_Release(swapchainData->texture.twod.targetView); + + /* Resize the swapchain */ + res = IDXGISwapChain_ResizeBuffers( + swapchainData->swapchain, + 0, /* Keep buffer count the same */ + width, + height, + DXGI_FORMAT_UNKNOWN, /* Keep the old format */ + 0 + ); + ERROR_CHECK_RETURN("Could not resize swapchain buffers", 0); + + /* Create the Refresh-side texture for the swapchain */ + return D3D11_INTERNAL_InitializeSwapchainTexture( + renderer, + swapchainData->swapchain, + &swapchainData->texture + ); +} + + static uint8_t D3D11_ClaimWindow( Refresh_Renderer *driverData, void *windowHandle, @@ -976,8 +1106,45 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( uint32_t *pWidth, uint32_t *pHeight ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11SwapchainData *swapchainData; + DXGI_SWAP_CHAIN_DESC swapchainDesc; + int w, h; + HRESULT res; + + /* Fetch the window and swapchain data. */ + swapchainData = D3D11_INTERNAL_FetchWindowData(windowHandle)->swapchainData; + if (swapchainData == NULL) + { + return NULL; + } + + /* Check for window size changes and resize the swapchain if needed. */ + IDXGISwapChain_GetDesc(swapchainData->swapchain, &swapchainDesc); + SDL_GetWindowSize((SDL_Window*) windowHandle, &w, &h); + + if (w != swapchainDesc.BufferDesc.Width || h != swapchainDesc.BufferDesc.Height) + { + res = D3D11_INTERNAL_ResizeSwapchain( + renderer, + swapchainData, + w, + h + ); + ERROR_CHECK_RETURN("Could not resize swapchain", NULL); + } + + /* Let the command buffer know it's associated with this swapchain. */ + cmdbuf->swapchainData = swapchainData; + + /* Send the dimensions to the out parameters. */ + *pWidth = swapchainData->texture.twod.width; + *pHeight = swapchainData->texture.twod.height; + + /* Return the swapchain texture */ + return (Refresh_Texture*) &swapchainData->texture; + } static Refresh_TextureFormat D3D11_GetSwapchainFormat( -- 2.25.1 From d7d89530dec6e231d6330ec67292f3f41daefe9c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 27 Sep 2023 21:01:45 -0500 Subject: [PATCH 07/69] Implemented BeginRenderPass and Submit, ClearScreen works now! --- src/Refresh_Driver_D3D11.c | 166 +++++++++++++++++++++++++++++++++++-- 1 file changed, 158 insertions(+), 8 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index c470673..4def7bb 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -333,7 +333,9 @@ typedef struct D3D11Renderer uint32_t claimedWindowCapacity; D3D11CommandBufferPool *commandBufferPool; - SDL_mutex *commandBufferAcquisitionMutex; + + SDL_mutex *contextLock; + SDL_mutex *commandBufferAcquisitionLock; } D3D11Renderer; /* Logging */ @@ -693,7 +695,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( HRESULT res; /* Make sure multiple threads can't acquire the same command buffer. */ - SDL_LockMutex(renderer->commandBufferAcquisitionMutex); + SDL_LockMutex(renderer->commandBufferAcquisitionLock); /* Try to use an existing command buffer, if one is available. */ for (i = 0; i < renderer->commandBufferPool->count; i += 1) @@ -729,7 +731,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( ); if (FAILED(res)) { - SDL_UnlockMutex(renderer->commandBufferAcquisitionMutex); + SDL_UnlockMutex(renderer->commandBufferAcquisitionLock); ERROR_CHECK_RETURN("Could not create deferred context for command buffer", NULL); } @@ -750,7 +752,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->rtViews[i] = NULL; } - SDL_UnlockMutex(renderer->commandBufferAcquisitionMutex); + SDL_UnlockMutex(renderer->commandBufferAcquisitionLock); return (Refresh_CommandBuffer*) commandBuffer; } @@ -762,14 +764,121 @@ static void D3D11_BeginRenderPass( uint32_t colorAttachmentCount, Refresh_DepthStencilAttachmentInfo *depthStencilAttachmentInfo ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + float clearColors[4]; + D3D11_CLEAR_FLAG dsClearFlags; + D3D11_VIEWPORT viewport; + D3D11_RECT scissorRect; + uint32_t i; + + /* FIXME: + * We need to unbind the RT textures on the Refresh side + * if they're bound for sampling on the command buffer! + */ + + /* Clear the bound RTs for the current command buffer */ + for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) + { + d3d11CommandBuffer->rtViews[i] = NULL; + } + d3d11CommandBuffer->dsView = NULL; + + /* Get RTVs for the color attachments */ + for (i = 0; i < colorAttachmentCount; i += 1) + { + /* FIXME: Cube RTs */ + d3d11CommandBuffer->rtViews[i] = (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->twod.targetView; + } + + /* Get the DSV for the depth stencil attachment, if applicable */ + if (depthStencilAttachmentInfo != NULL) + { + d3d11CommandBuffer->dsView = (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->twod.targetView; + } + + /* Actually set the RTs */ + ID3D11DeviceContext_OMSetRenderTargets( + d3d11CommandBuffer->context, + colorAttachmentCount, + d3d11CommandBuffer->rtViews, + d3d11CommandBuffer->dsView + ); + + /* Perform load ops on the RTs */ + for (i = 0; i < colorAttachmentCount; i += 1) + { + if (colorAttachmentInfos[i].loadOp == REFRESH_LOADOP_CLEAR) + { + clearColors[0] = colorAttachmentInfos[i].clearColor.x; + clearColors[1] = colorAttachmentInfos[i].clearColor.y; + clearColors[2] = colorAttachmentInfos[i].clearColor.z; + clearColors[3] = colorAttachmentInfos[i].clearColor.w; + + ID3D11DeviceContext_ClearRenderTargetView( + d3d11CommandBuffer->context, + (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->twod.targetView, + clearColors + ); + } + } + + if (d3d11CommandBuffer->dsView != NULL) + { + dsClearFlags = 0; + if (depthStencilAttachmentInfo->loadOp == REFRESH_LOADOP_CLEAR) + { + dsClearFlags |= D3D11_CLEAR_DEPTH; + } + if (depthStencilAttachmentInfo->stencilLoadOp == REFRESH_LOADOP_CLEAR) + { + dsClearFlags |= D3D11_CLEAR_STENCIL; + } + + if (dsClearFlags != 0) + { + ID3D11DeviceContext_ClearDepthStencilView( + d3d11CommandBuffer->context, + (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->twod.targetView, + dsClearFlags, + depthStencilAttachmentInfo->depthStencilClearValue.depth, + (uint8_t) depthStencilAttachmentInfo->depthStencilClearValue.stencil + ); + } + } + + /* Set default viewport and scissor state */ + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->twod.width; + viewport.Height = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->twod.height; + viewport.MinDepth = 0; + viewport.MaxDepth = 1; + + ID3D11DeviceContext_RSSetViewports( + d3d11CommandBuffer->context, + 1, + &viewport + ); + + scissorRect.left = 0; + scissorRect.right = (LONG) viewport.Width; + scissorRect.top = 0; + scissorRect.bottom = (LONG) viewport.Height; + + ID3D11DeviceContext_RSSetScissorRects( + d3d11CommandBuffer->context, + 1, + &scissorRect + ); } static void D3D11_EndRenderPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer ) { - NOT_IMPLEMENTED + /* FIXME: Resolve MSAA here! */ + /* FIXME: Anything else we need to do...? */ } static void D3D11_BindGraphicsPipeline( @@ -1168,7 +1277,47 @@ static void D3D11_Submit( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + ID3D11CommandList *commandList; + HRESULT res; + + /* FIXME: Should add sanity check that current thread ID matches the command buffer's threadID. */ + + /* Serialize the commands into the command list */ + res = ID3D11DeviceContext_FinishCommandList( + d3d11CommandBuffer->context, + 0, + &commandList + ); + ERROR_CHECK("Could not finish command list recording!"); + + /* Submit the command list to the immediate context */ + SDL_LockMutex(renderer->contextLock); + ID3D11DeviceContext_ExecuteCommandList( + renderer->immediateContext, + commandList, + 0 + ); + SDL_UnlockMutex(renderer->contextLock); + + /* Now that we're done with the command list, release it! */ + ID3D11CommandList_Release(commandList); + + /* Mark the command buffer as not-recording so that it can be used to record again. */ + d3d11CommandBuffer->recording = 0; + + /* Present, if applicable */ + if (d3d11CommandBuffer->swapchainData) + { + SDL_LockMutex(renderer->contextLock); + IDXGISwapChain_Present( + d3d11CommandBuffer->swapchainData->swapchain, + 1, /* FIXME: Assumes vsync! */ + 0 + ); + SDL_UnlockMutex(renderer->contextLock); + } } static Refresh_Fence* D3D11_SubmitAndAcquireFence( @@ -1461,7 +1610,8 @@ tryCreateDevice: ); /* Create mutexes */ - renderer->commandBufferAcquisitionMutex = SDL_CreateMutex(); + renderer->contextLock = SDL_CreateMutex(); + renderer->commandBufferAcquisitionLock = SDL_CreateMutex(); /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); -- 2.25.1 From e195e7f2220bb0ea28429523366b106e47843ba7 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 27 Sep 2023 21:12:28 -0500 Subject: [PATCH 08/69] UnclaimWindow, swapchain destruction, fixed template signature --- src/Refresh_Driver_D3D11.c | 62 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 4def7bb..a6bfee1 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -99,6 +99,10 @@ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)( ID3DBlob **ppErrorMsgs ); +/* Forward Declarations */ + +static void D3D11_Wait(Refresh_Renderer *driverData); + /* Conversions */ static DXGI_FORMAT RefreshToD3D11_TextureFormat[] = @@ -1153,6 +1157,30 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( ); } +static void D3D11_INTERNAL_DestroySwapchain( + D3D11Renderer *renderer, + D3D11WindowData *windowData +) { + D3D11SwapchainData *swapchainData; + + if (windowData == NULL) + { + return; + } + + swapchainData = windowData->swapchainData; + + if (swapchainData == NULL) + { + return; + } + + ID3D11RenderTargetView_Release(swapchainData->texture.twod.targetView); + IDXGISwapChain_Release(swapchainData->swapchain); + + windowData->swapchainData = NULL; + SDL_free(swapchainData); +} static uint8_t D3D11_ClaimWindow( Refresh_Renderer *driverData, @@ -1200,12 +1228,40 @@ static uint8_t D3D11_ClaimWindow( } } -static uint8_t D3D11_UnclaimWindow( +static void D3D11_UnclaimWindow( Refresh_Renderer *driverData, void *windowHandle ) { - NOT_IMPLEMENTED - return 0; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle); + uint32_t i; + + if (windowData == NULL) + { + return; + } + + if (windowData->swapchainData != NULL) + { + D3D11_Wait(driverData); + D3D11_INTERNAL_DestroySwapchain( + (D3D11Renderer*) driverData, + windowData + ); + } + + for (i = 0; i < renderer->claimedWindowCount; i += 1) + { + if (renderer->claimedWindows[i]->windowHandle == windowHandle) + { + renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1]; + renderer->claimedWindowCount -= 1; + break; + } + } + + SDL_free(windowData); + SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_DATA, NULL); } static Refresh_Texture* D3D11_AcquireSwapchainTexture( -- 2.25.1 From 413095923bffcae7918ddaa4c7777a4d6f60c6a0 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 29 Sep 2023 20:52:14 -0500 Subject: [PATCH 09/69] Stub out D3D11_Wait, fix crash when unclaiming windows, fix backend order --- src/Refresh.c | 2 +- src/Refresh_Driver_D3D11.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Refresh.c b/src/Refresh.c index b495fd2..4b2ad46 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -53,8 +53,8 @@ static const Refresh_Driver *backends[] = { NULL, - D3D11_DRIVER, VULKAN_DRIVER, + D3D11_DRIVER, PS5_DRIVER }; diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index a6bfee1..13465b2 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1273,13 +1273,19 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11WindowData *windowData; D3D11SwapchainData *swapchainData; DXGI_SWAP_CHAIN_DESC swapchainDesc; int w, h; HRESULT res; - /* Fetch the window and swapchain data. */ - swapchainData = D3D11_INTERNAL_FetchWindowData(windowHandle)->swapchainData; + windowData = D3D11_INTERNAL_FetchWindowData(windowHandle); + if (windowData == NULL) + { + return NULL; + } + + swapchainData = windowData->swapchainData; if (swapchainData == NULL) { return NULL; @@ -1387,7 +1393,7 @@ static Refresh_Fence* D3D11_SubmitAndAcquireFence( static void D3D11_Wait( Refresh_Renderer *driverData ) { - NOT_IMPLEMENTED + /* FIXME: Anything we need to do here? */ } static void D3D11_WaitForFences( -- 2.25.1 From ce984f58d102d2db7b270225abb0124bd26ac571 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 8 Oct 2023 16:05:33 -0500 Subject: [PATCH 10/69] Reworked Wait and Submit logic to use D3D11 Query objects as fences --- src/Refresh_Driver_D3D11.c | 223 ++++++++++++++++++++++++++----------- 1 file changed, 160 insertions(+), 63 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 13465b2..8bce5d5 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -298,7 +298,6 @@ typedef struct D3D11CommandBuffer { /* D3D11 Object References */ ID3D11DeviceContext *context; - ID3D11CommandList *commandList; D3D11SwapchainData *swapchainData; /* Render Pass */ @@ -308,7 +307,7 @@ typedef struct D3D11CommandBuffer /* State */ SDL_threadID threadID; - uint8_t recording; + ID3D11Query *completionQuery; } D3D11CommandBuffer; typedef struct D3D11CommandBufferPool @@ -339,7 +338,11 @@ typedef struct D3D11Renderer D3D11CommandBufferPool *commandBufferPool; SDL_mutex *contextLock; - SDL_mutex *commandBufferAcquisitionLock; + SDL_mutex *acquireCommandBufferLock; + + D3D11CommandBuffer **submittedCommandBuffers; + uint32_t submittedCommandBufferCount; + uint32_t submittedCommandBufferCapacity; } D3D11Renderer; /* Logging */ @@ -690,65 +693,82 @@ static void D3D11_QueueDestroyGraphicsPipeline( /* Graphics State */ +static void D3D11_INTERNAL_AllocateCommandBuffers( + D3D11Renderer *renderer, + uint32_t allocateCount +) { + D3D11CommandBufferPool *pool = renderer->commandBufferPool; + D3D11CommandBuffer *commandBuffer; + D3D11_QUERY_DESC queryDesc; + HRESULT res; + + pool->capacity += allocateCount; + + pool->elements = SDL_realloc( + pool->elements, + sizeof(D3D11CommandBuffer*) * pool->capacity + ); + + for (uint32_t i = 0; i < allocateCount; i += 1) + { + commandBuffer = SDL_malloc(sizeof(D3D11CommandBuffer)); + + res = ID3D11Device_CreateDeferredContext( + renderer->device, + 0, + &commandBuffer->context + ); + ERROR_CHECK("Could not create deferred context! Error Code: %08X"); + + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + res = ID3D11Device_CreateQuery( + renderer->device, + &queryDesc, + &commandBuffer->completionQuery + ); + ERROR_CHECK("Could not create query! Error Code: %08X"); + + /* FIXME: Resource tracking? */ + + pool->elements[pool->count] = commandBuffer; + pool->count += 1; + } +} + +static D3D11CommandBuffer* D3D11_INTERNAL_GetInactiveCommandBufferFromPool( + D3D11Renderer *renderer +) { + D3D11CommandBufferPool *commandPool = renderer->commandBufferPool; + D3D11CommandBuffer *commandBuffer; + + if (commandPool->count == 0) + { + D3D11_INTERNAL_AllocateCommandBuffers( + renderer, + commandPool->capacity + ); + } + + commandBuffer = commandPool->elements[commandPool->count - 1]; + commandPool->count -= 1; + + return commandBuffer; +} + static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( Refresh_Renderer *driverData ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11CommandBuffer *commandBuffer = NULL; + D3D11CommandBuffer *commandBuffer; uint32_t i; - HRESULT res; - /* Make sure multiple threads can't acquire the same command buffer. */ - SDL_LockMutex(renderer->commandBufferAcquisitionLock); - - /* Try to use an existing command buffer, if one is available. */ - for (i = 0; i < renderer->commandBufferPool->count; i += 1) - { - /* Search for a command buffer in the pool that is not recording. */ - if (!renderer->commandBufferPool->elements[i]->recording) - { - commandBuffer = renderer->commandBufferPool->elements[i]; - break; - } - } - - /* If there are no free command buffers, make a new one. */ - if (commandBuffer == NULL) - { - /* Expand the capacity as needed */ - EXPAND_ELEMENTS_IF_NEEDED( - renderer->commandBufferPool, - 2, - D3D11CommandBuffer* - ); - - /* Create a new command buffer */ - renderer->commandBufferPool->elements[i] = (D3D11CommandBuffer*) SDL_malloc( - sizeof(D3D11CommandBuffer) - ); - - /* Assign it a new deferred context */ - res = ID3D11Device_CreateDeferredContext( - renderer->device, - 0, - &renderer->commandBufferPool->elements[i]->context - ); - if (FAILED(res)) - { - SDL_UnlockMutex(renderer->commandBufferAcquisitionLock); - ERROR_CHECK_RETURN("Could not create deferred context for command buffer", NULL); - } - - /* Now we have a new command buffer we can use! */ - commandBuffer = renderer->commandBufferPool->elements[i]; - renderer->commandBufferPool->count += 1; - } + SDL_LockMutex(renderer->acquireCommandBufferLock); /* Set up the command buffer */ + commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer); commandBuffer->threadID = SDL_ThreadID(); - commandBuffer->recording = 1; commandBuffer->swapchainData = NULL; - commandBuffer->commandList = NULL; commandBuffer->dsView = NULL; commandBuffer->numBoundColorAttachments = 0; for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) @@ -756,7 +776,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->rtViews[i] = NULL; } - SDL_UnlockMutex(renderer->commandBufferAcquisitionLock); + SDL_UnlockMutex(renderer->acquireCommandBufferLock); return (Refresh_CommandBuffer*) commandBuffer; } @@ -1335,6 +1355,41 @@ static void D3D11_SetSwapchainPresentMode( /* Submission and Fences */ +static void D3D11_INTERNAL_CleanCommandBuffer( + D3D11Renderer *renderer, + D3D11CommandBuffer *commandBuffer +) { + uint32_t i; + + /* FIXME: All kinds of stuff should go here... */ + + SDL_LockMutex(renderer->acquireCommandBufferLock); + + if (renderer->commandBufferPool->count == renderer->commandBufferPool->capacity) + { + renderer->commandBufferPool->capacity += 1; + renderer->commandBufferPool->elements = SDL_realloc( + renderer->commandBufferPool->elements, + renderer->commandBufferPool->capacity * sizeof(D3D11CommandBuffer*) + ); + } + + renderer->commandBufferPool->elements[renderer->commandBufferPool->count] = commandBuffer; + renderer->commandBufferPool->count += 1; + + SDL_UnlockMutex(renderer->acquireCommandBufferLock); + + /* Remove this command buffer from the submitted list */ + for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) + { + if (renderer->submittedCommandBuffers[i] == commandBuffer) + { + renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1]; + renderer->submittedCommandBufferCount -= 1; + } + } +} + static void D3D11_Submit( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer @@ -1346,6 +1401,8 @@ static void D3D11_Submit( /* FIXME: Should add sanity check that current thread ID matches the command buffer's threadID. */ + SDL_LockMutex(renderer->contextLock); + /* Serialize the commands into the command list */ res = ID3D11DeviceContext_FinishCommandList( d3d11CommandBuffer->context, @@ -1355,31 +1412,40 @@ static void D3D11_Submit( ERROR_CHECK("Could not finish command list recording!"); /* Submit the command list to the immediate context */ - SDL_LockMutex(renderer->contextLock); ID3D11DeviceContext_ExecuteCommandList( renderer->immediateContext, commandList, 0 ); - SDL_UnlockMutex(renderer->contextLock); - - /* Now that we're done with the command list, release it! */ ID3D11CommandList_Release(commandList); - /* Mark the command buffer as not-recording so that it can be used to record again. */ - d3d11CommandBuffer->recording = 0; + /* Mark the command buffer as submitted */ + if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) + { + renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1; + + renderer->submittedCommandBuffers = SDL_realloc( + renderer->submittedCommandBuffers, + sizeof(D3D11CommandBuffer*) * renderer->submittedCommandBufferCapacity + ); + } + + renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d11CommandBuffer; + renderer->submittedCommandBufferCount += 1; + + SDL_UnlockMutex(renderer->contextLock); /* Present, if applicable */ if (d3d11CommandBuffer->swapchainData) { - SDL_LockMutex(renderer->contextLock); IDXGISwapChain_Present( d3d11CommandBuffer->swapchainData->swapchain, 1, /* FIXME: Assumes vsync! */ 0 ); - SDL_UnlockMutex(renderer->contextLock); } + + SDL_UnlockMutex(renderer->contextLock); } static Refresh_Fence* D3D11_SubmitAndAcquireFence( @@ -1393,7 +1459,38 @@ static Refresh_Fence* D3D11_SubmitAndAcquireFence( static void D3D11_Wait( Refresh_Renderer *driverData ) { - /* FIXME: Anything we need to do here? */ + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *commandBuffer; + BOOL queryData; + + /* + * Wait for all submitted command buffers to complete. + * Sort of equivalent to vkDeviceWaitIdle. + */ + for (uint32_t i = 0; i < renderer->submittedCommandBufferCount; i += 1) + { + while (S_OK != ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->completionQuery, + &queryData, + sizeof(queryData), + 0 + )) { + /* Spin until we get a result back... */ + } + } + + SDL_LockMutex(renderer->contextLock); + + for (int32_t i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) + { + commandBuffer = renderer->submittedCommandBuffers[i]; + D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer); + } + + /* FIXME: D3D11_INTERNAL_PerformPendingDestroys(renderer); */ + + SDL_UnlockMutex(renderer->contextLock); } static void D3D11_WaitForFences( @@ -1673,7 +1770,7 @@ tryCreateDevice: /* Create mutexes */ renderer->contextLock = SDL_CreateMutex(); - renderer->commandBufferAcquisitionLock = SDL_CreateMutex(); + renderer->acquireCommandBufferLock = SDL_CreateMutex(); /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); -- 2.25.1 From e47e7b2c752cca2260221c9a2b37c7623979a0ad Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 8 Oct 2023 16:16:11 -0500 Subject: [PATCH 11/69] Fix for command pool crash, fix for hanging on Wait --- src/Refresh_Driver_D3D11.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 8bce5d5..e99e3c7 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1403,6 +1403,12 @@ static void D3D11_Submit( SDL_LockMutex(renderer->contextLock); + /* Notify the command buffer completion query that we have completed recording */ + ID3D11DeviceContext_End( + renderer->immediateContext, + (ID3D11Asynchronous*) d3d11CommandBuffer->completionQuery + ); + /* Serialize the commands into the command list */ res = ID3D11DeviceContext_FinishCommandList( d3d11CommandBuffer->context, @@ -1775,6 +1781,9 @@ tryCreateDevice: /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); + /* Create command buffers to initialize the pool */ + D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2); + /* Create the Refresh Device */ result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); ASSIGN_DRIVER(D3D11) -- 2.25.1 From afcfacb30595c860521efb35cf5bfd6961a060f4 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:27:36 -0500 Subject: [PATCH 12/69] Pipeline creation copied over from old work + shaderc update --- shadercompiler/Program.cs | 14 +- src/Refresh_Driver_D3D11.c | 396 +++++++++++++++++++++++++++++++++++-- 2 files changed, 390 insertions(+), 20 deletions(-) diff --git a/shadercompiler/Program.cs b/shadercompiler/Program.cs index 1dba27e..8600b6c 100644 --- a/shadercompiler/Program.cs +++ b/shadercompiler/Program.cs @@ -200,20 +200,20 @@ partial class Program WriteShaderBlob(writer, inputPath, 1); } + if (data.d3d11) + { + string inputPath = Path.Combine(tempDir, $"{shaderName}.hlsl"); + WriteShaderBlob(writer, inputPath, 2); + } + #if PS5 if (data.ps5) { string ext = GetPS5ShaderFileExtension(); string inputPath = Path.Combine(tempDir, $"{shaderName}{ext}"); - WriteShaderBlob(writer, inputPath, 2); - } -#endif - - if (data.d3d11) - { - string inputPath = Path.Combine(tempDir, $"{shaderName}.hlsl"); WriteShaderBlob(writer, inputPath, 3); } +#endif } } diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index e99e3c7..8db96b9 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -228,17 +228,6 @@ static D3D11_STENCIL_OP RefreshToD3D11_StencilOp[] = 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 */ @@ -317,6 +306,36 @@ typedef struct D3D11CommandBufferPool 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; + 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; @@ -475,6 +494,224 @@ static void D3D11_DispatchCompute( /* State Creation */ +static ID3D11BlendState* D3D11_INTERNAL_FetchBlendState( + D3D11Renderer *renderer, + uint32_t numColorAttachments, + Refresh_ColorAttachmentDescription *colorAttachments +) { + ID3D11BlendState *result; + D3D11_BLEND_DESC blendDesc; + uint32_t i; + HRESULT res; + + /* Create a new blend state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + SDL_zero(blendDesc); /* needed for any unused RT entries */ + + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = TRUE; + + for (i = 0; i < numColorAttachments; i += 1) + { + blendDesc.RenderTarget[i].BlendEnable = colorAttachments[i].blendState.blendEnable; + blendDesc.RenderTarget[i].BlendOp = RefreshToD3D11_BlendOp[ + colorAttachments[i].blendState.colorBlendOp + ]; + blendDesc.RenderTarget[i].BlendOpAlpha = RefreshToD3D11_BlendOp[ + colorAttachments[i].blendState.alphaBlendOp + ]; + blendDesc.RenderTarget[i].DestBlend = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.dstColorBlendFactor + ]; + blendDesc.RenderTarget[i].DestBlendAlpha = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.dstAlphaBlendFactor + ]; + blendDesc.RenderTarget[i].RenderTargetWriteMask = colorAttachments[i].blendState.colorWriteMask; + blendDesc.RenderTarget[i].SrcBlend = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.srcColorBlendFactor + ]; + blendDesc.RenderTarget[i].SrcBlendAlpha = RefreshToD3D11_BlendFactor[ + colorAttachments[i].blendState.srcAlphaBlendFactor + ]; + } + + res = ID3D11Device_CreateBlendState( + renderer->device, + &blendDesc, + &result + ); + ERROR_CHECK_RETURN("Could not create blend state", NULL); + + return result; +} + +static ID3D11DepthStencilState* D3D11_INTERNAL_FetchDepthStencilState( + D3D11Renderer *renderer, + Refresh_DepthStencilState depthStencilState +) { + ID3D11DepthStencilState *result; + D3D11_DEPTH_STENCIL_DESC dsDesc; + HRESULT res; + + /* Create a new depth-stencil state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + dsDesc.DepthEnable = depthStencilState.depthTestEnable; + dsDesc.StencilEnable = depthStencilState.stencilTestEnable; + dsDesc.DepthFunc = depthStencilState.compareOp; + dsDesc.DepthWriteMask = ( + depthStencilState.depthWriteEnable ? + D3D11_DEPTH_WRITE_MASK_ALL : + D3D11_DEPTH_WRITE_MASK_ZERO + ); + + dsDesc.BackFace.StencilFunc = depthStencilState.backStencilState.compareOp; + dsDesc.BackFace.StencilDepthFailOp = depthStencilState.backStencilState.depthFailOp; + dsDesc.BackFace.StencilFailOp = depthStencilState.backStencilState.failOp; + dsDesc.BackFace.StencilPassOp = depthStencilState.backStencilState.passOp; + + dsDesc.FrontFace.StencilFunc = depthStencilState.frontStencilState.compareOp; + dsDesc.FrontFace.StencilDepthFailOp = depthStencilState.frontStencilState.depthFailOp; + dsDesc.FrontFace.StencilFailOp = depthStencilState.frontStencilState.failOp; + dsDesc.FrontFace.StencilPassOp = depthStencilState.frontStencilState.passOp; + + /* FIXME: D3D11 doesn't have separate read/write masks for each stencil side. What should we do? */ + dsDesc.StencilReadMask = depthStencilState.backStencilState.compareMask; + dsDesc.StencilWriteMask = depthStencilState.backStencilState.writeMask; + + /* FIXME: What do we do with these? + * depthStencilState.depthBoundsTestEnable + * depthStencilState.maxDepthBounds + * depthStencilState.minDepthBounds + */ + + res = ID3D11Device_CreateDepthStencilState( + renderer->device, + &dsDesc, + &result + ); + ERROR_CHECK_RETURN("Could not create depth-stencil state", NULL); + + return result; +} + +static ID3D11RasterizerState* D3D11_INTERNAL_FetchRasterizerState( + D3D11Renderer *renderer, + Refresh_RasterizerState rasterizerState +) { + ID3D11RasterizerState *result; + D3D11_RASTERIZER_DESC rasterizerDesc; + HRESULT res; + + /* Create a new rasterizer state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + rasterizerDesc.AntialiasedLineEnable = FALSE; + rasterizerDesc.CullMode = RefreshToD3D11_CullMode[rasterizerState.cullMode]; + rasterizerDesc.DepthBias = (INT) rasterizerState.depthBiasConstantFactor; /* FIXME: Is this cast correct? */ + rasterizerDesc.DepthBiasClamp = rasterizerState.depthBiasClamp; + rasterizerDesc.DepthClipEnable = TRUE; /* FIXME: Do we want this...? */ + rasterizerDesc.FillMode = (rasterizerState.fillMode == REFRESH_FILLMODE_FILL) ? D3D11_FILL_SOLID : D3D11_FILL_WIREFRAME; + rasterizerDesc.FrontCounterClockwise = (rasterizerState.frontFace == REFRESH_FRONTFACE_COUNTER_CLOCKWISE); + rasterizerDesc.MultisampleEnable = TRUE; /* only applies to MSAA render targets */ + rasterizerDesc.ScissorEnable = TRUE; + rasterizerDesc.SlopeScaledDepthBias = rasterizerState.depthBiasSlopeFactor; + + res = ID3D11Device_CreateRasterizerState( + renderer->device, + &rasterizerDesc, + &result + ); + ERROR_CHECK_RETURN("Could not create rasterizer state", NULL); + + return result; +} + +static uint32_t D3D11_INTERNAL_FindIndexOfVertexBinding( + uint32_t targetBinding, + const Refresh_VertexBinding *bindings, + uint32_t numBindings +) { + uint32_t i; + for (i = 0; i < numBindings; i += 1) + { + if (bindings[i].binding == targetBinding) + { + return i; + } + } + + Refresh_LogError("Could not find vertex binding %d!", targetBinding); + return 0; +} + +static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout( + D3D11Renderer *renderer, + Refresh_VertexInputState inputState, + void *shaderBytes, + size_t shaderByteLength +) { + ID3D11InputLayout *result = NULL; + D3D11_INPUT_ELEMENT_DESC *elementDescs; + uint32_t i, bindingIndex; + HRESULT res; + + /* Allocate an array of vertex elements */ + elementDescs = SDL_stack_alloc( + D3D11_INPUT_ELEMENT_DESC, + inputState.vertexAttributeCount + ); + + /* Create the array of input elements */ + for (i = 0; i < inputState.vertexAttributeCount; i += 1) + { + elementDescs[i].AlignedByteOffset = inputState.vertexAttributes[i].offset; + elementDescs[i].Format = RefreshToD3D11_VertexFormat[ + inputState.vertexAttributes[i].format + ]; + elementDescs[i].InputSlot = inputState.vertexAttributes[i].binding; + + bindingIndex = D3D11_INTERNAL_FindIndexOfVertexBinding( + elementDescs[i].InputSlot, + inputState.vertexBindings, + inputState.vertexBindingCount + ); + elementDescs[i].InputSlotClass = RefreshToD3D11_VertexInputRate[ + inputState.vertexBindings[bindingIndex].inputRate + ]; + /* The spec requires this to be 0 for per-vertex data */ + elementDescs[i].InstanceDataStepRate = ( + elementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA ? 1 : 0 + ); + + elementDescs[i].SemanticIndex = inputState.vertexAttributes[i].location; + elementDescs[i].SemanticName = "TEXCOORD"; + } + + res = ID3D11Device_CreateInputLayout( + renderer->device, + elementDescs, + inputState.vertexAttributeCount, + shaderBytes, + shaderByteLength, + &result + ); + if (FAILED(res)) + { + Refresh_LogError("Could not create input layout! Error: %X", res); + SDL_stack_free(elementDescs); + return NULL; + } + + /* FIXME: + * These are not cached by the driver! Should we cache them, or allow duplicates? + * If we have one input layout per graphics pipeline maybe that wouldn't be so bad...? + */ + + SDL_stack_free(elementDescs); + return result; +} static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_Renderer *driverData, @@ -488,8 +725,141 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( Refresh_Renderer *driverData, Refresh_GraphicsPipelineCreateInfo *pipelineCreateInfo ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline*) SDL_malloc(sizeof(D3D11GraphicsPipeline)); + D3D11ShaderModule *vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule; + D3D11ShaderModule *fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule; + ID3D10Blob *errorBlob; + int32_t i; + HRESULT res; + + /* Color */ + + pipeline->numColorAttachments = pipelineCreateInfo->attachmentInfo.colorAttachmentCount; + for (i = 0; i < pipeline->numColorAttachments; i += 1) + { + pipeline->colorAttachmentFormats[i] = RefreshToD3D11_TextureFormat[ + pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format + ]; + } + + pipeline->blendConstants[0] = pipelineCreateInfo->blendConstants[0]; + pipeline->blendConstants[1] = pipelineCreateInfo->blendConstants[1]; + pipeline->blendConstants[2] = pipelineCreateInfo->blendConstants[2]; + pipeline->blendConstants[3] = pipelineCreateInfo->blendConstants[3]; + + pipeline->multisampleState = pipelineCreateInfo->multisampleState; + + pipeline->colorAttachmentBlendState = D3D11_INTERNAL_FetchBlendState( + renderer, + pipelineCreateInfo->attachmentInfo.colorAttachmentCount, + pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions + ); + + /* Depth stencil */ + + pipeline->hasDepthStencilAttachment = pipelineCreateInfo->attachmentInfo.hasDepthStencilAttachment; + + pipeline->depthStencilAttachmentFormat = RefreshToD3D11_TextureFormat[ + pipelineCreateInfo->attachmentInfo.depthStencilFormat + ]; + + pipeline->stencilRef = pipelineCreateInfo->depthStencilState.backStencilState.reference; /* FIXME: Should we use front or back? */ + + pipeline->depthStencilState = D3D11_INTERNAL_FetchDepthStencilState( + renderer, + pipelineCreateInfo->depthStencilState + ); + + /* Rasterizer */ + + pipeline->primitiveTopology = RefreshToD3D11_PrimitiveType[pipelineCreateInfo->primitiveType]; + + pipeline->rasterizerState = D3D11_INTERNAL_FetchRasterizerState( + renderer, + pipelineCreateInfo->rasterizerState + ); + + /* Vertex shader */ + + if (vertShaderModule->shader == NULL) + { + res = renderer->D3DCompileFunc( + vertShaderModule->shaderSource, + vertShaderModule->shaderSourceLength, + NULL, + NULL, + NULL, + "main", + "vs_5_0", + 0, + 0, + &vertShaderModule->blob, + &errorBlob + ); + if (FAILED(res)) + { + Refresh_LogError("Vertex Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); + return NULL; + } + + res = ID3D11Device_CreateVertexShader( + renderer->device, + ID3D10Blob_GetBufferPointer(vertShaderModule->blob), + ID3D10Blob_GetBufferSize(vertShaderModule->blob), + NULL, + (ID3D11VertexShader**) &vertShaderModule->shader + ); + ERROR_CHECK_RETURN("Could not create vertex shader", NULL); + } + pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shader; + + /* Input Layout */ + + pipeline->inputLayout = D3D11_INTERNAL_FetchInputLayout( + renderer, + pipelineCreateInfo->vertexInputState, + ID3D10Blob_GetBufferPointer(vertShaderModule->blob), + ID3D10Blob_GetBufferSize(vertShaderModule->blob) + ); + + /* Fragment Shader */ + + if (fragShaderModule->shader == NULL) + { + res = renderer->D3DCompileFunc( + fragShaderModule->shaderSource, + fragShaderModule->shaderSourceLength, + NULL, + NULL, + NULL, + "main", + "ps_5_0", + 0, + 0, + &fragShaderModule->blob, + &errorBlob + ); + if (FAILED(res)) + { + Refresh_LogError("Fragment Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); + return NULL; + } + + res = ID3D11Device_CreatePixelShader( + renderer->device, + ID3D10Blob_GetBufferPointer(fragShaderModule->blob), + ID3D10Blob_GetBufferSize(fragShaderModule->blob), + NULL, + (ID3D11PixelShader**) &fragShaderModule->shader + ); + ERROR_CHECK_RETURN("Could not create pixel shader", NULL); + } + pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader; + + /* FIXME: Need to create uniform buffers for the shaders */ + + return (Refresh_GraphicsPipeline*) pipeline; } static Refresh_Sampler* D3D11_CreateSampler( -- 2.25.1 From 2cb678d9a1a39f8b777c0cd701ba0d9fc93781c6 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:32:12 -0500 Subject: [PATCH 13/69] Implement CreateShaderModule --- src/Refresh_Driver_D3D11.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 8db96b9..e7afe86 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -874,8 +874,20 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( Refresh_Renderer *driverData, Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule)); + + /* We don't know whether this is a vertex or fragment shader, + * so wait to compile until we bind to a pipeline... + */ + shaderModule->shader = NULL; + shaderModule->blob = NULL; + + shaderModule->shaderSourceLength = shaderModuleCreateInfo->codeSize; + shaderModule->shaderSource = (char*) SDL_malloc(shaderModule->shaderSourceLength); + SDL_memcpy(shaderModule->shaderSource, shaderModuleCreateInfo->byteCode, shaderModuleCreateInfo->codeSize); + + return (Refresh_ShaderModule*) shaderModule; } static Refresh_Texture* D3D11_CreateTexture( -- 2.25.1 From 9b139cf67229b64bf48ec0c35a2f0a0614df9c24 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:45:32 -0500 Subject: [PATCH 14/69] DrawPrimitives, BindGraphicsPipeline, misc cleanup --- src/Refresh_Driver_D3D11.c | 113 +++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 24 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index e7afe86..18a993b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -290,9 +290,9 @@ typedef struct D3D11CommandBuffer D3D11SwapchainData *swapchainData; /* Render Pass */ - uint8_t numBoundColorAttachments; ID3D11RenderTargetView *rtViews[MAX_COLOR_TARGET_BINDINGS]; - ID3D11DepthStencilView* dsView; + ID3D11DepthStencilView *dsView; + struct D3D11GraphicsPipeline *graphicsPipeline; /* State */ SDL_threadID threadID; @@ -325,7 +325,7 @@ typedef struct D3D11GraphicsPipeline uint8_t hasDepthStencilAttachment; DXGI_FORMAT depthStencilAttachmentFormat; - D3D11_PRIMITIVE_TOPOLOGY primitiveTopology; + Refresh_PrimitiveType primitiveType; uint32_t stencilRef; ID3D11DepthStencilState *depthStencilState; ID3D11RasterizerState *rasterizerState; @@ -465,7 +465,15 @@ static void D3D11_DrawPrimitives( uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { - NOT_IMPLEMENTED + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + + ID3D11DeviceContext_Draw( + cmdbuf->context, + PrimitiveVerts(cmdbuf->graphicsPipeline->primitiveType, primitiveCount), + vertexStart + ); + + /* FIXME: vertex/fragment param offsets */ } static void D3D11_DrawPrimitivesIndirect( @@ -735,6 +743,12 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( /* Color */ + pipeline->colorAttachmentBlendState = D3D11_INTERNAL_FetchBlendState( + renderer, + pipelineCreateInfo->attachmentInfo.colorAttachmentCount, + pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions + ); + pipeline->numColorAttachments = pipelineCreateInfo->attachmentInfo.colorAttachmentCount; for (i = 0; i < pipeline->numColorAttachments; i += 1) { @@ -750,31 +764,22 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( pipeline->multisampleState = pipelineCreateInfo->multisampleState; - pipeline->colorAttachmentBlendState = D3D11_INTERNAL_FetchBlendState( - renderer, - pipelineCreateInfo->attachmentInfo.colorAttachmentCount, - pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions - ); - /* Depth stencil */ - pipeline->hasDepthStencilAttachment = pipelineCreateInfo->attachmentInfo.hasDepthStencilAttachment; - - pipeline->depthStencilAttachmentFormat = RefreshToD3D11_TextureFormat[ - pipelineCreateInfo->attachmentInfo.depthStencilFormat - ]; - - pipeline->stencilRef = pipelineCreateInfo->depthStencilState.backStencilState.reference; /* FIXME: Should we use front or back? */ - pipeline->depthStencilState = D3D11_INTERNAL_FetchDepthStencilState( renderer, pipelineCreateInfo->depthStencilState ); + pipeline->hasDepthStencilAttachment = pipelineCreateInfo->attachmentInfo.hasDepthStencilAttachment; + pipeline->depthStencilAttachmentFormat = RefreshToD3D11_TextureFormat[ + pipelineCreateInfo->attachmentInfo.depthStencilFormat + ]; + pipeline->stencilRef = pipelineCreateInfo->depthStencilState.backStencilState.reference; /* FIXME: Should we use front or back? */ + /* Rasterizer */ - pipeline->primitiveTopology = RefreshToD3D11_PrimitiveType[pipelineCreateInfo->primitiveType]; - + pipeline->primitiveType = pipelineCreateInfo->primitiveType; pipeline->rasterizerState = D3D11_INTERNAL_FetchRasterizerState( renderer, pipelineCreateInfo->rasterizerState @@ -1056,7 +1061,11 @@ static void D3D11_QueueDestroyShaderModule( Refresh_Renderer *driverData, Refresh_ShaderModule *shaderModule ) { - NOT_IMPLEMENTED + D3D11ShaderModule *d3dShaderModule = (D3D11ShaderModule*) shaderModule; + ID3D11DeviceChild_Release(d3dShaderModule->shader); + ID3D10Blob_Release(d3dShaderModule->blob); + SDL_free(d3dShaderModule->shaderSource); + SDL_free(d3dShaderModule); } static void D3D11_QueueDestroyComputePipeline( @@ -1070,7 +1079,17 @@ static void D3D11_QueueDestroyGraphicsPipeline( Refresh_Renderer *driverData, Refresh_GraphicsPipeline *graphicsPipeline ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11GraphicsPipeline *d3dGraphicsPipeline = (D3D11GraphicsPipeline*) graphicsPipeline; + + ID3D11BlendState_Release(d3dGraphicsPipeline->colorAttachmentBlendState); + ID3D11DepthStencilState_Release(d3dGraphicsPipeline->depthStencilState); + ID3D11RasterizerState_Release(d3dGraphicsPipeline->rasterizerState); + ID3D11InputLayout_Release(d3dGraphicsPipeline->inputLayout); + + /* FIXME: Release uniform buffers, once that's written in */ + + SDL_free(d3dGraphicsPipeline); } /* Graphics State */ @@ -1152,7 +1171,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->threadID = SDL_ThreadID(); commandBuffer->swapchainData = NULL; commandBuffer->dsView = NULL; - commandBuffer->numBoundColorAttachments = 0; + commandBuffer->graphicsPipeline = NULL; for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { commandBuffer->rtViews[i] = NULL; @@ -1292,7 +1311,53 @@ static void D3D11_BindGraphicsPipeline( Refresh_CommandBuffer *commandBuffer, Refresh_GraphicsPipeline *graphicsPipeline ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline*) graphicsPipeline; + + cmdbuf->graphicsPipeline = pipeline; + + ID3D11DeviceContext_OMSetBlendState( + cmdbuf->context, + pipeline->colorAttachmentBlendState, + pipeline->blendConstants, + pipeline->multisampleState.sampleMask + ); + + ID3D11DeviceContext_OMSetDepthStencilState( + cmdbuf->context, + pipeline->depthStencilState, + pipeline->stencilRef + ); + + ID3D11DeviceContext_IASetPrimitiveTopology( + cmdbuf->context, + RefreshToD3D11_PrimitiveType[pipeline->primitiveType] + ); + + ID3D11DeviceContext_IASetInputLayout( + cmdbuf->context, + pipeline->inputLayout + ); + + ID3D11DeviceContext_RSSetState( + cmdbuf->context, + pipeline->rasterizerState + ); + + ID3D11DeviceContext_VSSetShader( + cmdbuf->context, + pipeline->vertexShader, + NULL, + 0 + ); + + ID3D11DeviceContext_PSSetShader( + cmdbuf->context, + pipeline->fragmentShader, + NULL, + 0 + ); } static void D3D11_SetViewport( -- 2.25.1 From 88ca03f213de48a1f43414df94f9065d66c1bcca Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:51:34 -0500 Subject: [PATCH 15/69] shaderc now flips Y values in the vertex shader --- shadercompiler/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadercompiler/Program.cs b/shadercompiler/Program.cs index 8600b6c..a76a1de 100644 --- a/shadercompiler/Program.cs +++ b/shadercompiler/Program.cs @@ -254,7 +254,7 @@ partial class Program { Process spirvcross = Process.Start( "spirv-cross", - $"\"{spirvPath}\" --hlsl --shader-model 50 --output \"{outputPath}\"" + $"\"{spirvPath}\" --hlsl --flip-vert-y --shader-model 50 --output \"{outputPath}\"" ); spirvcross.WaitForExit(); if (spirvcross.ExitCode != 0) -- 2.25.1 From 38d51cf6de9fd0dec3ffb5f9dd3ef133e120ec36 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 08:18:39 -0500 Subject: [PATCH 16/69] Style cleanups + added FIXME note for shader compilation --- src/Refresh_Driver_D3D11.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 18a993b..ffefa0d 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -465,11 +465,11 @@ static void D3D11_DrawPrimitives( uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { - D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; ID3D11DeviceContext_Draw( - cmdbuf->context, - PrimitiveVerts(cmdbuf->graphicsPipeline->primitiveType, primitiveCount), + d3d11CommandBuffer->context, + PrimitiveVerts(d3d11CommandBuffer->graphicsPipeline->primitiveType, primitiveCount), vertexStart ); @@ -789,6 +789,10 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( if (vertShaderModule->shader == NULL) { + /* FIXME: + * Could we store a flag in the shaderc output to mark if a shader is vertex/fragment? + * Then we could compile on shader module creation instead of at bind time. + */ res = renderer->D3DCompileFunc( vertShaderModule->shaderSource, vertShaderModule->shaderSourceLength, @@ -1312,48 +1316,48 @@ static void D3D11_BindGraphicsPipeline( Refresh_GraphicsPipeline *graphicsPipeline ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline*) graphicsPipeline; - cmdbuf->graphicsPipeline = pipeline; + d3d11CommandBuffer->graphicsPipeline = pipeline; ID3D11DeviceContext_OMSetBlendState( - cmdbuf->context, + d3d11CommandBuffer->context, pipeline->colorAttachmentBlendState, pipeline->blendConstants, pipeline->multisampleState.sampleMask ); ID3D11DeviceContext_OMSetDepthStencilState( - cmdbuf->context, + d3d11CommandBuffer->context, pipeline->depthStencilState, pipeline->stencilRef ); ID3D11DeviceContext_IASetPrimitiveTopology( - cmdbuf->context, + d3d11CommandBuffer->context, RefreshToD3D11_PrimitiveType[pipeline->primitiveType] ); ID3D11DeviceContext_IASetInputLayout( - cmdbuf->context, + d3d11CommandBuffer->context, pipeline->inputLayout ); ID3D11DeviceContext_RSSetState( - cmdbuf->context, + d3d11CommandBuffer->context, pipeline->rasterizerState ); ID3D11DeviceContext_VSSetShader( - cmdbuf->context, + d3d11CommandBuffer->context, pipeline->vertexShader, NULL, 0 ); ID3D11DeviceContext_PSSetShader( - cmdbuf->context, + d3d11CommandBuffer->context, pipeline->fragmentShader, NULL, 0 @@ -1739,7 +1743,7 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( uint32_t *pHeight ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11CommandBuffer *cmdbuf = (D3D11CommandBuffer*) commandBuffer; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11WindowData *windowData; D3D11SwapchainData *swapchainData; DXGI_SWAP_CHAIN_DESC swapchainDesc; @@ -1774,7 +1778,7 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( } /* Let the command buffer know it's associated with this swapchain. */ - cmdbuf->swapchainData = swapchainData; + d3d11CommandBuffer->swapchainData = swapchainData; /* Send the dimensions to the out parameters. */ *pWidth = swapchainData->texture.twod.width; @@ -1782,7 +1786,6 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( /* Return the swapchain texture */ return (Refresh_Texture*) &swapchainData->texture; - } static Refresh_TextureFormat D3D11_GetSwapchainFormat( -- 2.25.1 From 0f1a2423d0fdbd2177b394255510865b12ce8f02 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 08:18:53 -0500 Subject: [PATCH 17/69] Implement SetViewport and SetScissor --- src/Refresh_Driver_D3D11.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ffefa0d..bf68f89 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1369,7 +1369,22 @@ static void D3D11_SetViewport( Refresh_CommandBuffer *commandBuffer, Refresh_Viewport *viewport ) { - NOT_IMPLEMENTED + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11_VIEWPORT vp = + { + viewport->x, + viewport->y, + viewport->w, + viewport->h, + viewport->minDepth, + viewport->maxDepth + }; + + ID3D11DeviceContext_RSSetViewports( + d3d11CommandBuffer->context, + 1, + &vp + ); } static void D3D11_SetScissor( @@ -1377,7 +1392,20 @@ static void D3D11_SetScissor( Refresh_CommandBuffer *commandBuffer, Refresh_Rect *scissor ) { - NOT_IMPLEMENTED + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*)commandBuffer; + D3D11_RECT rect = + { + scissor->x, + scissor->y, + scissor->x + scissor->w, + scissor->y + scissor->h + }; + + ID3D11DeviceContext_RSSetScissorRects( + d3d11CommandBuffer->context, + 1, + &rect + ); } static void D3D11_BindVertexBuffers( -- 2.25.1 From 741d3ebcffdea8095f9b539b8de363be78db606d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 08:42:32 -0500 Subject: [PATCH 18/69] Initial work on DestroyDevice --- src/Refresh_Driver_D3D11.c | 102 ++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 23 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index bf68f89..43496d7 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -82,7 +82,6 @@ ); \ } - /* D3DCompile signature */ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)( @@ -102,6 +101,10 @@ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)( /* Forward Declarations */ static void D3D11_Wait(Refresh_Renderer *driverData); +static void D3D11_UnclaimWindow( + Refresh_Renderer * driverData, + void *windowHandle +); /* Conversions */ @@ -354,7 +357,7 @@ typedef struct D3D11Renderer uint32_t claimedWindowCount; uint32_t claimedWindowCapacity; - D3D11CommandBufferPool *commandBufferPool; + D3D11CommandBufferPool commandBufferPool; SDL_mutex *contextLock; SDL_mutex *acquireCommandBufferLock; @@ -427,7 +430,54 @@ static void D3D11_INTERNAL_LogError( static void D3D11_DestroyDevice( Refresh_Device *device ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) device->driverData; + D3D11CommandBuffer *commandBuffer; + int32_t i; + + D3D11_Wait(device->driverData); + + /* Release the window data */ + + for (i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) + { + D3D11_UnclaimWindow(device->driverData, renderer->claimedWindows[i]->windowHandle); + } + + SDL_free(renderer->claimedWindows); + + D3D11_Wait(device->driverData); /* FIXME: Copied this from Vulkan, is it actually necessary? */ + + /* Release command buffer infrastructure */ + + SDL_free(renderer->submittedCommandBuffers); + + for (i = 0; i < renderer->commandBufferPool.count; i += 1) + { + commandBuffer = renderer->commandBufferPool.elements[i]; + + ID3D11Query_Release(commandBuffer->completionQuery); + ID3D11DeviceContext_Release(commandBuffer->context); + + SDL_free(commandBuffer); + } + + /* Release the mutexes */ + + SDL_DestroyMutex(renderer->acquireCommandBufferLock); + SDL_DestroyMutex(renderer->contextLock); + + /* Release the DLLs and D3D11 device infrastructure */ + + SDL_UnloadObject(renderer->d3d11_dll); + SDL_UnloadObject(renderer->d3dcompiler_dll); + + ID3D11DeviceContext_Release(renderer->immediateContext); + ID3D11Device_Release(renderer->device); + IDXGIAdapter_Release(renderer->adapter); + IDXGIFactory_Release(renderer->factory); + + SDL_free(renderer); + SDL_free(device); } /* Drawing */ @@ -1066,8 +1116,16 @@ static void D3D11_QueueDestroyShaderModule( Refresh_ShaderModule *shaderModule ) { D3D11ShaderModule *d3dShaderModule = (D3D11ShaderModule*) shaderModule; - ID3D11DeviceChild_Release(d3dShaderModule->shader); - ID3D10Blob_Release(d3dShaderModule->blob); + + if (d3dShaderModule->shader) + { + ID3D11DeviceChild_Release(d3dShaderModule->shader); + } + if (d3dShaderModule->blob) + { + ID3D10Blob_Release(d3dShaderModule->blob); + } + SDL_free(d3dShaderModule->shaderSource); SDL_free(d3dShaderModule); } @@ -1102,7 +1160,7 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( D3D11Renderer *renderer, uint32_t allocateCount ) { - D3D11CommandBufferPool *pool = renderer->commandBufferPool; + D3D11CommandBufferPool *pool = &renderer->commandBufferPool; D3D11CommandBuffer *commandBuffer; D3D11_QUERY_DESC queryDesc; HRESULT res; @@ -1144,19 +1202,19 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( static D3D11CommandBuffer* D3D11_INTERNAL_GetInactiveCommandBufferFromPool( D3D11Renderer *renderer ) { - D3D11CommandBufferPool *commandPool = renderer->commandBufferPool; + D3D11CommandBufferPool *pool = &renderer->commandBufferPool; D3D11CommandBuffer *commandBuffer; - if (commandPool->count == 0) + if (pool->count == 0) { D3D11_INTERNAL_AllocateCommandBuffers( renderer, - commandPool->capacity + pool->capacity ); } - commandBuffer = commandPool->elements[commandPool->count - 1]; - commandPool->count -= 1; + commandBuffer = pool->elements[pool->count - 1]; + pool->count -= 1; return commandBuffer; } @@ -1837,23 +1895,24 @@ static void D3D11_INTERNAL_CleanCommandBuffer( D3D11Renderer *renderer, D3D11CommandBuffer *commandBuffer ) { + D3D11CommandBufferPool *commandBufferPool = &renderer->commandBufferPool; uint32_t i; /* FIXME: All kinds of stuff should go here... */ SDL_LockMutex(renderer->acquireCommandBufferLock); - if (renderer->commandBufferPool->count == renderer->commandBufferPool->capacity) + if (commandBufferPool->count == commandBufferPool->capacity) { - renderer->commandBufferPool->capacity += 1; - renderer->commandBufferPool->elements = SDL_realloc( - renderer->commandBufferPool->elements, - renderer->commandBufferPool->capacity * sizeof(D3D11CommandBuffer*) + commandBufferPool->capacity += 1; + commandBufferPool->elements = SDL_realloc( + commandBufferPool->elements, + commandBufferPool->capacity * sizeof(D3D11CommandBuffer*) ); } - renderer->commandBufferPool->elements[renderer->commandBufferPool->count] = commandBuffer; - renderer->commandBufferPool->count += 1; + commandBufferPool->elements[commandBufferPool->count] = commandBuffer; + commandBufferPool->count += 1; SDL_UnlockMutex(renderer->acquireCommandBufferLock); @@ -2246,11 +2305,8 @@ tryCreateDevice: 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) - ); + /* Initialize the command buffer pool */ + renderer->commandBufferPool = (D3D11CommandBufferPool) { 0 }; /* Create mutexes */ renderer->contextLock = SDL_CreateMutex(); -- 2.25.1 From e35efa40615647124f9037d3b2759393a631959f Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 21:31:04 -0500 Subject: [PATCH 19/69] CreateBuffer, QueueDestroyBuffer, SetBufferData, BindVertexBuffers --- src/Refresh_Driver_D3D11.c | 191 +++++++++++++++++++++++++++++-------- 1 file changed, 151 insertions(+), 40 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 43496d7..97d7f3d 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -286,6 +286,38 @@ typedef struct D3D11WindowData D3D11SwapchainData *swapchainData; } D3D11WindowData; +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; + DXGI_FORMAT colorAttachmentFormats[MAX_COLOR_TARGET_BINDINGS]; + ID3D11BlendState *colorAttachmentBlendState; + + Refresh_MultisampleState multisampleState; + + uint8_t hasDepthStencilAttachment; + DXGI_FORMAT depthStencilAttachmentFormat; + ID3D11DepthStencilState *depthStencilState; + uint32_t stencilRef; + + Refresh_PrimitiveType primitiveType; + ID3D11RasterizerState *rasterizerState; + + ID3D11VertexShader *vertexShader; + ID3D11InputLayout *inputLayout; + uint32_t *vertexStrides; + + ID3D11PixelShader *fragmentShader; +} D3D11GraphicsPipeline; + typedef struct D3D11CommandBuffer { /* D3D11 Object References */ @@ -295,7 +327,7 @@ typedef struct D3D11CommandBuffer /* Render Pass */ ID3D11RenderTargetView *rtViews[MAX_COLOR_TARGET_BINDINGS]; ID3D11DepthStencilView *dsView; - struct D3D11GraphicsPipeline *graphicsPipeline; + D3D11GraphicsPipeline *graphicsPipeline; /* State */ SDL_threadID threadID; @@ -309,35 +341,11 @@ typedef struct D3D11CommandBufferPool uint32_t capacity; } D3D11CommandBufferPool; -typedef struct D3D11ShaderModule +typedef struct D3D11Buffer { - ID3D11DeviceChild *shader; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */ - ID3D10Blob *blob; - char *shaderSource; - size_t shaderSourceLength; -} D3D11ShaderModule; - -typedef struct D3D11GraphicsPipeline -{ - float blendConstants[4]; - - int32_t numColorAttachments; - DXGI_FORMAT colorAttachmentFormats[MAX_COLOR_TARGET_BINDINGS]; - ID3D11BlendState *colorAttachmentBlendState; - - uint8_t hasDepthStencilAttachment; - DXGI_FORMAT depthStencilAttachmentFormat; - - Refresh_PrimitiveType primitiveType; - uint32_t stencilRef; - ID3D11DepthStencilState *depthStencilState; - ID3D11RasterizerState *rasterizerState; - ID3D11InputLayout *inputLayout; - - Refresh_MultisampleState multisampleState; - ID3D11VertexShader *vertexShader; - ID3D11PixelShader *fragmentShader; -} D3D11GraphicsPipeline; + ID3D11Buffer *handle; + uint32_t size; +} D3D11Buffer; typedef struct D3D11Renderer { @@ -432,13 +440,12 @@ static void D3D11_DestroyDevice( ) { D3D11Renderer *renderer = (D3D11Renderer*) device->driverData; D3D11CommandBuffer *commandBuffer; - int32_t i; D3D11_Wait(device->driverData); /* Release the window data */ - for (i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) + for (int32_t i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) { D3D11_UnclaimWindow(device->driverData, renderer->claimedWindows[i]->windowHandle); } @@ -451,7 +458,7 @@ static void D3D11_DestroyDevice( SDL_free(renderer->submittedCommandBuffers); - for (i = 0; i < renderer->commandBufferPool.count; i += 1) + for (uint32_t i = 0; i < renderer->commandBufferPool.count; i += 1) { commandBuffer = renderer->commandBufferPool.elements[i]; @@ -788,7 +795,6 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( D3D11ShaderModule *vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule; D3D11ShaderModule *fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule; ID3D10Blob *errorBlob; - int32_t i; HRESULT res; /* Color */ @@ -800,7 +806,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( ); pipeline->numColorAttachments = pipelineCreateInfo->attachmentInfo.colorAttachmentCount; - for (i = 0; i < pipeline->numColorAttachments; i += 1) + for (int32_t i = 0; i < pipeline->numColorAttachments; i += 1) { pipeline->colorAttachmentFormats[i] = RefreshToD3D11_TextureFormat[ pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format @@ -882,6 +888,24 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( ID3D10Blob_GetBufferSize(vertShaderModule->blob) ); + if (pipelineCreateInfo->vertexInputState.vertexBindingCount > 0) + { + pipeline->vertexStrides = SDL_malloc( + sizeof(uint32_t) * + pipelineCreateInfo->vertexInputState.vertexBindingCount + ); + + for (uint32_t i = 0; i < pipelineCreateInfo->vertexInputState.vertexBindingCount; i += 1) + { + pipeline->vertexStrides[i] = pipelineCreateInfo->vertexInputState.vertexBindings[i].stride; + } + } + else + { + /* Not sure if this is even possible, but juuust in case... */ + pipeline->vertexStrides = NULL; + } + /* Fragment Shader */ if (fragShaderModule->shader == NULL) @@ -962,8 +986,46 @@ static Refresh_Buffer* D3D11_CreateBuffer( Refresh_BufferUsageFlags usageFlags, uint32_t sizeInBytes ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11_BUFFER_DESC bufferDesc; + ID3D11Buffer *bufferHandle; + D3D11Buffer *d3d11Buffer; + HRESULT res; + + uint32_t bindFlags = 0; + if (usageFlags & REFRESH_BUFFERUSAGE_VERTEX_BIT) + { + bindFlags |= D3D11_BIND_VERTEX_BUFFER; + } + if (usageFlags & REFRESH_BUFFERUSAGE_INDEX_BIT) + { + bindFlags |= D3D11_BIND_INDEX_BUFFER; + } + if (usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) + { + bindFlags |= D3D11_BIND_UNORDERED_ACCESS; + } + bufferDesc.BindFlags = bindFlags; + + bufferDesc.ByteWidth = sizeInBytes; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + res = ID3D11Device_CreateBuffer( + renderer->device, + &bufferDesc, + NULL, + &bufferHandle + ); + ERROR_CHECK_RETURN("Could not create buffer! Error Code: %08X", NULL); + + d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); + d3d11Buffer->handle = bufferHandle; + d3d11Buffer->size = sizeInBytes; + + return (Refresh_Buffer*) d3d11Buffer; } /* Setters */ @@ -1026,7 +1088,33 @@ static void D3D11_SetBufferData( void* data, uint32_t dataLength ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + D3D11_MAPPED_SUBRESOURCE subres = { 0 }; + HRESULT res; + + res = ID3D11DeviceContext_Map( + d3d11CommandBuffer->context, + (ID3D11Resource*) d3d11Buffer->handle, + 0, + D3D11_MAP_WRITE_DISCARD, + 0, + &subres + ); + ERROR_CHECK_RETURN("Could not map buffer for writing!", ); + + SDL_memcpy( + (uint8_t*) subres.pData + offsetInBytes, + data, + dataLength + ); + + ID3D11DeviceContext_Unmap( + d3d11CommandBuffer->context, + (ID3D11Resource*) d3d11Buffer->handle, + 0 + ); } static uint32_t D3D11_PushVertexShaderUniforms( @@ -1108,7 +1196,9 @@ static void D3D11_QueueDestroyBuffer( Refresh_Renderer *driverData, Refresh_Buffer *buffer ) { - NOT_IMPLEMENTED + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + ID3D11Buffer_Release(d3d11Buffer->handle); + SDL_free(d3d11Buffer); } static void D3D11_QueueDestroyShaderModule( @@ -1151,6 +1241,11 @@ static void D3D11_QueueDestroyGraphicsPipeline( /* FIXME: Release uniform buffers, once that's written in */ + if (d3dGraphicsPipeline->vertexStrides) + { + SDL_free(d3dGraphicsPipeline->vertexStrides); + } + SDL_free(d3dGraphicsPipeline); } @@ -1450,7 +1545,7 @@ static void D3D11_SetScissor( Refresh_CommandBuffer *commandBuffer, Refresh_Rect *scissor ) { - D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*)commandBuffer; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11_RECT rect = { scissor->x, @@ -1474,7 +1569,23 @@ static void D3D11_BindVertexBuffers( Refresh_Buffer **pBuffers, uint64_t *pOffsets ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + ID3D11Buffer *bufferHandles[MAX_BUFFER_BINDINGS]; + + for (uint32_t i = 0; i < bindingCount; i += 1) + { + bufferHandles[i] = ((D3D11Buffer*) pBuffers[i])->handle; + } + + ID3D11DeviceContext_IASetVertexBuffers( + d3d11CommandBuffer->context, + firstBinding, + bindingCount, + bufferHandles, + &d3d11CommandBuffer->graphicsPipeline->vertexStrides[firstBinding], + (UINT*) pOffsets + ); } static void D3D11_BindIndexBuffer( -- 2.25.1 From 6b39da7d2de030240b5ae4ddbf8bd6c737796040 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 22:07:46 -0500 Subject: [PATCH 20/69] CreateSampler --- src/Refresh_Driver_D3D11.c | 99 +++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 97d7f3d..8325942 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -245,6 +245,60 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = D3D11_TEXTURE_ADDRESS_BORDER /* CLAMP_TO_BORDER */ }; +static D3D11_FILTER RefreshToD3D11_Filter(Refresh_SamplerStateCreateInfo *createInfo) +{ + if (createInfo->minFilter == REFRESH_FILTER_LINEAR) + { + if (createInfo->magFilter == REFRESH_FILTER_LINEAR) + { + if (createInfo->mipmapMode == REFRESH_SAMPLERMIPMAPMODE_LINEAR) + { + return D3D11_FILTER_MIN_MAG_MIP_LINEAR; + } + else + { + return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + } + } + else + { + if (createInfo->mipmapMode == REFRESH_SAMPLERMIPMAPMODE_LINEAR) + { + return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + } + else + { + return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + } + } + } + else + { + if (createInfo->magFilter == REFRESH_FILTER_LINEAR) + { + if (createInfo->mipmapMode == REFRESH_SAMPLERMIPMAPMODE_LINEAR) + { + return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; + } + else + { + return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + } + } + else + { + if (createInfo->mipmapMode == REFRESH_SAMPLERMIPMAPMODE_LINEAR) + { + return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + } + else + { + return D3D11_FILTER_MIN_MAG_MIP_POINT; + } + } + } +} + /* Structs */ typedef struct D3D11Texture @@ -347,6 +401,11 @@ typedef struct D3D11Buffer uint32_t size; } D3D11Buffer; +typedef struct D3D11Sampler +{ + ID3D11SamplerState *handle; +} D3D11Sampler; + typedef struct D3D11Renderer { ID3D11Device *device; @@ -949,8 +1008,44 @@ static Refresh_Sampler* D3D11_CreateSampler( Refresh_Renderer *driverData, Refresh_SamplerStateCreateInfo *samplerStateCreateInfo ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11_SAMPLER_DESC samplerDesc; + ID3D11SamplerState *samplerState; + D3D11Sampler *d3d11Sampler; + HRESULT res; + + samplerDesc.AddressU = RefreshToD3D11_SamplerAddressMode[samplerStateCreateInfo->addressModeU]; + samplerDesc.AddressV = RefreshToD3D11_SamplerAddressMode[samplerStateCreateInfo->addressModeV]; + samplerDesc.AddressW = RefreshToD3D11_SamplerAddressMode[samplerStateCreateInfo->addressModeW]; + + /* FIXME: border color! */ + + samplerDesc.ComparisonFunc = ( + samplerStateCreateInfo->compareEnable ? + RefreshToD3D11_CompareOp[samplerStateCreateInfo->compareOp] : + RefreshToD3D11_CompareOp[REFRESH_COMPAREOP_ALWAYS] + ); + samplerDesc.MaxAnisotropy = ( + samplerStateCreateInfo->anisotropyEnable ? + (UINT) samplerStateCreateInfo->maxAnisotropy : + 0 + ); + samplerDesc.Filter = RefreshToD3D11_Filter(samplerStateCreateInfo); + samplerDesc.MaxLOD = samplerStateCreateInfo->maxLod; + samplerDesc.MinLOD = samplerStateCreateInfo->minLod; + samplerDesc.MipLODBias = samplerStateCreateInfo->mipLodBias; + + res = ID3D11Device_CreateSamplerState( + renderer->device, + &samplerDesc, + &samplerState + ); + ERROR_CHECK_RETURN("Could not create sampler state! Error Code: %08X", NULL); + + d3d11Sampler = (D3D11Sampler*) SDL_malloc(sizeof(D3D11Sampler)); + d3d11Sampler->handle = samplerState; + + return (Refresh_Sampler*) d3d11Sampler; } static Refresh_ShaderModule* D3D11_CreateShaderModule( -- 2.25.1 From 42a9ce28e63699892db1db370f21b857112cbe54 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 22:11:55 -0500 Subject: [PATCH 21/69] Add a border color conversion function --- src/Refresh_Driver_D3D11.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 8325942..9d3ec06 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -245,6 +245,38 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] = D3D11_TEXTURE_ADDRESS_BORDER /* CLAMP_TO_BORDER */ }; +static void RefreshToD3D11_BorderColor( + Refresh_SamplerStateCreateInfo *createInfo, + D3D11_SAMPLER_DESC *desc +) { + switch (createInfo->borderColor) + { + case REFRESH_BORDERCOLOR_FLOAT_OPAQUE_BLACK: + case REFRESH_BORDERCOLOR_INT_OPAQUE_BLACK: + desc->BorderColor[0] = 0.0f; + desc->BorderColor[1] = 0.0f; + desc->BorderColor[2] = 0.0f; + desc->BorderColor[3] = 1.0f; + break; + + case REFRESH_BORDERCOLOR_FLOAT_OPAQUE_WHITE: + case REFRESH_BORDERCOLOR_INT_OPAQUE_WHITE: + desc->BorderColor[0] = 1.0f; + desc->BorderColor[1] = 1.0f; + desc->BorderColor[2] = 1.0f; + desc->BorderColor[3] = 1.0f; + break; + + case REFRESH_BORDERCOLOR_FLOAT_TRANSPARENT_BLACK: + case REFRESH_BORDERCOLOR_INT_TRANSPARENT_BLACK: + desc->BorderColor[0] = 0.0f; + desc->BorderColor[1] = 0.0f; + desc->BorderColor[2] = 0.0f; + desc->BorderColor[3] = 0.0f; + break; + } +} + static D3D11_FILTER RefreshToD3D11_Filter(Refresh_SamplerStateCreateInfo *createInfo) { if (createInfo->minFilter == REFRESH_FILTER_LINEAR) @@ -1018,7 +1050,10 @@ static Refresh_Sampler* D3D11_CreateSampler( samplerDesc.AddressV = RefreshToD3D11_SamplerAddressMode[samplerStateCreateInfo->addressModeV]; samplerDesc.AddressW = RefreshToD3D11_SamplerAddressMode[samplerStateCreateInfo->addressModeW]; - /* FIXME: border color! */ + RefreshToD3D11_BorderColor( + samplerStateCreateInfo, + &samplerDesc + ); samplerDesc.ComparisonFunc = ( samplerStateCreateInfo->compareEnable ? -- 2.25.1 From d4ac8a16566995aa96ede7a4c011a2dc598cbebd Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 22:12:55 -0500 Subject: [PATCH 22/69] QueueDestroySampler --- src/Refresh_Driver_D3D11.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 9d3ec06..bd6f911 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1319,7 +1319,9 @@ static void D3D11_QueueDestroySampler( Refresh_Renderer *driverData, Refresh_Sampler *sampler ) { - NOT_IMPLEMENTED + D3D11Sampler *d3d11Sampler = (D3D11Sampler*) sampler; + ID3D11SamplerState_Release(d3d11Sampler->handle); + SDL_free(d3d11Sampler); } static void D3D11_QueueDestroyBuffer( -- 2.25.1 From 4bdfc2293fc41abd7c58e526e39ab355a7451e72 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 20:37:27 -0500 Subject: [PATCH 23/69] Fix redundant error code printing --- src/Refresh_Driver_D3D11.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index bd6f911..52ae91b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1042,7 +1042,7 @@ static Refresh_Sampler* D3D11_CreateSampler( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11_SAMPLER_DESC samplerDesc; - ID3D11SamplerState *samplerState; + ID3D11SamplerState *samplerStateHandle; D3D11Sampler *d3d11Sampler; HRESULT res; @@ -1073,12 +1073,12 @@ static Refresh_Sampler* D3D11_CreateSampler( res = ID3D11Device_CreateSamplerState( renderer->device, &samplerDesc, - &samplerState + &samplerStateHandle ); - ERROR_CHECK_RETURN("Could not create sampler state! Error Code: %08X", NULL); + ERROR_CHECK_RETURN("Could not create sampler state", NULL); d3d11Sampler = (D3D11Sampler*) SDL_malloc(sizeof(D3D11Sampler)); - d3d11Sampler->handle = samplerState; + d3d11Sampler->handle = samplerStateHandle; return (Refresh_Sampler*) d3d11Sampler; } @@ -1149,7 +1149,7 @@ static Refresh_Buffer* D3D11_CreateBuffer( NULL, &bufferHandle ); - ERROR_CHECK_RETURN("Could not create buffer! Error Code: %08X", NULL); + ERROR_CHECK_RETURN("Could not create buffer", NULL); d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); d3d11Buffer->handle = bufferHandle; @@ -1408,7 +1408,7 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( 0, &commandBuffer->context ); - ERROR_CHECK("Could not create deferred context! Error Code: %08X"); + ERROR_CHECK("Could not create deferred context"); queryDesc.Query = D3D11_QUERY_EVENT; queryDesc.MiscFlags = 0; @@ -1417,7 +1417,7 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( &queryDesc, &commandBuffer->completionQuery ); - ERROR_CHECK("Could not create query! Error Code: %08X"); + ERROR_CHECK("Could not create query"); /* FIXME: Resource tracking? */ @@ -1799,11 +1799,8 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( ); if (FAILED(res)) { - Refresh_LogError( - "Swapchain RTV creation failed. Error Code: %08X", - res - ); ID3D11Texture2D_Release(swapchainTexture); + D3D11_INTERNAL_LogError(renderer->device, "Swapchain RTV creation failed", res); return 0; } -- 2.25.1 From e6402cbb145e050c100ce15d3d4df9924bb2d125 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 21:25:03 -0500 Subject: [PATCH 24/69] CreateTexture, SetTextureData, BindIndexBuffer, BindFragmentSamplers, QueueDestroyTexture, DrawIndexedPrimitives, DrawInstancedPrimitives --- src/Refresh_Driver.h | 42 ++++- src/Refresh_Driver_D3D11.c | 345 ++++++++++++++++++++++++++++++++----- 2 files changed, 347 insertions(+), 40 deletions(-) diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index 679539d..b8ae8a2 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -48,6 +48,46 @@ void Refresh_LogError(const char *fmt, ...); /* Internal Helper Utilities */ +static inline int32_t Texture_GetBlockSize( + Refresh_TextureFormat format +) { + switch (format) + { + case REFRESH_TEXTUREFORMAT_BC1: + case REFRESH_TEXTUREFORMAT_BC2: + case REFRESH_TEXTUREFORMAT_BC3: + case REFRESH_TEXTUREFORMAT_BC7: + return 4; + case REFRESH_TEXTUREFORMAT_R8: + case REFRESH_TEXTUREFORMAT_R8_UINT: + case REFRESH_TEXTUREFORMAT_R5G6B5: + case REFRESH_TEXTUREFORMAT_B4G4R4A4: + case REFRESH_TEXTUREFORMAT_A1R5G5B5: + case REFRESH_TEXTUREFORMAT_R16_SFLOAT: + case REFRESH_TEXTUREFORMAT_R8G8_SNORM: + case REFRESH_TEXTUREFORMAT_R8G8_UINT: + case REFRESH_TEXTUREFORMAT_R16_UINT: + case REFRESH_TEXTUREFORMAT_R8G8B8A8: + case REFRESH_TEXTUREFORMAT_R32_SFLOAT: + case REFRESH_TEXTUREFORMAT_R16G16_SFLOAT: + case REFRESH_TEXTUREFORMAT_R8G8B8A8_SNORM: + case REFRESH_TEXTUREFORMAT_A2R10G10B10: + case REFRESH_TEXTUREFORMAT_R8G8B8A8_UINT: + case REFRESH_TEXTUREFORMAT_R16G16_UINT: + case REFRESH_TEXTUREFORMAT_R16G16B16A16_SFLOAT: + case REFRESH_TEXTUREFORMAT_R16G16B16A16: + case REFRESH_TEXTUREFORMAT_R32G32_SFLOAT: + case REFRESH_TEXTUREFORMAT_R16G16B16A16_UINT: + case REFRESH_TEXTUREFORMAT_R32G32B32A32_SFLOAT: + return 1; + default: + Refresh_LogError( + "Unrecognized TextureFormat!" + ); + return 0; + } +} + static inline uint32_t Texture_GetFormatSize( Refresh_TextureFormat format ) { @@ -87,7 +127,7 @@ static inline uint32_t Texture_GetFormatSize( return 16; default: Refresh_LogError( - "Unrecognized SurfaceFormat!" + "Unrecognized TextureFormat!" ); return 0; } diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 52ae91b..9b47552 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -153,6 +153,14 @@ static DXGI_FORMAT RefreshToD3D11_VertexFormat[] = DXGI_FORMAT_R16G16B16A16_FLOAT /* HALFVECTOR4 */ }; +static uint32_t RefreshToD3D11_SampleCount[] = +{ + 1, /* REFRESH_SAMPLECOUNT_1 */ + 2, /* REFRESH_SAMPLECOUNT_2 */ + 4, /* REFRESH_SAMPLECOUNT_4 */ + 8 /* REFRESH_SAMPLECOUNT_8 */ +}; + static DXGI_FORMAT RefreshToD3D11_IndexType[] = { DXGI_FORMAT_R16_UINT, /* 16BIT */ @@ -338,25 +346,15 @@ typedef struct D3D11Texture /* D3D Handles */ ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ ID3D11ShaderResourceView *shaderView; + ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ /* Basic Info */ + Refresh_TextureFormat format; + uint32_t width; + uint32_t height; + uint32_t depth; uint32_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 - { - uint32_t width; - uint32_t height; - ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ - } twod; - }; + uint8_t isCube; } D3D11Texture; typedef struct D3D11SwapchainData @@ -400,8 +398,10 @@ typedef struct D3D11GraphicsPipeline ID3D11VertexShader *vertexShader; ID3D11InputLayout *inputLayout; uint32_t *vertexStrides; + uint32_t numVertexSamplers; ID3D11PixelShader *fragmentShader; + uint32_t numFragmentSamplers; } D3D11GraphicsPipeline; typedef struct D3D11CommandBuffer @@ -524,6 +524,16 @@ static void D3D11_INTERNAL_LogError( Refresh_LogError("%s! Error Code: %s (0x%08X)", msg, wszMsgBuff, res); } +/* Subresources */ + +static inline uint32_t D3D11_INTERNAL_CalcSubresource( + uint32_t mipLevel, + uint32_t arraySlice, + uint32_t numLevels +) { + return mipLevel + (arraySlice * numLevels); +} + /* Quit */ static void D3D11_DestroyDevice( @@ -590,7 +600,18 @@ static void D3D11_DrawInstancedPrimitives( uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { - NOT_IMPLEMENTED + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + + ID3D11DeviceContext_DrawIndexedInstanced( + d3d11CommandBuffer->context, + PrimitiveVerts(d3d11CommandBuffer->graphicsPipeline->primitiveType, primitiveCount), + instanceCount, + startIndex, + baseVertex, + 0 + ); + + /* FIXME: vertex/fragment param offsets */ } static void D3D11_DrawIndexedPrimitives( @@ -602,7 +623,16 @@ static void D3D11_DrawIndexedPrimitives( uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { - NOT_IMPLEMENTED + D3D11_DrawInstancedPrimitives( + driverData, + commandBuffer, + baseVertex, + startIndex, + primitiveCount, + 1, + vertexParamOffset, + fragmentParamOffset + ); } static void D3D11_DrawPrimitives( @@ -969,6 +999,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( ERROR_CHECK_RETURN("Could not create vertex shader", NULL); } pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shader; + pipeline->numVertexSamplers = pipelineCreateInfo->vertexShaderInfo.samplerBindingCount; /* Input Layout */ @@ -1030,6 +1061,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( ERROR_CHECK_RETURN("Could not create pixel shader", NULL); } pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader; + pipeline->numFragmentSamplers = pipelineCreateInfo->fragmentShaderInfo.samplerBindingCount; /* FIXME: Need to create uniform buffers for the shaders */ @@ -1107,8 +1139,172 @@ static Refresh_Texture* D3D11_CreateTexture( Refresh_Renderer *driverData, Refresh_TextureCreateInfo *textureCreateInfo ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + uint8_t isSampler, isCompute, isRenderTarget, isDepthStencil; + ID3D11Resource *textureHandle; + ID3D11ShaderResourceView *srv = NULL; + ID3D11RenderTargetView *rtv = NULL; + ID3D11DepthStencilView *dsv = NULL; + D3D11Texture *d3d11Texture; + HRESULT res; + + isRenderTarget = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT; + isDepthStencil = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT; + isSampler = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT; + isCompute = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COMPUTE_BIT; + + if (textureCreateInfo->depth <= 1) + { + D3D11_TEXTURE2D_DESC desc2D; + + desc2D.Width = textureCreateInfo->width; + desc2D.Height = textureCreateInfo->height; + + desc2D.BindFlags = 0; + if (isSampler) + { + desc2D.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (isCompute) + { + desc2D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + } + if (isRenderTarget) + { + desc2D.BindFlags |= D3D11_BIND_RENDER_TARGET; + } + if (isDepthStencil) + { + desc2D.BindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + + desc2D.ArraySize = textureCreateInfo->isCube ? 6 : 1; + desc2D.CPUAccessFlags = 0; + desc2D.Format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; + desc2D.MipLevels = textureCreateInfo->levelCount; + desc2D.MiscFlags = ( + (textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT) ? + D3D11_RESOURCE_MISC_GENERATE_MIPS : + 0 + ); + desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; + desc2D.SampleDesc.Quality = 0; + desc2D.Usage = D3D11_USAGE_DEFAULT; + + res = ID3D11Device_CreateTexture2D( + renderer->device, + &desc2D, + NULL, + (ID3D11Texture2D**) &textureHandle + ); + ERROR_CHECK_RETURN("Could not create Texture2D", NULL); + + /* Create the SRV, if applicable */ + if (isSampler) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = desc2D.Format; + + if (textureCreateInfo->isCube) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = desc2D.MipLevels; + srvDesc.TextureCube.MostDetailedMip = 0; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = desc2D.MipLevels; + srvDesc.Texture2D.MostDetailedMip = 0; + } + + res = ID3D11Device_CreateShaderResourceView( + renderer->device, + textureHandle, + &srvDesc, + &srv + ); + if (FAILED(res)) + { + ID3D11Resource_Release(textureHandle); + D3D11_INTERNAL_LogError(renderer->device, "Could not create SRV for 2D texture", res); + return NULL; + } + } + } + else + { + D3D11_TEXTURE3D_DESC desc3D; + + desc3D.Width = textureCreateInfo->width; + desc3D.Height = textureCreateInfo->height; + desc3D.Depth = textureCreateInfo->depth; + + desc3D.BindFlags = 0; + if (isSampler) + { + desc3D.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (isCompute) + { + desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + } + + desc3D.CPUAccessFlags = 0; + desc3D.Format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; + desc3D.MipLevels = textureCreateInfo->levelCount; + desc3D.MiscFlags = 0; + desc3D.Usage = D3D11_USAGE_DEFAULT; + + res = ID3D11Device_CreateTexture3D( + renderer->device, + &desc3D, + NULL, + (ID3D11Texture3D**) &textureHandle + ); + ERROR_CHECK_RETURN("Could not create Texture3D", NULL); + + /* Create the SRV, if applicable */ + if (isSampler) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + + srvDesc.Format = desc3D.Format; + srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE3D; + srvDesc.Texture3D.MipLevels = desc3D.MipLevels; + srvDesc.Texture3D.MostDetailedMip = 0; + + if (FAILED(res)) + { + ID3D11Resource_Release(textureHandle); + D3D11_INTERNAL_LogError(renderer->device, "Could not create SRV for 3D texture", res); + return NULL; + } + } + } + + /* Create the RTV or DSV, if applicable */ + if (isRenderTarget) + { + NOT_IMPLEMENTED + } + else if (isDepthStencil) + { + NOT_IMPLEMENTED + } + + d3d11Texture = (D3D11Texture*) SDL_malloc(sizeof(D3D11Texture)); + d3d11Texture->handle = textureHandle; + d3d11Texture->format = textureCreateInfo->format; + d3d11Texture->width = textureCreateInfo->width; + d3d11Texture->height = textureCreateInfo->height; + d3d11Texture->depth = textureCreateInfo->depth; + d3d11Texture->levelCount = textureCreateInfo->levelCount; + d3d11Texture->isCube = textureCreateInfo->isCube; + d3d11Texture->targetView = isRenderTarget ? (ID3D11View*) rtv : (ID3D11View*) dsv; + d3d11Texture->shaderView = srv; + + return (Refresh_Texture*) d3d11Texture; } static Refresh_Buffer* D3D11_CreateBuffer( @@ -1167,7 +1363,41 @@ static void D3D11_SetTextureData( void *data, uint32_t dataLengthInBytes ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Texture *d3d11Texture = (D3D11Texture*) textureSlice->texture; + + int32_t w = textureSlice->rectangle.w; + int32_t h = textureSlice->rectangle.h; + + int32_t blockSize = Texture_GetBlockSize(d3d11Texture->format); + if (blockSize > 1) + { + w = (w + blockSize - 1) & ~(blockSize - 1); + h = (h + blockSize - 1) & ~(blockSize - 1); + } + + D3D11_BOX dstBox; + dstBox.left = textureSlice->rectangle.x; + dstBox.top = textureSlice->rectangle.y; + dstBox.front = textureSlice->depth; + dstBox.right = textureSlice->rectangle.x + w; + dstBox.bottom = textureSlice->rectangle.y + h; + dstBox.back = textureSlice->depth + 1; + + ID3D11DeviceContext_UpdateSubresource( + d3d11CommandBuffer->context, + d3d11Texture->handle, + D3D11_INTERNAL_CalcSubresource( + textureSlice->level, + textureSlice->layer, + d3d11Texture->levelCount + ), + &dstBox, + data, + BytesPerRow(w, d3d11Texture->format), + BytesPerImage(w, h, d3d11Texture->format) + ); } static void D3D11_SetTextureDataYUV( @@ -1292,7 +1522,32 @@ static void D3D11_BindFragmentSamplers( Refresh_Texture **pTextures, Refresh_Sampler **pSamplers ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + ID3D11ShaderResourceView* srvs[MAX_TEXTURE_SAMPLERS]; + ID3D11SamplerState* d3d11Samplers[MAX_TEXTURE_SAMPLERS]; + + int32_t numFragmentSamplers = d3d11CommandBuffer->graphicsPipeline->numFragmentSamplers; + + for (int32_t i = 0; i < numFragmentSamplers; i += 1) + { + srvs[i] = ((D3D11Texture*) pTextures[i])->shaderView; + d3d11Samplers[i] = ((D3D11Sampler*) pSamplers[i])->handle; + } + + ID3D11DeviceContext_PSSetShaderResources( + d3d11CommandBuffer->context, + 0, + numFragmentSamplers, + srvs + ); + + ID3D11DeviceContext_PSSetSamplers( + d3d11CommandBuffer->context, + 0, + numFragmentSamplers, + d3d11Samplers + ); } /* Getters */ @@ -1312,7 +1567,9 @@ static void D3D11_QueueDestroyTexture( Refresh_Renderer *driverData, Refresh_Texture *texture ) { - NOT_IMPLEMENTED + D3D11Texture *d3d11Texture = (D3D11Texture*) texture; + ID3D11Resource_Release(d3d11Texture->handle); + SDL_free(d3d11Texture); } static void D3D11_QueueDestroySampler( @@ -1502,13 +1759,14 @@ static void D3D11_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { /* FIXME: Cube RTs */ - d3d11CommandBuffer->rtViews[i] = (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->twod.targetView; + + d3d11CommandBuffer->rtViews[i] = (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->targetView; } /* Get the DSV for the depth stencil attachment, if applicable */ if (depthStencilAttachmentInfo != NULL) { - d3d11CommandBuffer->dsView = (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->twod.targetView; + d3d11CommandBuffer->dsView = (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->targetView; } /* Actually set the RTs */ @@ -1531,7 +1789,7 @@ static void D3D11_BeginRenderPass( ID3D11DeviceContext_ClearRenderTargetView( d3d11CommandBuffer->context, - (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->twod.targetView, + (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->targetView, clearColors ); } @@ -1553,7 +1811,7 @@ static void D3D11_BeginRenderPass( { ID3D11DeviceContext_ClearDepthStencilView( d3d11CommandBuffer->context, - (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->twod.targetView, + (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->targetView, dsClearFlags, depthStencilAttachmentInfo->depthStencilClearValue.depth, (uint8_t) depthStencilAttachmentInfo->depthStencilClearValue.stencil @@ -1564,8 +1822,8 @@ static void D3D11_BeginRenderPass( /* Set default viewport and scissor state */ viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->twod.width; - viewport.Height = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->twod.height; + viewport.Width = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->width; + viewport.Height = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->height; viewport.MinDepth = 0; viewport.MaxDepth = 1; @@ -1727,7 +1985,16 @@ static void D3D11_BindIndexBuffer( uint64_t offset, Refresh_IndexElementSize indexElementSize ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + + ID3D11DeviceContext_IASetIndexBuffer( + d3d11CommandBuffer->context, + d3d11Buffer->handle, + RefreshToD3D11_IndexType[indexElementSize], + (UINT) offset + ); } /* Compute State */ @@ -1795,7 +2062,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( renderer->device, (ID3D11Resource*) swapchainTexture, &rtvDesc, - (ID3D11RenderTargetView**) &pTexture->twod.targetView + (ID3D11RenderTargetView**) &pTexture->targetView ); if (FAILED(res)) { @@ -1807,13 +2074,13 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( /* Fill out the rest of the texture struct */ pTexture->handle = NULL; pTexture->shaderView = NULL; - pTexture->isRenderTarget = 1; - pTexture->rtType = REFRESH_D3D11_RENDERTARGET_2D; + pTexture->depth = 1; + pTexture->isCube = 0; ID3D11Texture2D_GetDesc(swapchainTexture, &textureDesc); pTexture->levelCount = textureDesc.MipLevels; - pTexture->twod.width = textureDesc.Width; - pTexture->twod.height = textureDesc.Height; + pTexture->width = textureDesc.Width; + pTexture->height = textureDesc.Height; /* Cleanup */ ID3D11Texture2D_Release(swapchainTexture); @@ -1933,7 +2200,7 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( HRESULT res; /* Release the old RTV */ - ID3D11RenderTargetView_Release(swapchainData->texture.twod.targetView); + ID3D11RenderTargetView_Release(swapchainData->texture.targetView); /* Resize the swapchain */ res = IDXGISwapChain_ResizeBuffers( @@ -1972,7 +2239,7 @@ static void D3D11_INTERNAL_DestroySwapchain( return; } - ID3D11RenderTargetView_Release(swapchainData->texture.twod.targetView); + ID3D11RenderTargetView_Release(swapchainData->texture.targetView); IDXGISwapChain_Release(swapchainData->swapchain); windowData->swapchainData = NULL; @@ -2107,8 +2374,8 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( d3d11CommandBuffer->swapchainData = swapchainData; /* Send the dimensions to the out parameters. */ - *pWidth = swapchainData->texture.twod.width; - *pHeight = swapchainData->texture.twod.height; + *pWidth = swapchainData->texture.width; + *pHeight = swapchainData->texture.height; /* Return the swapchain texture */ return (Refresh_Texture*) &swapchainData->texture; -- 2.25.1 From 94c2d15895a0846f937536278eae25d955400984 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 21:39:15 -0500 Subject: [PATCH 25/69] Fix command buffer memory leak --- src/Refresh_Driver_D3D11.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 9b47552..2b8ef9c 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2483,8 +2483,6 @@ static void D3D11_Submit( renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d11CommandBuffer; renderer->submittedCommandBufferCount += 1; - SDL_UnlockMutex(renderer->contextLock); - /* Present, if applicable */ if (d3d11CommandBuffer->swapchainData) { @@ -2495,6 +2493,27 @@ static void D3D11_Submit( ); } + /* Check if we can perform any cleanups */ + for (int32_t i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) + { + BOOL queryData; + + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->completionQuery, + &queryData, + sizeof(queryData), + 0 + ); + if (res == S_OK) + { + D3D11_INTERNAL_CleanCommandBuffer( + renderer, + renderer->submittedCommandBuffers[i] + ); + } + } + SDL_UnlockMutex(renderer->contextLock); } -- 2.25.1 From 991b37c0064b81ed5594e6d379a15db5f6f3826b Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 23:03:05 -0500 Subject: [PATCH 26/69] Fix texture conversion array --- src/Refresh_Driver_D3D11.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 2b8ef9c..bc40a74 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -112,28 +112,35 @@ static DXGI_FORMAT RefreshToD3D11_TextureFormat[] = { DXGI_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */ DXGI_FORMAT_B8G8R8A8_UNORM, /* B8G8R8A8 */ - DXGI_FORMAT_B5G6R5_UNORM, /* R5G6B5 */ - DXGI_FORMAT_B5G5R5A1_UNORM, /* A1R5G5B5 */ + DXGI_FORMAT_B5G6R5_UNORM, /* R5G6B5 */ /* FIXME: Swizzle? */ + DXGI_FORMAT_B5G5R5A1_UNORM, /* A1R5G5B5 */ /* FIXME: Swizzle? */ 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_BC1_UNORM, /* BC1 */ + DXGI_FORMAT_BC2_UNORM, /* BC2 */ + DXGI_FORMAT_BC3_UNORM, /* BC3 */ + DXGI_FORMAT_BC7_UNORM, /* BC7 */ + DXGI_FORMAT_R8G8_SNORM, /* R8G8_SNORM */ + DXGI_FORMAT_R8G8B8A8_SNORM, /* R8G8B8A8_SNORM */ 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 */ + DXGI_FORMAT_R32_FLOAT, /* R32_SFLOAT */ + DXGI_FORMAT_R32G32_FLOAT, /* R32G32_SFLOAT */ + DXGI_FORMAT_R32G32B32A32_FLOAT, /* R32G32B32A32_SFLOAT */ + DXGI_FORMAT_R8_UINT, /* R8_UINT */ + DXGI_FORMAT_R8G8_UINT, /* R8G8_UINT */ + DXGI_FORMAT_R8G8B8A8_UINT, /* R8G8B8A8_UINT */ + DXGI_FORMAT_R16_UINT, /* R16_UINT */ + DXGI_FORMAT_R16G16_UINT, /* R16G16_UINT */ + DXGI_FORMAT_R16G16B16A16_UINT, /* R16G16B16A16_UINT */ + DXGI_FORMAT_D16_UNORM, /* D16_UNORM */ + DXGI_FORMAT_D32_FLOAT, /* D32_SFLOAT */ + DXGI_FORMAT_D24_UNORM_S8_UINT, /* D16_UNORM_S8_UINT */ + DXGI_FORMAT_D32_FLOAT_S8X24_UINT/* D32_SFLOAT_S8_UINT */ }; static DXGI_FORMAT RefreshToD3D11_VertexFormat[] = -- 2.25.1 From 53128e0b660d047e0cf120c7e5a2d8afb2553a58 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 5 Nov 2023 14:17:23 -0600 Subject: [PATCH 27/69] Uniform buffer infrastructure, still missing offset support --- src/Refresh_Driver_D3D11.c | 480 ++++++++++++++++++++++++++++++------- 1 file changed, 397 insertions(+), 83 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index bc40a74..da09189 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -47,6 +47,7 @@ #define D3DCOMPILE_FUNC "D3DCompile" #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" #define WINDOW_DATA "Refresh_D3D11WindowData" +#define UBO_BUFFER_SIZE 16000 /* 16KB */ #define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!"); @@ -406,11 +407,25 @@ typedef struct D3D11GraphicsPipeline ID3D11InputLayout *inputLayout; uint32_t *vertexStrides; uint32_t numVertexSamplers; + uint32_t vertexUniformBlockSize; ID3D11PixelShader *fragmentShader; uint32_t numFragmentSamplers; + uint32_t fragmentUniformBlockSize; } D3D11GraphicsPipeline; +typedef struct D3D11Buffer +{ + ID3D11Buffer *handle; + uint32_t size; +} D3D11Buffer; + +typedef struct D3D11UniformBuffer +{ + D3D11Buffer *d3d11Buffer; + uint32_t offset; +} D3D11UniformBuffer; + typedef struct D3D11CommandBuffer { /* D3D11 Object References */ @@ -425,21 +440,16 @@ typedef struct D3D11CommandBuffer /* State */ SDL_threadID threadID; ID3D11Query *completionQuery; + + /* Uniforms */ + D3D11UniformBuffer *vertexUniformBuffer; + D3D11UniformBuffer *fragmentUniformBuffer; + + D3D11UniformBuffer **boundUniformBuffers; + uint32_t boundUniformBufferCount; + uint32_t boundUniformBufferCapacity; } D3D11CommandBuffer; -typedef struct D3D11CommandBufferPool -{ - D3D11CommandBuffer **elements; - uint32_t count; - uint32_t capacity; -} D3D11CommandBufferPool; - -typedef struct D3D11Buffer -{ - ID3D11Buffer *handle; - uint32_t size; -} D3D11Buffer; - typedef struct D3D11Sampler { ID3D11SamplerState *handle; @@ -463,14 +473,21 @@ typedef struct D3D11Renderer uint32_t claimedWindowCount; uint32_t claimedWindowCapacity; - D3D11CommandBufferPool commandBufferPool; - - SDL_mutex *contextLock; - SDL_mutex *acquireCommandBufferLock; + D3D11CommandBuffer **availableCommandBuffers; + uint32_t availableCommandBufferCount; + uint32_t availableCommandBufferCapacity; D3D11CommandBuffer **submittedCommandBuffers; uint32_t submittedCommandBufferCount; uint32_t submittedCommandBufferCapacity; + + D3D11UniformBuffer **availableUniformBuffers; + uint32_t availableUniformBufferCount; + uint32_t availableUniformBufferCapacity; + + SDL_mutex *contextLock; + SDL_mutex *acquireCommandBufferLock; + SDL_mutex *uniformBufferLock; } D3D11Renderer; /* Logging */ @@ -547,45 +564,51 @@ static void D3D11_DestroyDevice( Refresh_Device *device ) { D3D11Renderer *renderer = (D3D11Renderer*) device->driverData; - D3D11CommandBuffer *commandBuffer; + /* Flush any remaining GPU work... */ D3D11_Wait(device->driverData); /* Release the window data */ - for (int32_t i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) { D3D11_UnclaimWindow(device->driverData, renderer->claimedWindows[i]->windowHandle); } - SDL_free(renderer->claimedWindows); - D3D11_Wait(device->driverData); /* FIXME: Copied this from Vulkan, is it actually necessary? */ + /* FIXME: Copied this from Vulkan, is it actually necessary? */ + D3D11_Wait(device->driverData); /* Release command buffer infrastructure */ - - SDL_free(renderer->submittedCommandBuffers); - - for (uint32_t i = 0; i < renderer->commandBufferPool.count; i += 1) + for (uint32_t i = 0; i < renderer->availableCommandBufferCount; i += 1) { - commandBuffer = renderer->commandBufferPool.elements[i]; - + D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i]; ID3D11Query_Release(commandBuffer->completionQuery); ID3D11DeviceContext_Release(commandBuffer->context); - SDL_free(commandBuffer); } + SDL_free(renderer->availableCommandBuffers); + SDL_free(renderer->submittedCommandBuffers); + + /* Release uniform buffer infrastructure */ + for (uint32_t i = 0; i < renderer->availableUniformBufferCount; i += 1) + { + D3D11UniformBuffer *uniformBuffer = renderer->availableUniformBuffers[i]; + ID3D11Buffer_Release(uniformBuffer->d3d11Buffer->handle); + SDL_free(uniformBuffer->d3d11Buffer); + SDL_free(uniformBuffer); + } + SDL_free(renderer->availableCommandBuffers); /* Release the mutexes */ - SDL_DestroyMutex(renderer->acquireCommandBufferLock); SDL_DestroyMutex(renderer->contextLock); + SDL_DestroyMutex(renderer->uniformBufferLock); - /* Release the DLLs and D3D11 device infrastructure */ - + /* Release the DLLs */ SDL_UnloadObject(renderer->d3d11_dll); SDL_UnloadObject(renderer->d3dcompiler_dll); + /* Release the device and associated objects */ ID3D11DeviceContext_Release(renderer->immediateContext); ID3D11Device_Release(renderer->device); IDXGIAdapter_Release(renderer->adapter); @@ -609,6 +632,26 @@ static void D3D11_DrawInstancedPrimitives( ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + if (d3d11CommandBuffer->vertexUniformBuffer != NULL) + { + ID3D11DeviceContext_VSSetConstantBuffers( + d3d11CommandBuffer->context, + 0, + 1, + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle + ); + } + + if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) + { + ID3D11DeviceContext_PSSetConstantBuffers( + d3d11CommandBuffer->context, + 0, + 1, + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle + ); + } + ID3D11DeviceContext_DrawIndexedInstanced( d3d11CommandBuffer->context, PrimitiveVerts(d3d11CommandBuffer->graphicsPipeline->primitiveType, primitiveCount), @@ -652,13 +695,31 @@ static void D3D11_DrawPrimitives( ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + if (d3d11CommandBuffer->vertexUniformBuffer != NULL) + { + ID3D11DeviceContext_VSSetConstantBuffers( + d3d11CommandBuffer->context, + 0, + 1, + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle + ); + } + + if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) + { + ID3D11DeviceContext_PSSetConstantBuffers( + d3d11CommandBuffer->context, + 0, + 1, + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle + ); + } + ID3D11DeviceContext_Draw( d3d11CommandBuffer->context, PrimitiveVerts(d3d11CommandBuffer->graphicsPipeline->primitiveType, primitiveCount), vertexStart ); - - /* FIXME: vertex/fragment param offsets */ } static void D3D11_DrawPrimitivesIndirect( @@ -983,7 +1044,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( NULL, NULL, NULL, - "main", + "main", /* FIXME: Is this correct or should this be vertexShaderInfo.entryPoint? */ "vs_5_0", 0, 0, @@ -1007,6 +1068,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( } pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shader; pipeline->numVertexSamplers = pipelineCreateInfo->vertexShaderInfo.samplerBindingCount; + pipeline->vertexUniformBlockSize = (uint32_t) pipelineCreateInfo->vertexShaderInfo.uniformBufferSize; /* Input Layout */ @@ -1045,7 +1107,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( NULL, NULL, NULL, - "main", + "main", /* FIXME: Is this correct or should this be fragmentShaderInfo.entryPoint? */ "ps_5_0", 0, 0, @@ -1069,8 +1131,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( } pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader; pipeline->numFragmentSamplers = pipelineCreateInfo->fragmentShaderInfo.samplerBindingCount; - - /* FIXME: Need to create uniform buffers for the shaders */ + pipeline->fragmentUniformBlockSize = (uint32_t) pipelineCreateInfo->fragmentShaderInfo.uniformBufferSize; return (Refresh_GraphicsPipeline*) pipeline; } @@ -1447,25 +1508,23 @@ static void D3D11_CopyTextureToBuffer( NOT_IMPLEMENTED } -static void D3D11_SetBufferData( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer *buffer, +static void D3D11_INTERNAL_SetBufferData( + D3D11Renderer *renderer, + D3D11CommandBuffer *commandBuffer, + D3D11Buffer *buffer, uint32_t offsetInBytes, void* data, - uint32_t dataLength + uint32_t dataLength, + uint8_t noOverwrite ) { - D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; - D3D11_MAPPED_SUBRESOURCE subres = { 0 }; + D3D11_MAPPED_SUBRESOURCE subres; HRESULT res; res = ID3D11DeviceContext_Map( - d3d11CommandBuffer->context, - (ID3D11Resource*) d3d11Buffer->handle, + commandBuffer->context, + (ID3D11Resource*) buffer->handle, 0, - D3D11_MAP_WRITE_DISCARD, + noOverwrite ? D3D11_MAP_WRITE_NO_OVERWRITE : D3D11_MAP_WRITE_DISCARD, 0, &subres ); @@ -1478,20 +1537,156 @@ static void D3D11_SetBufferData( ); ID3D11DeviceContext_Unmap( - d3d11CommandBuffer->context, - (ID3D11Resource*) d3d11Buffer->handle, + commandBuffer->context, + (ID3D11Resource*) buffer->handle, 0 ); } +static void D3D11_SetBufferData( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_Buffer *buffer, + uint32_t offsetInBytes, + void* data, + uint32_t dataLength +) { + D3D11_INTERNAL_SetBufferData( + (D3D11Renderer*) driverData, + (D3D11CommandBuffer*) commandBuffer, + (D3D11Buffer*) buffer, + offsetInBytes, + data, + dataLength, + 0 + ); +} + +static void D3D11_INTERNAL_BindUniformBuffer( + D3D11CommandBuffer *commandBuffer, + D3D11UniformBuffer *uniformBuffer +) { + if (commandBuffer->boundUniformBufferCount >= commandBuffer->boundUniformBufferCapacity) + { + commandBuffer->boundUniformBufferCapacity *= 2; + commandBuffer->boundUniformBuffers = SDL_realloc( + commandBuffer->boundUniformBuffers, + sizeof(D3D11UniformBuffer*) * commandBuffer->boundUniformBufferCapacity + ); + } + + commandBuffer->boundUniformBuffers[commandBuffer->boundUniformBufferCount] = uniformBuffer; + commandBuffer->boundUniformBufferCount += 1; +} + +static uint8_t D3D11_INTERNAL_CreateUniformBuffer( + D3D11Renderer *renderer +) { + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc.ByteWidth = UBO_BUFFER_SIZE; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + + ID3D11Buffer *bufferHandle; + HRESULT res = ID3D11Device_CreateBuffer( + renderer->device, + &bufferDesc, + NULL, + &bufferHandle + ); + ERROR_CHECK_RETURN("Failed to create uniform buffer", 0); + + D3D11UniformBuffer *uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer)); + uniformBuffer->offset = 0; + uniformBuffer->d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); + uniformBuffer->d3d11Buffer->handle = bufferHandle; + uniformBuffer->d3d11Buffer->size = UBO_BUFFER_SIZE; + + /* Add it to the available pool */ + if (renderer->availableUniformBufferCount >= renderer->availableUniformBufferCapacity) + { + renderer->availableUniformBufferCapacity *= 2; + + renderer->availableUniformBuffers = SDL_realloc( + renderer->availableUniformBuffers, + sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity + ); + } + + renderer->availableUniformBuffers[renderer->availableUniformBufferCount] = uniformBuffer; + renderer->availableUniformBufferCount += 1; + + return 1; +} + +static D3D11UniformBuffer* D3D11_INTERNAL_AcquireUniformBufferFromPool( + D3D11Renderer *renderer, + uint64_t blockSize +) { + SDL_LockMutex(renderer->uniformBufferLock); + + if (renderer->availableUniformBufferCount == 0) + { + if (!D3D11_INTERNAL_CreateUniformBuffer(renderer)) + { + SDL_UnlockMutex(renderer->uniformBufferLock); + Refresh_LogError("Failed to create uniform buffer!"); + return NULL; + } + } + + D3D11UniformBuffer *uniformBuffer = renderer->availableUniformBuffers[renderer->availableUniformBufferCount - 1]; + renderer->availableUniformBufferCount -= 1; + + SDL_UnlockMutex(renderer->uniformBufferLock); + + uniformBuffer->offset = 0; + + return uniformBuffer; +} + static uint32_t D3D11_PushVertexShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *data, uint32_t dataLengthInBytes ) { - NOT_IMPLEMENTED - return 0; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11GraphicsPipeline *graphicsPipeline = d3d11CommandBuffer->graphicsPipeline; + uint32_t offset; + + if (d3d11CommandBuffer->vertexUniformBuffer->offset + graphicsPipeline->vertexUniformBlockSize >= UBO_BUFFER_SIZE) + { + /* We're out of space in this buffer, bind the old one and acquire a new one */ + D3D11_INTERNAL_BindUniformBuffer( + d3d11CommandBuffer, + d3d11CommandBuffer->vertexUniformBuffer + ); + d3d11CommandBuffer->vertexUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + renderer, + graphicsPipeline->vertexUniformBlockSize + ); + } + + offset = d3d11CommandBuffer->vertexUniformBuffer->offset; + + D3D11_INTERNAL_SetBufferData( + renderer, + d3d11CommandBuffer, + d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer, + d3d11CommandBuffer->vertexUniformBuffer->offset, + data, + dataLengthInBytes, + 0 + ); + + d3d11CommandBuffer->vertexUniformBuffer->offset += graphicsPipeline->vertexUniformBlockSize; + + return offset; } static uint32_t D3D11_PushFragmentShaderUniforms( @@ -1500,8 +1695,39 @@ static uint32_t D3D11_PushFragmentShaderUniforms( void *data, uint32_t dataLengthInBytes ) { - NOT_IMPLEMENTED - return 0; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11GraphicsPipeline *graphicsPipeline = d3d11CommandBuffer->graphicsPipeline; + uint32_t offset; + + if (d3d11CommandBuffer->fragmentUniformBuffer->offset + graphicsPipeline->fragmentUniformBlockSize >= UBO_BUFFER_SIZE) + { + /* We're out of space in this buffer, bind the old one and acquire a new one */ + D3D11_INTERNAL_BindUniformBuffer( + d3d11CommandBuffer, + d3d11CommandBuffer->fragmentUniformBuffer + ); + d3d11CommandBuffer->fragmentUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + renderer, + graphicsPipeline->fragmentUniformBlockSize + ); + } + + offset = d3d11CommandBuffer->fragmentUniformBuffer->offset; + + D3D11_INTERNAL_SetBufferData( + renderer, + d3d11CommandBuffer, + d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer, + d3d11CommandBuffer->fragmentUniformBuffer->offset, + data, + dataLengthInBytes, + 0 + ); + + d3d11CommandBuffer->fragmentUniformBuffer->offset += graphicsPipeline->fragmentUniformBlockSize; + + return offset; } static uint32_t D3D11_PushComputeShaderUniforms( @@ -1651,22 +1877,22 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( D3D11Renderer *renderer, uint32_t allocateCount ) { - D3D11CommandBufferPool *pool = &renderer->commandBufferPool; D3D11CommandBuffer *commandBuffer; D3D11_QUERY_DESC queryDesc; HRESULT res; - pool->capacity += allocateCount; + renderer->availableCommandBufferCapacity += allocateCount; - pool->elements = SDL_realloc( - pool->elements, - sizeof(D3D11CommandBuffer*) * pool->capacity + renderer->availableCommandBuffers = SDL_realloc( + renderer->availableCommandBuffers, + sizeof(D3D11CommandBuffer*) * renderer->availableCommandBufferCapacity ); for (uint32_t i = 0; i < allocateCount; i += 1) { commandBuffer = SDL_malloc(sizeof(D3D11CommandBuffer)); + /* Deferred Device Context */ res = ID3D11Device_CreateDeferredContext( renderer->device, 0, @@ -1674,6 +1900,7 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( ); ERROR_CHECK("Could not create deferred context"); + /* Fence Query */ queryDesc.Query = D3D11_QUERY_EVENT; queryDesc.MiscFlags = 0; res = ID3D11Device_CreateQuery( @@ -1683,29 +1910,35 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( ); ERROR_CHECK("Could not create query"); + /* Bound Uniform Buffers */ + commandBuffer->boundUniformBufferCapacity = 16; + commandBuffer->boundUniformBufferCount = 0; + commandBuffer->boundUniformBuffers = SDL_malloc( + commandBuffer->boundUniformBufferCapacity * sizeof(D3D11UniformBuffer*) + ); + /* FIXME: Resource tracking? */ - pool->elements[pool->count] = commandBuffer; - pool->count += 1; + renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; + renderer->availableCommandBufferCount += 1; } } static D3D11CommandBuffer* D3D11_INTERNAL_GetInactiveCommandBufferFromPool( D3D11Renderer *renderer ) { - D3D11CommandBufferPool *pool = &renderer->commandBufferPool; D3D11CommandBuffer *commandBuffer; - if (pool->count == 0) + if (renderer->availableCommandBufferCount == 0) { D3D11_INTERNAL_AllocateCommandBuffers( renderer, - pool->capacity + renderer->availableCommandBufferCapacity ); } - commandBuffer = pool->elements[pool->count - 1]; - pool->count -= 1; + commandBuffer = renderer->availableCommandBuffers[renderer->availableCommandBufferCount - 1]; + renderer->availableCommandBufferCount -= 1; return commandBuffer; } @@ -1723,8 +1956,9 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer); commandBuffer->threadID = SDL_ThreadID(); commandBuffer->swapchainData = NULL; - commandBuffer->dsView = NULL; commandBuffer->graphicsPipeline = NULL; + commandBuffer->vertexUniformBuffer = NULL; + commandBuffer->dsView = NULL; for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { commandBuffer->rtViews[i] = NULL; @@ -1856,6 +2090,26 @@ static void D3D11_EndRenderPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer ) { + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + + if (d3d11CommandBuffer->vertexUniformBuffer != NULL) + { + D3D11_INTERNAL_BindUniformBuffer( + d3d11CommandBuffer, + d3d11CommandBuffer->vertexUniformBuffer + ); + } + d3d11CommandBuffer->vertexUniformBuffer = NULL; + + if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) + { + D3D11_INTERNAL_BindUniformBuffer( + d3d11CommandBuffer, + d3d11CommandBuffer->fragmentUniformBuffer + ); + } + d3d11CommandBuffer->fragmentUniformBuffer = NULL; + /* FIXME: Resolve MSAA here! */ /* FIXME: Anything else we need to do...? */ } @@ -1871,6 +2125,46 @@ static void D3D11_BindGraphicsPipeline( d3d11CommandBuffer->graphicsPipeline = pipeline; + if (d3d11CommandBuffer->vertexUniformBuffer != NULL) + { + D3D11_INTERNAL_BindUniformBuffer( + d3d11CommandBuffer, + d3d11CommandBuffer->vertexUniformBuffer + ); + } + + if (pipeline->vertexUniformBlockSize == 0) + { + d3d11CommandBuffer->vertexUniformBuffer = NULL; + } + else + { + d3d11CommandBuffer->vertexUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + renderer, + pipeline->vertexUniformBlockSize + ); + } + + if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) + { + D3D11_INTERNAL_BindUniformBuffer( + d3d11CommandBuffer, + d3d11CommandBuffer->fragmentUniformBuffer + ); + } + + if (pipeline->fragmentUniformBlockSize == 0) + { + d3d11CommandBuffer->fragmentUniformBuffer = NULL; + } + else + { + d3d11CommandBuffer->fragmentUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + renderer, + pipeline->fragmentUniformBlockSize + ); + } + ID3D11DeviceContext_OMSetBlendState( d3d11CommandBuffer->context, pipeline->colorAttachmentBlendState, @@ -2409,29 +2703,47 @@ static void D3D11_INTERNAL_CleanCommandBuffer( D3D11Renderer *renderer, D3D11CommandBuffer *commandBuffer ) { - D3D11CommandBufferPool *commandBufferPool = &renderer->commandBufferPool; - uint32_t i; - /* FIXME: All kinds of stuff should go here... */ + /* Bound uniform buffers are now available */ + SDL_LockMutex(renderer->uniformBufferLock); + for (uint32_t i = 0; i < commandBuffer->boundUniformBufferCount; i += 1) + { + if (renderer->availableUniformBufferCount == renderer->availableUniformBufferCapacity) + { + renderer->availableUniformBufferCapacity *= 2; + renderer->availableUniformBuffers = SDL_realloc( + renderer->availableUniformBuffers, + renderer->availableUniformBufferCapacity * sizeof(D3D11UniformBuffer*) + ); + } + + renderer->availableUniformBuffers[renderer->availableUniformBufferCount] = commandBuffer->boundUniformBuffers[i]; + renderer->availableUniformBufferCount += 1; + } + SDL_UnlockMutex(renderer->uniformBufferLock); + + commandBuffer->boundUniformBufferCount = 0; + + /* Return command buffer to pool */ SDL_LockMutex(renderer->acquireCommandBufferLock); - if (commandBufferPool->count == commandBufferPool->capacity) + if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) { - commandBufferPool->capacity += 1; - commandBufferPool->elements = SDL_realloc( - commandBufferPool->elements, - commandBufferPool->capacity * sizeof(D3D11CommandBuffer*) + renderer->availableCommandBufferCapacity += 1; + renderer->availableCommandBuffers = SDL_realloc( + renderer->availableCommandBuffers, + renderer->availableCommandBufferCapacity * sizeof(D3D11CommandBuffer*) ); } - commandBufferPool->elements[commandBufferPool->count] = commandBuffer; - commandBufferPool->count += 1; + renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; + renderer->availableCommandBufferCount += 1; SDL_UnlockMutex(renderer->acquireCommandBufferLock); /* Remove this command buffer from the submitted list */ - for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) + for (uint32_t i = 0; i < renderer->submittedCommandBufferCount; i += 1) { if (renderer->submittedCommandBuffers[i] == commandBuffer) { @@ -2700,7 +3012,7 @@ static Refresh_Device* D3D11_CreateDevice( D3D11Renderer *renderer; PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; - D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 }; + D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 }; IDXGIFactory6 *factory6; uint32_t flags; DXGI_ADAPTER_DESC1 adapterDesc; @@ -2838,12 +3150,10 @@ tryCreateDevice: Refresh_LogInfo("Refresh Driver: D3D11"); Refresh_LogInfo("D3D11 Adapter: %S", adapterDesc.Description); - /* Initialize the command buffer pool */ - renderer->commandBufferPool = (D3D11CommandBufferPool) { 0 }; - /* Create mutexes */ renderer->contextLock = SDL_CreateMutex(); renderer->acquireCommandBufferLock = SDL_CreateMutex(); + renderer->uniformBufferLock = SDL_CreateMutex(); /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); @@ -2851,6 +3161,10 @@ tryCreateDevice: /* Create command buffers to initialize the pool */ D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2); + /* Create uniform buffer pool */ + renderer->availableUniformBufferCapacity = 2; + renderer->availableUniformBuffers = SDL_malloc(sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity); + /* Create the Refresh Device */ result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); ASSIGN_DRIVER(D3D11) -- 2.25.1 From 641abe4bb5c1f9923080ad2265ea3364593cb9b8 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 5 Nov 2023 19:20:37 -0600 Subject: [PATCH 28/69] Fixed uniform offsets, removed a bunch of code from cdefines.h --- src/Refresh_Driver_D3D11.c | 77 +++++++++--- src/Refresh_Driver_D3D11_cdefines.h | 181 +--------------------------- 2 files changed, 59 insertions(+), 199 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index da09189..113e650 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -30,7 +30,9 @@ #define CINTERFACE #define COBJMACROS #include +#include #include +#include #include #include "Refresh_Driver.h" @@ -429,7 +431,7 @@ typedef struct D3D11UniformBuffer typedef struct D3D11CommandBuffer { /* D3D11 Object References */ - ID3D11DeviceContext *context; + ID3D11DeviceContext1 *context; D3D11SwapchainData *swapchainData; /* Render Pass */ @@ -457,7 +459,7 @@ typedef struct D3D11Sampler typedef struct D3D11Renderer { - ID3D11Device *device; + ID3D11Device1 *device; ID3D11DeviceContext *immediateContext; IDXGIFactory1 *factory; IDXGIAdapter1 *adapter; @@ -493,7 +495,7 @@ typedef struct D3D11Renderer /* Logging */ static void D3D11_INTERNAL_LogError( - ID3D11Device *device, + ID3D11Device1 *device, const char *msg, HRESULT res ) { @@ -631,24 +633,32 @@ static void D3D11_DrawInstancedPrimitives( uint32_t fragmentParamOffset ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + uint32_t vertexOffsetInConstants = vertexParamOffset / 16; + uint32_t fragmentOffsetInConstants = fragmentParamOffset / 16; + uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; + uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; if (d3d11CommandBuffer->vertexUniformBuffer != NULL) { - ID3D11DeviceContext_VSSetConstantBuffers( + ID3D11DeviceContext1_VSSetConstantBuffers1( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle, + &vertexOffsetInConstants, + &vertexBlockSizeInConstants ); } if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) { - ID3D11DeviceContext_PSSetConstantBuffers( + ID3D11DeviceContext1_PSSetConstantBuffers1( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle, + &fragmentOffsetInConstants, + &fragmentBlockSizeInConstants ); } @@ -660,8 +670,6 @@ static void D3D11_DrawInstancedPrimitives( baseVertex, 0 ); - - /* FIXME: vertex/fragment param offsets */ } static void D3D11_DrawIndexedPrimitives( @@ -694,24 +702,32 @@ static void D3D11_DrawPrimitives( uint32_t fragmentParamOffset ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + uint32_t vertexOffsetInConstants = vertexParamOffset / 16; + uint32_t fragmentOffsetInConstants = fragmentParamOffset / 16; + uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; + uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; if (d3d11CommandBuffer->vertexUniformBuffer != NULL) { - ID3D11DeviceContext_VSSetConstantBuffers( + ID3D11DeviceContext1_VSSetConstantBuffers1( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle, + &vertexOffsetInConstants, + &vertexBlockSizeInConstants ); } if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) { - ID3D11DeviceContext_PSSetConstantBuffers( + ID3D11DeviceContext1_PSSetConstantBuffers1( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle, + &fragmentOffsetInConstants, + &fragmentBlockSizeInConstants ); } @@ -975,6 +991,13 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( return NULL; } +static inline uint32_t D3D11_INTERNAL_NextHighestAlignment( + uint32_t n, + uint32_t align +) { + return align * ((n + align - 1) / align); +} + static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( Refresh_Renderer *driverData, Refresh_GraphicsPipelineCreateInfo *pipelineCreateInfo @@ -1068,7 +1091,10 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( } pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shader; pipeline->numVertexSamplers = pipelineCreateInfo->vertexShaderInfo.samplerBindingCount; - pipeline->vertexUniformBlockSize = (uint32_t) pipelineCreateInfo->vertexShaderInfo.uniformBufferSize; + pipeline->vertexUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( + (uint32_t) pipelineCreateInfo->vertexShaderInfo.uniformBufferSize, + 256 + ); /* Input Layout */ @@ -1131,7 +1157,10 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( } pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader; pipeline->numFragmentSamplers = pipelineCreateInfo->fragmentShaderInfo.samplerBindingCount; - pipeline->fragmentUniformBlockSize = (uint32_t) pipelineCreateInfo->fragmentShaderInfo.uniformBufferSize; + pipeline->fragmentUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( + (uint32_t) pipelineCreateInfo->vertexShaderInfo.uniformBufferSize, + 256 + ); return (Refresh_GraphicsPipeline*) pipeline; } @@ -1681,7 +1710,7 @@ static uint32_t D3D11_PushVertexShaderUniforms( d3d11CommandBuffer->vertexUniformBuffer->offset, data, dataLengthInBytes, - 0 + 0 /* FIXME: Should be NoOverwrite! */ ); d3d11CommandBuffer->vertexUniformBuffer->offset += graphicsPipeline->vertexUniformBlockSize; @@ -1722,7 +1751,7 @@ static uint32_t D3D11_PushFragmentShaderUniforms( d3d11CommandBuffer->fragmentUniformBuffer->offset, data, dataLengthInBytes, - 0 + 0 /* FIXME: Should be NoOverwrite! */ ); d3d11CommandBuffer->fragmentUniformBuffer->offset += graphicsPipeline->fragmentUniformBlockSize; @@ -1893,7 +1922,7 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( commandBuffer = SDL_malloc(sizeof(D3D11CommandBuffer)); /* Deferred Device Context */ - res = ID3D11Device_CreateDeferredContext( + res = ID3D11Device1_CreateDeferredContext1( renderer->device, 0, &commandBuffer->context @@ -1958,6 +1987,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->swapchainData = NULL; commandBuffer->graphicsPipeline = NULL; commandBuffer->vertexUniformBuffer = NULL; + commandBuffer->fragmentUniformBuffer = NULL; commandBuffer->dsView = NULL; for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { @@ -3122,6 +3152,7 @@ static Refresh_Device* D3D11_CreateDevice( } /* Create the device */ + ID3D11Device *d3d11Device; tryCreateDevice: res = D3D11CreateDeviceFunc( (IDXGIAdapter*) renderer->adapter, @@ -3131,7 +3162,7 @@ tryCreateDevice: levels, SDL_arraysize(levels), D3D11_SDK_VERSION, - &renderer->device, + &d3d11Device, &renderer->featureLevel, &renderer->immediateContext ); @@ -3146,6 +3177,14 @@ tryCreateDevice: ERROR_CHECK_RETURN("Could not create D3D11 device", NULL); + /* The actual device we want is the ID3D11Device1 interface... */ + res = ID3D11Device_QueryInterface( + d3d11Device, + &D3D_IID_ID3D11Device1, + &renderer->device + ); + ERROR_CHECK_RETURN("Could not get ID3D11Device1 interface", NULL); + /* Print driver info */ Refresh_LogInfo("Refresh Driver: D3D11"); Refresh_LogInfo("D3D11 Adapter: %S", adapterDesc.Description); diff --git a/src/Refresh_Driver_D3D11_cdefines.h b/src/Refresh_Driver_D3D11_cdefines.h index aac92d2..f9361c4 100644 --- a/src/Refresh_Driver_D3D11_cdefines.h +++ b/src/Refresh_Driver_D3D11_cdefines.h @@ -33,183 +33,4 @@ static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78,0xf26f,0x4dba,{0xa8,0x29,0 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_ID3D11Texture2D = { 0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c} }; - -/* IDXGIFactory6 (taken from dxgi1_6.h, cleaned up a bit) */ -typedef enum -{ - DXGI_FEATURE_PRESENT_ALLOW_TEARING = 0 -} DXGI_FEATURE; - -typedef enum -{ - DXGI_GPU_PREFERENCE_UNSPECIFIED = 0, - DXGI_GPU_PREFERENCE_MINIMUM_POWER = (DXGI_GPU_PREFERENCE_UNSPECIFIED + 1), - DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE = (DXGI_GPU_PREFERENCE_MINIMUM_POWER + 1) -} DXGI_GPU_PREFERENCE; - -typedef struct IDXGIFactory6 IDXGIFactory6; -typedef struct IDXGIFactory6Vtbl -{ - HRESULT(STDMETHODCALLTYPE* QueryInterface)( - IDXGIFactory6* This, - REFIID riid, - void** ppvObject); - - ULONG(STDMETHODCALLTYPE* AddRef)( - IDXGIFactory6* This); - - ULONG(STDMETHODCALLTYPE* Release)( - IDXGIFactory6* This); - - HRESULT(STDMETHODCALLTYPE* SetPrivateData)( - IDXGIFactory6* This, - REFGUID Name, - UINT DataSize, - const void* pData); - - HRESULT(STDMETHODCALLTYPE* SetPrivateDataInterface)( - IDXGIFactory6* This, - REFGUID Name, - const IUnknown* pUnknown); - - HRESULT(STDMETHODCALLTYPE* GetPrivateData)( - IDXGIFactory6* This, - REFGUID Name, - UINT* pDataSize, - void* pData); - - HRESULT(STDMETHODCALLTYPE* GetParent)( - IDXGIFactory6* This, - REFIID riid, - void** ppParent); - - HRESULT(STDMETHODCALLTYPE* EnumAdapters)( - IDXGIFactory6* This, - UINT Adapter, - IDXGIAdapter** ppAdapter); - - HRESULT(STDMETHODCALLTYPE* MakeWindowAssociation)( - IDXGIFactory6* This, - HWND WindowHandle, - UINT Flags); - - HRESULT(STDMETHODCALLTYPE* GetWindowAssociation)( - IDXGIFactory6* This, - HWND* pWindowHandle); - - HRESULT(STDMETHODCALLTYPE* CreateSwapChain)( - IDXGIFactory6* This, - IUnknown* pDevice, - DXGI_SWAP_CHAIN_DESC* pDesc, - IDXGISwapChain** ppSwapChain); - - HRESULT(STDMETHODCALLTYPE* CreateSoftwareAdapter)( - IDXGIFactory6* This, - HMODULE Module, - IDXGIAdapter** ppAdapter); - - HRESULT(STDMETHODCALLTYPE* EnumAdapters1)( - IDXGIFactory6* This, - UINT Adapter, - IDXGIAdapter1** ppAdapter); - - BOOL(STDMETHODCALLTYPE* IsCurrent)( - IDXGIFactory6* This); - - BOOL(STDMETHODCALLTYPE* IsWindowedStereoEnabled)( - IDXGIFactory6* This); - - HRESULT(STDMETHODCALLTYPE* CreateSwapChainForHwnd)( - IDXGIFactory6* This, - IUnknown* pDevice, - HWND hWnd, - void* pDesc, - void* pFullscreenDesc, - void* pRestrictToOutput, - void** ppSwapChain); - - HRESULT(STDMETHODCALLTYPE* CreateSwapChainForCoreWindow)( - IDXGIFactory6* This, - IUnknown* pDevice, - IUnknown* pWindow, - void* pDesc, - void* pRestrictToOutput, - void** ppSwapChain); - - HRESULT(STDMETHODCALLTYPE* GetSharedResourceAdapterLuid)( - IDXGIFactory6* This, - HANDLE hResource, - LUID* pLuid); - - HRESULT(STDMETHODCALLTYPE* RegisterStereoStatusWindow)( - IDXGIFactory6* This, - HWND WindowHandle, - UINT wMsg, - DWORD* pdwCookie); - - HRESULT(STDMETHODCALLTYPE* RegisterStereoStatusEvent)( - IDXGIFactory6* This, - HANDLE hEvent, - DWORD* pdwCookie); - - void (STDMETHODCALLTYPE* UnregisterStereoStatus)( - IDXGIFactory6* This, - DWORD dwCookie); - - HRESULT(STDMETHODCALLTYPE* RegisterOcclusionStatusWindow)( - IDXGIFactory6* This, - HWND WindowHandle, - UINT wMsg, - DWORD* pdwCookie); - - HRESULT(STDMETHODCALLTYPE* RegisterOcclusionStatusEvent)( - IDXGIFactory6* This, - HANDLE hEvent, - DWORD* pdwCookie); - - void (STDMETHODCALLTYPE* UnregisterOcclusionStatus)( - IDXGIFactory6* This, - DWORD dwCookie); - - HRESULT(STDMETHODCALLTYPE* CreateSwapChainForComposition)( - IDXGIFactory6* This, - IUnknown* pDevice, - void* pDesc, - void* pRestrictToOutput, - void** ppSwapChain); - - UINT(STDMETHODCALLTYPE* GetCreationFlags)( - IDXGIFactory6* This); - - HRESULT(STDMETHODCALLTYPE* EnumAdapterByLuid)( - IDXGIFactory6* This, - LUID AdapterLuid, - REFIID riid, - void** ppvAdapter); - - HRESULT(STDMETHODCALLTYPE* EnumWarpAdapter)( - IDXGIFactory6* This, - REFIID riid, - void** ppvAdapter); - - HRESULT(STDMETHODCALLTYPE* CheckFeatureSupport)( - IDXGIFactory6* This, - DXGI_FEATURE Feature, - void* pFeatureSupportData, - UINT FeatureSupportDataSize); - - HRESULT(STDMETHODCALLTYPE* EnumAdapterByGpuPreference)( - IDXGIFactory6* This, - UINT Adapter, - DXGI_GPU_PREFERENCE GpuPreference, - REFIID riid, - void** ppvAdapter); -} IDXGIFactory6Vtbl; - -struct IDXGIFactory6 -{ - struct IDXGIFactory6Vtbl* lpVtbl; -}; - -#define IDXGIFactory6_EnumAdapterByGpuPreference(This,Adapter,GpuPreference,riid,ppvAdapter) \ - ( (This)->lpVtbl -> EnumAdapterByGpuPreference(This,Adapter,GpuPreference,riid,ppvAdapter) ) +static const IID D3D_IID_ID3D11Device1 = { 0xa04bfb29,0x08ef,0x43d6,{0xa4,0x9c,0xa9,0xbd,0xbd,0xcb,0xe6,0x86} }; -- 2.25.1 From e022faf54527900e3da19a9ab94f4e03e8d431f7 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 6 Feb 2024 21:48:16 -0600 Subject: [PATCH 29/69] Fix degenerate InputLayout creation when creating graphics pipeline with no vertex attributes --- src/Refresh_Driver_D3D11.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 113e650..7af1aa8 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -927,6 +927,12 @@ static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout( uint32_t i, bindingIndex; HRESULT res; + /* Don't bother creating/fetching an input layout if there are no attributes. */ + if (inputState.vertexAttributeCount == 0) + { + return NULL; + } + /* Allocate an array of vertex elements */ elementDescs = SDL_stack_alloc( D3D11_INPUT_ELEMENT_DESC, @@ -1119,7 +1125,6 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( } else { - /* Not sure if this is even possible, but juuust in case... */ pipeline->vertexStrides = NULL; } @@ -1888,15 +1893,18 @@ static void D3D11_QueueDestroyGraphicsPipeline( ID3D11BlendState_Release(d3dGraphicsPipeline->colorAttachmentBlendState); ID3D11DepthStencilState_Release(d3dGraphicsPipeline->depthStencilState); ID3D11RasterizerState_Release(d3dGraphicsPipeline->rasterizerState); - ID3D11InputLayout_Release(d3dGraphicsPipeline->inputLayout); - - /* FIXME: Release uniform buffers, once that's written in */ + if (d3dGraphicsPipeline->inputLayout) + { + ID3D11InputLayout_Release(d3dGraphicsPipeline->inputLayout); + } if (d3dGraphicsPipeline->vertexStrides) { SDL_free(d3dGraphicsPipeline->vertexStrides); } + /* FIXME: Release uniform buffers, once that's written in */ + SDL_free(d3dGraphicsPipeline); } -- 2.25.1 From 248aa956acd33efce0442d55ba70ba7d34ef02b2 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 6 Feb 2024 22:40:16 -0600 Subject: [PATCH 30/69] Release DLLs after releasing D3D11/DXGI objects (and release dxgi.dll!) --- src/Refresh_Driver_D3D11.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 7af1aa8..17bc85b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -606,16 +606,18 @@ static void D3D11_DestroyDevice( SDL_DestroyMutex(renderer->contextLock); SDL_DestroyMutex(renderer->uniformBufferLock); - /* Release the DLLs */ - SDL_UnloadObject(renderer->d3d11_dll); - SDL_UnloadObject(renderer->d3dcompiler_dll); - /* Release the device and associated objects */ ID3D11DeviceContext_Release(renderer->immediateContext); ID3D11Device_Release(renderer->device); IDXGIAdapter_Release(renderer->adapter); IDXGIFactory_Release(renderer->factory); + /* Release the DLLs */ + SDL_UnloadObject(renderer->d3d11_dll); + SDL_UnloadObject(renderer->dxgi_dll); + SDL_UnloadObject(renderer->d3dcompiler_dll); + + /* Free the primary Refresh structures */ SDL_free(renderer); SDL_free(device); } -- 2.25.1 From 69df00398ef7b1ca506608ba3b02922e947a3fc5 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 07:33:23 -0600 Subject: [PATCH 31/69] Fix a couple minor memory leaks --- src/Refresh_Driver_D3D11.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 17bc85b..c310832 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -599,7 +599,7 @@ static void D3D11_DestroyDevice( SDL_free(uniformBuffer->d3d11Buffer); SDL_free(uniformBuffer); } - SDL_free(renderer->availableCommandBuffers); + SDL_free(renderer->availableUniformBuffers); /* Release the mutexes */ SDL_DestroyMutex(renderer->acquireCommandBufferLock); @@ -1905,8 +1905,6 @@ static void D3D11_QueueDestroyGraphicsPipeline( SDL_free(d3dGraphicsPipeline->vertexStrides); } - /* FIXME: Release uniform buffers, once that's written in */ - SDL_free(d3dGraphicsPipeline); } @@ -2488,7 +2486,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( res = IDXGISwapChain_GetParent( swapchain, &D3D_IID_IDXGIFactory1, - (void**) &pParent /* FIXME: Does pParent need to get released? (Same for FNA3D) */ + (void**) &pParent ); if (FAILED(res)) { @@ -2512,6 +2510,9 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( res ); } + + /* We're done with the parent now */ + IDXGIFactory1_Release(pParent); } /* Create the swapchain data */ -- 2.25.1 From 1b63ff84671f2b2997a33f76f311056708a9c721 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 07:34:07 -0600 Subject: [PATCH 32/69] Minor style cleanup --- src/Refresh_Driver_D3D11.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index c310832..fcb3231 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1619,6 +1619,10 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( D3D11Renderer *renderer ) { D3D11_BUFFER_DESC bufferDesc; + ID3D11Buffer *bufferHandle; + D3D11UniformBuffer *uniformBuffer; + HRESULT res; + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bufferDesc.ByteWidth = UBO_BUFFER_SIZE; bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -1626,8 +1630,7 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( bufferDesc.StructureByteStride = 0; bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - ID3D11Buffer *bufferHandle; - HRESULT res = ID3D11Device_CreateBuffer( + res = ID3D11Device_CreateBuffer( renderer->device, &bufferDesc, NULL, @@ -1635,7 +1638,7 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( ); ERROR_CHECK_RETURN("Failed to create uniform buffer", 0); - D3D11UniformBuffer *uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer)); + uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer)); uniformBuffer->offset = 0; uniformBuffer->d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); uniformBuffer->d3d11Buffer->handle = bufferHandle; @@ -1662,6 +1665,8 @@ static D3D11UniformBuffer* D3D11_INTERNAL_AcquireUniformBufferFromPool( D3D11Renderer *renderer, uint64_t blockSize ) { + D3D11UniformBuffer *uniformBuffer; + SDL_LockMutex(renderer->uniformBufferLock); if (renderer->availableUniformBufferCount == 0) @@ -1674,7 +1679,7 @@ static D3D11UniformBuffer* D3D11_INTERNAL_AcquireUniformBufferFromPool( } } - D3D11UniformBuffer *uniformBuffer = renderer->availableUniformBuffers[renderer->availableUniformBufferCount - 1]; + uniformBuffer = renderer->availableUniformBuffers[renderer->availableUniformBufferCount - 1]; renderer->availableUniformBufferCount -= 1; SDL_UnlockMutex(renderer->uniformBufferLock); -- 2.25.1 From 30fe868ea23a2ddc7d9417f6956820e6b46d1833 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 08:02:49 -0600 Subject: [PATCH 33/69] Add DXGIDebug logic to help track memory leaks, fix SRV leak it discovered --- src/Refresh_Driver_D3D11.c | 76 +++++++++++++++++++++++++++++ src/Refresh_Driver_D3D11_cdefines.h | 6 ++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index fcb3231..602ce10 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -29,10 +29,12 @@ #define D3D11_NO_HELPERS #define CINTERFACE #define COBJMACROS + #include #include #include #include +#include #include #include "Refresh_Driver.h" @@ -45,9 +47,11 @@ #define D3D11_DLL "d3d11.dll" #define DXGI_DLL "dxgi.dll" +#define DXGIDEBUG_DLL "dxgidebug.dll" #define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice" #define D3DCOMPILE_FUNC "D3DCompile" #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" +#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface" #define WINDOW_DATA "Refresh_D3D11WindowData" #define UBO_BUFFER_SIZE 16000 /* 16KB */ @@ -463,8 +467,11 @@ typedef struct D3D11Renderer ID3D11DeviceContext *immediateContext; IDXGIFactory1 *factory; IDXGIAdapter1 *adapter; + IDXGIDebug *dxgiDebug; + IDXGIInfoQueue *dxgiInfoQueue; void *d3d11_dll; void *dxgi_dll; + void *dxgidebug_dll; void *d3dcompiler_dll; uint8_t debugMode; @@ -612,9 +619,25 @@ static void D3D11_DestroyDevice( IDXGIAdapter_Release(renderer->adapter); IDXGIFactory_Release(renderer->factory); + /* Report leaks and clean up debug objects */ + if (renderer->dxgiDebug) + { + IDXGIDebug_ReportLiveObjects(renderer->dxgiDebug, D3D_IID_DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL); + IDXGIDebug_Release(renderer->dxgiDebug); + } + + if (renderer->dxgiInfoQueue) + { + IDXGIInfoQueue_Release(renderer->dxgiInfoQueue); + } + /* Release the DLLs */ SDL_UnloadObject(renderer->d3d11_dll); SDL_UnloadObject(renderer->dxgi_dll); + if (renderer->dxgidebug_dll) + { + SDL_UnloadObject(renderer->dxgidebug_dll); + } SDL_UnloadObject(renderer->d3dcompiler_dll); /* Free the primary Refresh structures */ @@ -1842,7 +1865,18 @@ static void D3D11_QueueDestroyTexture( Refresh_Texture *texture ) { D3D11Texture *d3d11Texture = (D3D11Texture*) texture; + + if (d3d11Texture->shaderView) + { + ID3D11ShaderResourceView_Release(d3d11Texture->shaderView); + } + if (d3d11Texture->targetView) + { + ID3D11View_Release(d3d11Texture->targetView); + } + ID3D11Resource_Release(d3d11Texture->handle); + SDL_free(d3d11Texture); } @@ -3052,6 +3086,42 @@ static uint8_t D3D11_PrepareDriver( return 1; } +static void D3D11_INTERNAL_TryInitializeDXGIDebug(D3D11Renderer *renderer) +{ + PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc; + HRESULT res; + + renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL); + if (renderer->dxgidebug_dll == NULL) + { + Refresh_LogWarn("Could not find " DXGIDEBUG_DLL); + return; + } + + DXGIGetDebugInterfaceFunc = SDL_LoadFunction( + renderer->dxgidebug_dll, + DXGI_GET_DEBUG_INTERFACE_FUNC + ); + if (DXGIGetDebugInterfaceFunc == NULL) + { + Refresh_LogWarn("Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC); + return; + } + + res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, &renderer->dxgiDebug); + if (FAILED(res)) + { + Refresh_LogWarn("Could not get IDXGIDebug interface"); + } + + /* FIXME: Actually do something with the info queue! */ + res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, &renderer->dxgiInfoQueue); + if (FAILED(res)) + { + Refresh_LogWarn("Could not get IDXGIInfoQueue interface"); + } +} + static Refresh_Device* D3D11_CreateDevice( uint8_t debugMode ) { @@ -3141,6 +3211,12 @@ static Refresh_Device* D3D11_CreateDevice( /* Get information about the selected adapter. Used for logging info. */ IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc); + /* Initialize the DXGI debug layer, if applicable */ + if (debugMode) + { + D3D11_INTERNAL_TryInitializeDXGIDebug(renderer); + } + /* Load the D3D library */ renderer->d3d11_dll = SDL_LoadObject(D3D11_DLL); if (renderer->d3d11_dll == NULL) diff --git a/src/Refresh_Driver_D3D11_cdefines.h b/src/Refresh_Driver_D3D11_cdefines.h index f9361c4..da87aef 100644 --- a/src/Refresh_Driver_D3D11_cdefines.h +++ b/src/Refresh_Driver_D3D11_cdefines.h @@ -26,11 +26,15 @@ /* Function Pointer Signatures */ typedef HRESULT(WINAPI* PFN_CREATE_DXGI_FACTORY1)(const GUID* riid, void** ppFactory); +typedef HRESULT(WINAPI* PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID* riid, void** ppDebug); /* 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_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_ID3D11Texture2D = { 0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c} }; static const IID D3D_IID_ID3D11Device1 = { 0xa04bfb29,0x08ef,0x43d6,{0xa4,0x9c,0xa9,0xbd,0xbd,0xcb,0xe6,0x86} }; +static const IID D3D_IID_IDXGIDebug = { 0x119e7452,0xde9e,0x40fe,{0x88,0x06,0x88,0xf9,0x0c,0x12,0xb4,0x41} }; +static const IID D3D_IID_IDXGIInfoQueue = { 0xd67441c7,0x672a,0x476f,{0x9e,0x82,0xcd,0x55,0xb4,0x49,0x49,0xce} }; + +static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283,0xda80,0x490b,{0x87,0xe6,0x43,0xe9,0xa9,0xcf,0xda,0x08} }; -- 2.25.1 From 7f70318f7087b183ca502fc457de46a7d85a5afd Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 09:09:01 -0600 Subject: [PATCH 34/69] Set up the DXGI Info Queue so we can filter messages without using DirectX Control Panel --- src/Refresh_Driver_D3D11.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 602ce10..bfc4ece 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -622,7 +622,11 @@ static void D3D11_DestroyDevice( /* Report leaks and clean up debug objects */ if (renderer->dxgiDebug) { - IDXGIDebug_ReportLiveObjects(renderer->dxgiDebug, D3D_IID_DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL); + IDXGIDebug_ReportLiveObjects( + renderer->dxgiDebug, + D3D_IID_DXGI_DEBUG_ALL, + DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL + ); IDXGIDebug_Release(renderer->dxgiDebug); } @@ -3114,7 +3118,6 @@ static void D3D11_INTERNAL_TryInitializeDXGIDebug(D3D11Renderer *renderer) Refresh_LogWarn("Could not get IDXGIDebug interface"); } - /* FIXME: Actually do something with the info queue! */ res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, &renderer->dxgiInfoQueue); if (FAILED(res)) { @@ -3277,6 +3280,28 @@ tryCreateDevice: ); ERROR_CHECK_RETURN("Could not get ID3D11Device1 interface", NULL); + /* Set up the info queue */ + if (renderer->dxgiInfoQueue) + { + DXGI_INFO_QUEUE_MESSAGE_SEVERITY sevList[] = + { + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, + // DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO, /* This can be a bit much, so toggle as needed for debugging. */ + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE + }; + DXGI_INFO_QUEUE_FILTER filter = { 0 }; + filter.AllowList.NumSeverities = SDL_arraysize(sevList); + filter.AllowList.pSeverityList = sevList; + + IDXGIInfoQueue_PushStorageFilter( + renderer->dxgiInfoQueue, + D3D_IID_DXGI_DEBUG_ALL, + &filter + ); + } + /* Print driver info */ Refresh_LogInfo("Refresh Driver: D3D11"); Refresh_LogInfo("D3D11 Adapter: %S", adapterDesc.Description); -- 2.25.1 From 10cbac3fc3eaa7a14608b605c30f3bc5c32e7076 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 09:09:30 -0600 Subject: [PATCH 35/69] Fix device level check, fix ID3D11Device memory leak --- src/Refresh_Driver_D3D11.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index bfc4ece..01d2949 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2996,7 +2996,7 @@ static uint8_t D3D11_PrepareDriver( ) { void *d3d11_dll, *d3dcompiler_dll, *dxgi_dll; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; - D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 }; + D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 }; PFN_D3DCOMPILE D3DCompileFunc; PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc; HRESULT res; @@ -3280,6 +3280,9 @@ tryCreateDevice: ); ERROR_CHECK_RETURN("Could not get ID3D11Device1 interface", NULL); + /* Release the old device interface, we don't need it anymore */ + ID3D11Device_Release(d3d11Device); + /* Set up the info queue */ if (renderer->dxgiInfoQueue) { -- 2.25.1 From b0bd383f2e32f004956bd85d266e374cf8e56fe3 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 09:35:03 -0600 Subject: [PATCH 36/69] Fix fragment uniform buffer block calculation --- src/Refresh_Driver_D3D11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 01d2949..59f270f 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1192,7 +1192,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader; pipeline->numFragmentSamplers = pipelineCreateInfo->fragmentShaderInfo.samplerBindingCount; pipeline->fragmentUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( - (uint32_t) pipelineCreateInfo->vertexShaderInfo.uniformBufferSize, + (uint32_t) pipelineCreateInfo->fragmentShaderInfo.uniformBufferSize, 256 ); -- 2.25.1 From ce7cca2eba9f738239cc7ceb82b2091f0ed43bf1 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 10:08:23 -0600 Subject: [PATCH 37/69] Fix 3D texture SRV creation, use UpdateSubresource1 to avoid bug with non-zero offsets on deferred contexts --- src/Refresh_Driver_D3D11.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 59f270f..bc4f9ab 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1405,6 +1405,12 @@ static Refresh_Texture* D3D11_CreateTexture( srvDesc.Texture3D.MipLevels = desc3D.MipLevels; srvDesc.Texture3D.MostDetailedMip = 0; + res = ID3D11Device_CreateShaderResourceView( + renderer->device, + textureHandle, + &srvDesc, + &srv + ); if (FAILED(res)) { ID3D11Resource_Release(textureHandle); @@ -1516,7 +1522,7 @@ static void D3D11_SetTextureData( dstBox.bottom = textureSlice->rectangle.y + h; dstBox.back = textureSlice->depth + 1; - ID3D11DeviceContext_UpdateSubresource( + ID3D11DeviceContext1_UpdateSubresource1( d3d11CommandBuffer->context, d3d11Texture->handle, D3D11_INTERNAL_CalcSubresource( @@ -1527,7 +1533,8 @@ static void D3D11_SetTextureData( &dstBox, data, BytesPerRow(w, d3d11Texture->format), - BytesPerImage(w, h, d3d11Texture->format) + BytesPerImage(w, h, d3d11Texture->format), + D3D11_COPY_DISCARD /* FIXME: Is this right? */ ); } -- 2.25.1 From 597b8dcef3ef44e3c7ba76f8b55405f51ca85cc6 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 10:18:49 -0600 Subject: [PATCH 38/69] BindVertexSamplers --- src/Refresh_Driver_D3D11.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index bc4f9ab..c8c18b7 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1821,7 +1821,32 @@ static void D3D11_BindVertexSamplers( Refresh_Texture **pTextures, Refresh_Sampler **pSamplers ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + ID3D11ShaderResourceView* srvs[MAX_VERTEXTEXTURE_SAMPLERS]; + ID3D11SamplerState* d3d11Samplers[MAX_VERTEXTEXTURE_SAMPLERS]; + + int32_t numVertexSamplers = d3d11CommandBuffer->graphicsPipeline->numVertexSamplers; + + for (int32_t i = 0; i < numVertexSamplers; i += 1) + { + srvs[i] = ((D3D11Texture*) pTextures[i])->shaderView; + d3d11Samplers[i] = ((D3D11Sampler*) pSamplers[i])->handle; + } + + ID3D11DeviceContext_VSSetShaderResources( + d3d11CommandBuffer->context, + 0, + numVertexSamplers, + srvs + ); + + ID3D11DeviceContext_VSSetSamplers( + d3d11CommandBuffer->context, + 0, + numVertexSamplers, + d3d11Samplers + ); } static void D3D11_BindFragmentSamplers( -- 2.25.1 From f36abf29dec30de9712f4836df2fa858f5504706 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 11:53:18 -0600 Subject: [PATCH 39/69] DrawPrimitivesIndirect --- src/Refresh_Driver_D3D11.c | 79 +++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index c8c18b7..fc2dc7b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -424,6 +424,7 @@ typedef struct D3D11Buffer { ID3D11Buffer *handle; uint32_t size; + uint8_t isDynamic; } D3D11Buffer; typedef struct D3D11UniformBuffer @@ -777,7 +778,48 @@ static void D3D11_DrawPrimitivesIndirect( uint32_t vertexParamOffset, uint32_t fragmentParamOffset ) { - NOT_IMPLEMENTED + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + uint32_t vertexOffsetInConstants = vertexParamOffset / 16; + uint32_t fragmentOffsetInConstants = fragmentParamOffset / 16; + uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; + uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; + + if (d3d11CommandBuffer->vertexUniformBuffer != NULL) + { + ID3D11DeviceContext1_VSSetConstantBuffers1( + d3d11CommandBuffer->context, + 0, + 1, + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle, + &vertexOffsetInConstants, + &vertexBlockSizeInConstants + ); + } + + if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) + { + ID3D11DeviceContext1_PSSetConstantBuffers1( + d3d11CommandBuffer->context, + 0, + 1, + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle, + &fragmentOffsetInConstants, + &fragmentBlockSizeInConstants + ); + } + + /* D3D11: "We have multi-draw at home!" + * Multi-draw at home: + */ + for (uint32_t i = 0; i < drawCount; i += 1) + { + ID3D11DeviceContext_DrawInstancedIndirect( + d3d11CommandBuffer->context, + d3d11Buffer->handle, + offsetInBytes + (stride * i) + ); + } } static void D3D11_DispatchCompute( @@ -1455,6 +1497,7 @@ static Refresh_Buffer* D3D11_CreateBuffer( D3D11Buffer *d3d11Buffer; HRESULT res; + uint8_t isDynamic = 1; uint32_t bindFlags = 0; if (usageFlags & REFRESH_BUFFERUSAGE_VERTEX_BIT) { @@ -1464,16 +1507,17 @@ static Refresh_Buffer* D3D11_CreateBuffer( { bindFlags |= D3D11_BIND_INDEX_BUFFER; } - if (usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) + if ((usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) || (usageFlags & REFRESH_BUFFERUSAGE_INDIRECT_BIT)) { bindFlags |= D3D11_BIND_UNORDERED_ACCESS; + isDynamic = 0; } bufferDesc.BindFlags = bindFlags; bufferDesc.ByteWidth = sizeInBytes; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; + bufferDesc.Usage = isDynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; + bufferDesc.CPUAccessFlags = isDynamic ? D3D11_CPU_ACCESS_WRITE : 0; + bufferDesc.MiscFlags = (usageFlags & REFRESH_BUFFERUSAGE_INDIRECT_BIT) ? D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS : 0; bufferDesc.StructureByteStride = 0; res = ID3D11Device_CreateBuffer( @@ -1487,6 +1531,7 @@ static Refresh_Buffer* D3D11_CreateBuffer( d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); d3d11Buffer->handle = bufferHandle; d3d11Buffer->size = sizeInBytes; + d3d11Buffer->isDynamic = isDynamic; return (Refresh_Buffer*) d3d11Buffer; } @@ -1587,9 +1632,33 @@ static void D3D11_INTERNAL_SetBufferData( uint32_t dataLength, uint8_t noOverwrite ) { + D3D11_BOX dstBox; D3D11_MAPPED_SUBRESOURCE subres; HRESULT res; + /* Use UpdateSubresource for non-dynamic buffers (i.e. compute/indirect) */ + if (!buffer->isDynamic) + { + dstBox.left = 0; + dstBox.right = dataLength; + dstBox.top = 0; + dstBox.bottom = 1; + dstBox.front = 0; + dstBox.back = 1; + + ID3D11DeviceContext_UpdateSubresource( + commandBuffer->context, + (ID3D11Resource*) buffer->handle, + 0, + &dstBox, + data, + dataLength, + 1 + ); + + return; + } + res = ID3D11DeviceContext_Map( commandBuffer->context, (ID3D11Resource*) buffer->handle, -- 2.25.1 From ebf96ff4233d26b638b5793679c130a8ddcc0a9a Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 21:03:21 -0600 Subject: [PATCH 40/69] First rough draft of Compute functions (untested!) --- src/Refresh_Driver_D3D11.c | 213 +++++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 6 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index fc2dc7b..b42777c 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -361,6 +361,7 @@ typedef struct D3D11Texture ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ ID3D11ShaderResourceView *shaderView; ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ + ID3D11UnorderedAccessView *unorderedAccessView; /* Basic Info */ Refresh_TextureFormat format; @@ -420,11 +421,20 @@ typedef struct D3D11GraphicsPipeline uint32_t fragmentUniformBlockSize; } D3D11GraphicsPipeline; +typedef struct D3D11ComputePipeline +{ + ID3D11ComputeShader *computeShader; + uint64_t computeUniformBlockSize; + uint32_t numTextures; + uint32_t numBuffers; +} D3D11ComputePipeline; + typedef struct D3D11Buffer { ID3D11Buffer *handle; uint32_t size; uint8_t isDynamic; + ID3D11UnorderedAccessView *uav; } D3D11Buffer; typedef struct D3D11UniformBuffer @@ -444,6 +454,9 @@ typedef struct D3D11CommandBuffer ID3D11DepthStencilView *dsView; D3D11GraphicsPipeline *graphicsPipeline; + /* Compute Pass */ + D3D11ComputePipeline *computePipeline; + /* State */ SDL_threadID threadID; ID3D11Query *completionQuery; @@ -451,6 +464,7 @@ typedef struct D3D11CommandBuffer /* Uniforms */ D3D11UniformBuffer *vertexUniformBuffer; D3D11UniformBuffer *fragmentUniformBuffer; + D3D11UniformBuffer *computeUniformBuffer; D3D11UniformBuffer **boundUniformBuffers; uint32_t boundUniformBufferCount; @@ -830,7 +844,28 @@ static void D3D11_DispatchCompute( uint32_t groupCountZ, uint32_t computeParamOffset ) { - NOT_IMPLEMENTED + D3D11CommandBuffer* d3d11CommandBuffer = (D3D11CommandBuffer*)commandBuffer; + uint32_t computeOffsetInConstants = computeParamOffset / 16; + uint32_t computeBlockSizeInConstants = (uint32_t) (d3d11CommandBuffer->computePipeline->computeUniformBlockSize / 16); + + if (d3d11CommandBuffer->computeUniformBuffer != NULL) + { + ID3D11DeviceContext1_CSSetConstantBuffers1( + d3d11CommandBuffer->context, + 0, + 1, + &d3d11CommandBuffer->computeUniformBuffer->d3d11Buffer->handle, + &computeOffsetInConstants, + &computeBlockSizeInConstants + ); + } + + ID3D11DeviceContext_Dispatch( + d3d11CommandBuffer->context, + groupCountX, + groupCountY, + groupCountZ + ); } /* State Creation */ @@ -1064,8 +1099,16 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_Renderer *driverData, Refresh_ComputeShaderInfo *computeShaderInfo ) { - NOT_IMPLEMENTED - return NULL; + D3D11Renderer* renderer = (D3D11Renderer*) driverData; + D3D11ComputePipeline* pipeline = (D3D11ComputePipeline*) SDL_malloc(sizeof(D3D11ComputePipeline)); + D3D11ShaderModule* shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule; + + pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; + pipeline->numTextures = computeShaderInfo->imageBindingCount; + pipeline->numBuffers = computeShaderInfo->bufferBindingCount; + pipeline->computeUniformBlockSize = computeShaderInfo->uniformBufferSize; + + return (Refresh_ComputePipeline*) pipeline; } static inline uint32_t D3D11_INTERNAL_NextHighestAlignment( @@ -1318,6 +1361,7 @@ static Refresh_Texture* D3D11_CreateTexture( ID3D11ShaderResourceView *srv = NULL; ID3D11RenderTargetView *rtv = NULL; ID3D11DepthStencilView *dsv = NULL; + ID3D11UnorderedAccessView *uav = NULL; D3D11Texture *d3d11Texture; HRESULT res; @@ -1404,6 +1448,32 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } + + /* Create the UAV, if applicable */ + if (isCompute) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.Format = desc2D.Format; + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = 0; /* FIXME: Is this right? */ + + res = ID3D11Device_CreateUnorderedAccessView( + renderer->device, + textureHandle, + &uavDesc, + &uav + ); + if (FAILED(res)) + { + ID3D11Resource_Release(textureHandle); + if (srv != NULL) + { + ID3D11ShaderResourceView_Release(srv); + } + D3D11_INTERNAL_LogError(renderer->device, "Could not create UAV for 2D texture", res); + return NULL; + } + } } else { @@ -1460,6 +1530,33 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } + + /* Create the UAV, if applicable */ + if (isCompute) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; + uavDesc.Texture3D.MipSlice = 0; + uavDesc.Texture3D.FirstWSlice = 0; /* FIXME */ + uavDesc.Texture3D.WSize = 0; /* FIXME */ + + res = ID3D11Device_CreateUnorderedAccessView( + renderer->device, + textureHandle, + &uavDesc, + &uav + ); + if (FAILED(res)) + { + ID3D11Resource_Release(textureHandle); + if (srv != NULL) + { + ID3D11ShaderResourceView_Release(srv); + } + D3D11_INTERNAL_LogError(renderer->device, "Could not create UAV for 3D texture", res); + return NULL; + } + } } /* Create the RTV or DSV, if applicable */ @@ -1482,6 +1579,7 @@ static Refresh_Texture* D3D11_CreateTexture( d3d11Texture->isCube = textureCreateInfo->isCube; d3d11Texture->targetView = isRenderTarget ? (ID3D11View*) rtv : (ID3D11View*) dsv; d3d11Texture->shaderView = srv; + d3d11Texture->unorderedAccessView = uav; return (Refresh_Texture*) d3d11Texture; } @@ -1494,6 +1592,7 @@ static Refresh_Buffer* D3D11_CreateBuffer( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11_BUFFER_DESC bufferDesc; ID3D11Buffer *bufferHandle; + ID3D11UnorderedAccessView *uav = NULL; D3D11Buffer *d3d11Buffer; HRESULT res; @@ -1528,10 +1627,34 @@ static Refresh_Buffer* D3D11_CreateBuffer( ); ERROR_CHECK_RETURN("Could not create buffer", NULL); + /* Create a UAV for the buffer */ + if (usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.Format = DXGI_FORMAT_R8_UINT; + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + uavDesc.Buffer.FirstElement = 0; + uavDesc.Buffer.Flags = 0; + uavDesc.Buffer.NumElements = sizeInBytes; + + res = ID3D11Device_CreateUnorderedAccessView( + renderer->device, + (ID3D11Resource*) bufferHandle, + &uavDesc, + &uav + ); + if (FAILED(res)) + { + ID3D11Buffer_Release(bufferHandle); + ERROR_CHECK_RETURN("Could not create UAV for buffer!", NULL); + } + } + d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); d3d11Buffer->handle = bufferHandle; d3d11Buffer->size = sizeInBytes; d3d11Buffer->isDynamic = isDynamic; + d3d11Buffer->uav = uav; return (Refresh_Buffer*) d3d11Buffer; } @@ -1979,6 +2102,10 @@ static void D3D11_QueueDestroyTexture( { ID3D11View_Release(d3d11Texture->targetView); } + if (d3d11Texture->unorderedAccessView) + { + ID3D11UnorderedAccessView_Release(d3d11Texture->unorderedAccessView); + } ID3D11Resource_Release(d3d11Texture->handle); @@ -1999,7 +2126,14 @@ static void D3D11_QueueDestroyBuffer( Refresh_Buffer *buffer ) { D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + + if (d3d11Buffer->uav) + { + ID3D11UnorderedAccessView_Release(d3d11Buffer->handle); + } + ID3D11Buffer_Release(d3d11Buffer->handle); + SDL_free(d3d11Buffer); } @@ -2138,8 +2272,10 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->threadID = SDL_ThreadID(); commandBuffer->swapchainData = NULL; commandBuffer->graphicsPipeline = NULL; + commandBuffer->computePipeline = NULL; commandBuffer->vertexUniformBuffer = NULL; commandBuffer->fragmentUniformBuffer = NULL; + commandBuffer->computeUniformBuffer = NULL; commandBuffer->dsView = NULL; for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { @@ -2487,7 +2623,38 @@ static void D3D11_BindComputePipeline( Refresh_CommandBuffer *commandBuffer, Refresh_ComputePipeline *computePipeline ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11ComputePipeline *pipeline = (D3D11ComputePipeline*) computePipeline; + + d3d11CommandBuffer->computePipeline = pipeline; + + if (d3d11CommandBuffer->computeUniformBuffer != NULL) + { + D3D11_INTERNAL_BindUniformBuffer( + d3d11CommandBuffer, + d3d11CommandBuffer->computeUniformBuffer + ); + } + + if (pipeline->computeUniformBlockSize == 0) + { + d3d11CommandBuffer->computeUniformBuffer = NULL; + } + else + { + d3d11CommandBuffer->computeUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + renderer, + pipeline->computeUniformBlockSize + ); + } + + ID3D11DeviceContext_CSSetShader( + d3d11CommandBuffer->context, + pipeline->computeShader, + NULL, + 0 + ); } static void D3D11_BindComputeBuffers( @@ -2495,7 +2662,24 @@ static void D3D11_BindComputeBuffers( Refresh_CommandBuffer *commandBuffer, Refresh_Buffer **pBuffers ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + ID3D11UnorderedAccessView* uavs[MAX_BUFFER_BINDINGS]; /* FIXME: Is this limit right? */ + + int32_t numBuffers = d3d11CommandBuffer->computePipeline->numBuffers; + + for (int32_t i = 0; i < numBuffers; i += 1) + { + uavs[i] = ((D3D11Buffer*) pBuffers[i])->uav; + } + + ID3D11DeviceContext_CSSetUnorderedAccessViews( + d3d11CommandBuffer->context, + 0, + numBuffers, + uavs, + NULL + ); } static void D3D11_BindComputeTextures( @@ -2503,7 +2687,24 @@ static void D3D11_BindComputeTextures( Refresh_CommandBuffer *commandBuffer, Refresh_Texture **pTextures ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + ID3D11UnorderedAccessView *uavs[MAX_TEXTURE_SAMPLERS]; /* FIXME: Is this limit right? */ + + int32_t numTextures = d3d11CommandBuffer->computePipeline->numTextures; + + for (int32_t i = 0; i < numTextures; i += 1) + { + uavs[i] = ((D3D11Texture*) pTextures[i])->unorderedAccessView; + } + + ID3D11DeviceContext_CSSetUnorderedAccessViews( + d3d11CommandBuffer->context, + 0, + numTextures, + uavs, + NULL + ); } /* Window and Swapchain Management */ -- 2.25.1 From 0d6043cfef8ea112ee5b27cf57fe182764a17a68 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 8 Feb 2024 22:53:36 -0600 Subject: [PATCH 41/69] First pass at fence infrastructure --- src/Refresh_Driver_D3D11.c | 126 ++++++++++++++++++++++++++++++------- 1 file changed, 104 insertions(+), 22 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b42777c..a4a6235 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -443,6 +443,11 @@ typedef struct D3D11UniformBuffer uint32_t offset; } D3D11UniformBuffer; +typedef struct D3D11Fence +{ + ID3D11Query *handle; +} D3D11Fence; + typedef struct D3D11CommandBuffer { /* D3D11 Object References */ @@ -459,7 +464,7 @@ typedef struct D3D11CommandBuffer /* State */ SDL_threadID threadID; - ID3D11Query *completionQuery; + D3D11Fence *fence; /* Uniforms */ D3D11UniformBuffer *vertexUniformBuffer; @@ -509,9 +514,14 @@ typedef struct D3D11Renderer uint32_t availableUniformBufferCount; uint32_t availableUniformBufferCapacity; + D3D11Fence **availableFences; + uint32_t availableFenceCount; + uint32_t availableFenceCapacity; + SDL_mutex *contextLock; SDL_mutex *acquireCommandBufferLock; SDL_mutex *uniformBufferLock; + SDL_mutex *acquireFenceLock; } D3D11Renderer; /* Logging */ @@ -606,7 +616,6 @@ static void D3D11_DestroyDevice( for (uint32_t i = 0; i < renderer->availableCommandBufferCount; i += 1) { D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i]; - ID3D11Query_Release(commandBuffer->completionQuery); ID3D11DeviceContext_Release(commandBuffer->context); SDL_free(commandBuffer); } @@ -623,10 +632,20 @@ static void D3D11_DestroyDevice( } SDL_free(renderer->availableUniformBuffers); + /* Release fence infrastructure */ + for (uint32_t i = 0; i < renderer->availableFenceCount; i += 1) + { + D3D11Fence *fence = renderer->availableFences[i]; + ID3D11Query_Release(fence->handle); + SDL_free(fence); + } + SDL_free(renderer->availableFences); + /* Release the mutexes */ SDL_DestroyMutex(renderer->acquireCommandBufferLock); SDL_DestroyMutex(renderer->contextLock); SDL_DestroyMutex(renderer->uniformBufferLock); + SDL_DestroyMutex(renderer->acquireFenceLock); /* Release the device and associated objects */ ID3D11DeviceContext_Release(renderer->immediateContext); @@ -2193,7 +2212,6 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( uint32_t allocateCount ) { D3D11CommandBuffer *commandBuffer; - D3D11_QUERY_DESC queryDesc; HRESULT res; renderer->availableCommandBufferCapacity += allocateCount; @@ -2215,16 +2233,6 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( ); ERROR_CHECK("Could not create deferred context"); - /* Fence Query */ - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - res = ID3D11Device_CreateQuery( - renderer->device, - &queryDesc, - &commandBuffer->completionQuery - ); - ERROR_CHECK("Could not create query"); - /* Bound Uniform Buffers */ commandBuffer->boundUniformBufferCapacity = 16; commandBuffer->boundUniformBufferCount = 0; @@ -2232,8 +2240,6 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( commandBuffer->boundUniformBufferCapacity * sizeof(D3D11UniformBuffer*) ); - /* FIXME: Resource tracking? */ - renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; renderer->availableCommandBufferCount += 1; } @@ -2258,6 +2264,59 @@ static D3D11CommandBuffer* D3D11_INTERNAL_GetInactiveCommandBufferFromPool( return commandBuffer; } +static void D3D11_INTERNAL_AllocateFences( + D3D11Renderer *renderer, + uint32_t allocateCount +) { + D3D11Fence *fence; + D3D11_QUERY_DESC queryDesc; + HRESULT res; + + renderer->availableFenceCapacity += allocateCount; + + renderer->availableFences = SDL_realloc( + renderer->availableFences, + sizeof(D3D11Fence*) * renderer->availableFenceCapacity + ); + + for (uint32_t i = 0; i < allocateCount; i += 1) + { + fence = SDL_malloc(sizeof(D3D11Fence)); + + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + res = ID3D11Device_CreateQuery( + renderer->device, + &queryDesc, + &fence->handle + ); + ERROR_CHECK("Could not create query"); /* FIXME: Should this return an error code? */ + + renderer->availableFences[renderer->availableFenceCount] = fence; + renderer->availableFenceCount += 1; + } +} + +static D3D11Fence* D3D11_INTERNAL_GetFenceFromPool( + D3D11Renderer* renderer +) { + D3D11Fence *fence; + + SDL_LockMutex(renderer->acquireFenceLock); + + if (renderer->availableFenceCount == 0) + { + D3D11_INTERNAL_AllocateFences(renderer, renderer->availableFenceCapacity); + } + + fence = renderer->availableFences[renderer->availableFenceCount - 1]; + renderer->availableFenceCount -= 1; + + SDL_UnlockMutex(renderer->acquireFenceLock); + + return fence; +} + static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( Refresh_Renderer *driverData ) { @@ -2267,8 +2326,8 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( SDL_LockMutex(renderer->acquireCommandBufferLock); - /* Set up the command buffer */ commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer); + commandBuffer->threadID = SDL_ThreadID(); commandBuffer->swapchainData = NULL; commandBuffer->graphicsPipeline = NULL; @@ -2277,11 +2336,16 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->fragmentUniformBuffer = NULL; commandBuffer->computeUniformBuffer = NULL; commandBuffer->dsView = NULL; + for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { commandBuffer->rtViews[i] = NULL; } + SDL_LockMutex(renderer->acquireFenceLock); + commandBuffer->fence = D3D11_INTERNAL_GetFenceFromPool(renderer); + SDL_UnlockMutex(renderer->acquireFenceLock); + SDL_UnlockMutex(renderer->acquireCommandBufferLock); return (Refresh_CommandBuffer*) commandBuffer; @@ -3111,6 +3175,22 @@ static void D3D11_INTERNAL_CleanCommandBuffer( commandBuffer->boundUniformBufferCount = 0; + /* The fence is now available */ + /* FIXME: Not if auto-release is false! */ + SDL_LockMutex(renderer->acquireFenceLock); + if (renderer->availableFenceCount == renderer->availableFenceCapacity) + { + renderer->availableFenceCapacity *= 2; + renderer->availableFences = SDL_realloc( + renderer->availableFences, + renderer->availableFenceCapacity * sizeof(D3D11Fence*) + ); + } + + renderer->availableFences[renderer->availableFenceCount] = commandBuffer->fence; + renderer->availableFenceCount += 1; + SDL_UnlockMutex(renderer->acquireFenceLock); + /* Return command buffer to pool */ SDL_LockMutex(renderer->acquireCommandBufferLock); @@ -3155,7 +3235,7 @@ static void D3D11_Submit( /* Notify the command buffer completion query that we have completed recording */ ID3D11DeviceContext_End( renderer->immediateContext, - (ID3D11Asynchronous*) d3d11CommandBuffer->completionQuery + (ID3D11Asynchronous*) d3d11CommandBuffer->fence->handle ); /* Serialize the commands into the command list */ @@ -3205,7 +3285,7 @@ static void D3D11_Submit( res = ID3D11DeviceContext_GetData( renderer->immediateContext, - (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->completionQuery, + (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->fence->handle, &queryData, sizeof(queryData), 0 @@ -3245,7 +3325,7 @@ static void D3D11_Wait( { while (S_OK != ID3D11DeviceContext_GetData( renderer->immediateContext, - (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->completionQuery, + (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->fence->handle, &queryData, sizeof(queryData), 0 @@ -3262,8 +3342,6 @@ static void D3D11_Wait( D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer); } - /* FIXME: D3D11_INTERNAL_PerformPendingDestroys(renderer); */ - SDL_UnlockMutex(renderer->contextLock); } @@ -3615,17 +3693,21 @@ tryCreateDevice: renderer->contextLock = SDL_CreateMutex(); renderer->acquireCommandBufferLock = SDL_CreateMutex(); renderer->uniformBufferLock = SDL_CreateMutex(); + renderer->acquireFenceLock = SDL_CreateMutex(); /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); - /* Create command buffers to initialize the pool */ + /* Create command buffer pool */ D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2); /* Create uniform buffer pool */ renderer->availableUniformBufferCapacity = 2; renderer->availableUniformBuffers = SDL_malloc(sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity); + /* Create fence pool */ + D3D11_INTERNAL_AllocateFences(renderer, 2); + /* Create the Refresh Device */ result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); ASSIGN_DRIVER(D3D11) -- 2.25.1 From 8be21dde9b1130d4d38955e7750b64297e43379d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 8 Feb 2024 23:47:25 -0600 Subject: [PATCH 42/69] Uniform buffer binding rework for clarity + minor cleanup --- src/Refresh_Driver_D3D11.c | 186 +++++++++++++++---------------------- 1 file changed, 77 insertions(+), 109 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index a4a6235..ac1cc48 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -582,7 +582,7 @@ static void D3D11_INTERNAL_LogError( Refresh_LogError("%s! Error Code: %s (0x%08X)", msg, wszMsgBuff, res); } -/* Subresources */ +/* Helper Functions */ static inline uint32_t D3D11_INTERNAL_CalcSubresource( uint32_t mipLevel, @@ -592,6 +592,13 @@ static inline uint32_t D3D11_INTERNAL_CalcSubresource( return mipLevel + (arraySlice * numLevels); } +static inline uint32_t D3D11_INTERNAL_NextHighestAlignment( + uint32_t n, + uint32_t align +) { + return align * ((n + align - 1) / align); +} + /* Quit */ static void D3D11_DestroyDevice( @@ -896,7 +903,6 @@ static ID3D11BlendState* D3D11_INTERNAL_FetchBlendState( ) { ID3D11BlendState *result; D3D11_BLEND_DESC blendDesc; - uint32_t i; HRESULT res; /* Create a new blend state. @@ -907,7 +913,7 @@ static ID3D11BlendState* D3D11_INTERNAL_FetchBlendState( blendDesc.AlphaToCoverageEnable = FALSE; blendDesc.IndependentBlendEnable = TRUE; - for (i = 0; i < numColorAttachments; i += 1) + for (uint32_t i = 0; i < numColorAttachments; i += 1) { blendDesc.RenderTarget[i].BlendEnable = colorAttachments[i].blendState.blendEnable; blendDesc.RenderTarget[i].BlendOp = RefreshToD3D11_BlendOp[ @@ -1028,8 +1034,7 @@ static uint32_t D3D11_INTERNAL_FindIndexOfVertexBinding( const Refresh_VertexBinding *bindings, uint32_t numBindings ) { - uint32_t i; - for (i = 0; i < numBindings; i += 1) + for (uint32_t i = 0; i < numBindings; i += 1) { if (bindings[i].binding == targetBinding) { @@ -1049,7 +1054,7 @@ static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout( ) { ID3D11InputLayout *result = NULL; D3D11_INPUT_ELEMENT_DESC *elementDescs; - uint32_t i, bindingIndex; + uint32_t bindingIndex; HRESULT res; /* Don't bother creating/fetching an input layout if there are no attributes. */ @@ -1065,7 +1070,7 @@ static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout( ); /* Create the array of input elements */ - for (i = 0; i < inputState.vertexAttributeCount; i += 1) + for (uint32_t i = 0; i < inputState.vertexAttributeCount; i += 1) { elementDescs[i].AlignedByteOffset = inputState.vertexAttributes[i].offset; elementDescs[i].Format = RefreshToD3D11_VertexFormat[ @@ -1118,7 +1123,6 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_Renderer *driverData, Refresh_ComputeShaderInfo *computeShaderInfo ) { - D3D11Renderer* renderer = (D3D11Renderer*) driverData; D3D11ComputePipeline* pipeline = (D3D11ComputePipeline*) SDL_malloc(sizeof(D3D11ComputePipeline)); D3D11ShaderModule* shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule; @@ -1130,13 +1134,6 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( return (Refresh_ComputePipeline*) pipeline; } -static inline uint32_t D3D11_INTERNAL_NextHighestAlignment( - uint32_t n, - uint32_t align -) { - return align * ((n + align - 1) / align); -} - static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( Refresh_Renderer *driverData, Refresh_GraphicsPipelineCreateInfo *pipelineCreateInfo @@ -1148,7 +1145,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( ID3D10Blob *errorBlob; HRESULT res; - /* Color */ + /* Blend */ pipeline->colorAttachmentBlendState = D3D11_INTERNAL_FetchBlendState( renderer, @@ -1169,9 +1166,11 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( pipeline->blendConstants[2] = pipelineCreateInfo->blendConstants[2]; pipeline->blendConstants[3] = pipelineCreateInfo->blendConstants[3]; + /* Multisample */ + pipeline->multisampleState = pipelineCreateInfo->multisampleState; - /* Depth stencil */ + /* Depth-Stencil */ pipeline->depthStencilState = D3D11_INTERNAL_FetchDepthStencilState( renderer, @@ -1192,7 +1191,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( pipelineCreateInfo->rasterizerState ); - /* Vertex shader */ + /* Vertex Shader */ if (vertShaderModule->shader == NULL) { @@ -1344,6 +1343,7 @@ static Refresh_Sampler* D3D11_CreateSampler( ); ERROR_CHECK_RETURN("Could not create sampler state", NULL); + /* FIXME: Is there even a point to having a D3D11Sampler struct if it's just a wrapper? */ d3d11Sampler = (D3D11Sampler*) SDL_malloc(sizeof(D3D11Sampler)); d3d11Sampler->handle = samplerStateHandle; @@ -1678,7 +1678,7 @@ static Refresh_Buffer* D3D11_CreateBuffer( return (Refresh_Buffer*) d3d11Buffer; } -/* Setters */ +/* Texture Data */ static void D3D11_SetTextureData( Refresh_Renderer *driverData, @@ -1765,6 +1765,8 @@ static void D3D11_CopyTextureToBuffer( NOT_IMPLEMENTED } +/* Buffer Data */ + static void D3D11_INTERNAL_SetBufferData( D3D11Renderer *renderer, D3D11CommandBuffer *commandBuffer, @@ -1843,23 +1845,17 @@ static void D3D11_SetBufferData( ); } -static void D3D11_INTERNAL_BindUniformBuffer( - D3D11CommandBuffer *commandBuffer, - D3D11UniformBuffer *uniformBuffer +static void D3D11_GetBufferData( + Refresh_Renderer *driverData, + Refresh_Buffer *buffer, + void* data, + uint32_t dataLengthInBytes ) { - if (commandBuffer->boundUniformBufferCount >= commandBuffer->boundUniformBufferCapacity) - { - commandBuffer->boundUniformBufferCapacity *= 2; - commandBuffer->boundUniformBuffers = SDL_realloc( - commandBuffer->boundUniformBuffers, - sizeof(D3D11UniformBuffer*) * commandBuffer->boundUniformBufferCapacity - ); - } - - commandBuffer->boundUniformBuffers[commandBuffer->boundUniformBufferCount] = uniformBuffer; - commandBuffer->boundUniformBufferCount += 1; + NOT_IMPLEMENTED } +/* Uniforms */ + static uint8_t D3D11_INTERNAL_CreateUniformBuffer( D3D11Renderer *renderer ) { @@ -1888,6 +1884,8 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( uniformBuffer->d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); uniformBuffer->d3d11Buffer->handle = bufferHandle; uniformBuffer->d3d11Buffer->size = UBO_BUFFER_SIZE; + uniformBuffer->d3d11Buffer->isDynamic = 1; + uniformBuffer->d3d11Buffer->uav = NULL; /* Add it to the available pool */ if (renderer->availableUniformBufferCount >= renderer->availableUniformBufferCapacity) @@ -1906,12 +1904,15 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( return 1; } -static D3D11UniformBuffer* D3D11_INTERNAL_AcquireUniformBufferFromPool( +static uint8_t D3D11_INTERNAL_AcquireUniformBuffer( D3D11Renderer *renderer, + D3D11CommandBuffer *commandBuffer, + D3D11UniformBuffer **uniformBufferToBind, uint64_t blockSize ) { D3D11UniformBuffer *uniformBuffer; + /* Acquire a uniform buffer from the pool */ SDL_LockMutex(renderer->uniformBufferLock); if (renderer->availableUniformBufferCount == 0) @@ -1920,7 +1921,7 @@ static D3D11UniformBuffer* D3D11_INTERNAL_AcquireUniformBufferFromPool( { SDL_UnlockMutex(renderer->uniformBufferLock); Refresh_LogError("Failed to create uniform buffer!"); - return NULL; + return 0; } } @@ -1929,9 +1930,24 @@ static D3D11UniformBuffer* D3D11_INTERNAL_AcquireUniformBufferFromPool( SDL_UnlockMutex(renderer->uniformBufferLock); + /* Reset the uniform buffer */ uniformBuffer->offset = 0; - return uniformBuffer; + /* Bind the uniform buffer to the command buffer */ + if (commandBuffer->boundUniformBufferCount >= commandBuffer->boundUniformBufferCapacity) + { + commandBuffer->boundUniformBufferCapacity *= 2; + commandBuffer->boundUniformBuffers = SDL_realloc( + commandBuffer->boundUniformBuffers, + sizeof(D3D11UniformBuffer*) * commandBuffer->boundUniformBufferCapacity + ); + } + commandBuffer->boundUniformBuffers[commandBuffer->boundUniformBufferCount] = uniformBuffer; + commandBuffer->boundUniformBufferCount += 1; + + *uniformBufferToBind = uniformBuffer; + + return 1; } static uint32_t D3D11_PushVertexShaderUniforms( @@ -1947,13 +1963,11 @@ static uint32_t D3D11_PushVertexShaderUniforms( if (d3d11CommandBuffer->vertexUniformBuffer->offset + graphicsPipeline->vertexUniformBlockSize >= UBO_BUFFER_SIZE) { - /* We're out of space in this buffer, bind the old one and acquire a new one */ - D3D11_INTERNAL_BindUniformBuffer( - d3d11CommandBuffer, - d3d11CommandBuffer->vertexUniformBuffer - ); - d3d11CommandBuffer->vertexUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + /* Out of space! Get a new uniform buffer. */ + D3D11_INTERNAL_AcquireUniformBuffer( renderer, + d3d11CommandBuffer, + &d3d11CommandBuffer->vertexUniformBuffer, graphicsPipeline->vertexUniformBlockSize ); } @@ -1988,13 +2002,11 @@ static uint32_t D3D11_PushFragmentShaderUniforms( if (d3d11CommandBuffer->fragmentUniformBuffer->offset + graphicsPipeline->fragmentUniformBlockSize >= UBO_BUFFER_SIZE) { - /* We're out of space in this buffer, bind the old one and acquire a new one */ - D3D11_INTERNAL_BindUniformBuffer( - d3d11CommandBuffer, - d3d11CommandBuffer->fragmentUniformBuffer - ); - d3d11CommandBuffer->fragmentUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + /* Out of space! Get a new uniform buffer. */ + D3D11_INTERNAL_AcquireUniformBuffer( renderer, + d3d11CommandBuffer, + &d3d11CommandBuffer->fragmentUniformBuffer, graphicsPipeline->fragmentUniformBlockSize ); } @@ -2026,6 +2038,8 @@ static uint32_t D3D11_PushComputeShaderUniforms( return 0; } +/* Samplers */ + static void D3D11_BindVertexSamplers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -2094,17 +2108,6 @@ static void D3D11_BindFragmentSamplers( ); } -/* Getters */ - -static void D3D11_GetBufferData( - Refresh_Renderer *driverData, - Refresh_Buffer *buffer, - void *data, - uint32_t dataLengthInBytes -) { - NOT_IMPLEMENTED -} - /* Disposal */ static void D3D11_QueueDestroyTexture( @@ -2322,7 +2325,6 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *commandBuffer; - uint32_t i; SDL_LockMutex(renderer->acquireCommandBufferLock); @@ -2337,7 +2339,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->computeUniformBuffer = NULL; commandBuffer->dsView = NULL; - for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) + for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { commandBuffer->rtViews[i] = NULL; } @@ -2364,7 +2366,6 @@ static void D3D11_BeginRenderPass( D3D11_CLEAR_FLAG dsClearFlags; D3D11_VIEWPORT viewport; D3D11_RECT scissorRect; - uint32_t i; /* FIXME: * We need to unbind the RT textures on the Refresh side @@ -2372,14 +2373,14 @@ static void D3D11_BeginRenderPass( */ /* Clear the bound RTs for the current command buffer */ - for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) + for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { d3d11CommandBuffer->rtViews[i] = NULL; } d3d11CommandBuffer->dsView = NULL; /* Get RTVs for the color attachments */ - for (i = 0; i < colorAttachmentCount; i += 1) + for (uint32_t i = 0; i < colorAttachmentCount; i += 1) { /* FIXME: Cube RTs */ @@ -2401,7 +2402,7 @@ static void D3D11_BeginRenderPass( ); /* Perform load ops on the RTs */ - for (i = 0; i < colorAttachmentCount; i += 1) + for (uint32_t i = 0; i < colorAttachmentCount; i += 1) { if (colorAttachmentInfos[i].loadOp == REFRESH_LOADOP_CLEAR) { @@ -2474,23 +2475,9 @@ static void D3D11_EndRenderPass( ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - if (d3d11CommandBuffer->vertexUniformBuffer != NULL) - { - D3D11_INTERNAL_BindUniformBuffer( - d3d11CommandBuffer, - d3d11CommandBuffer->vertexUniformBuffer - ); - } d3d11CommandBuffer->vertexUniformBuffer = NULL; - - if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) - { - D3D11_INTERNAL_BindUniformBuffer( - d3d11CommandBuffer, - d3d11CommandBuffer->fragmentUniformBuffer - ); - } d3d11CommandBuffer->fragmentUniformBuffer = NULL; + d3d11CommandBuffer->computeUniformBuffer = NULL; /* FIXME: Resolve MSAA here! */ /* FIXME: Anything else we need to do...? */ @@ -2507,31 +2494,17 @@ static void D3D11_BindGraphicsPipeline( d3d11CommandBuffer->graphicsPipeline = pipeline; - if (d3d11CommandBuffer->vertexUniformBuffer != NULL) - { - D3D11_INTERNAL_BindUniformBuffer( - d3d11CommandBuffer, - d3d11CommandBuffer->vertexUniformBuffer - ); - } - if (pipeline->vertexUniformBlockSize == 0) { d3d11CommandBuffer->vertexUniformBuffer = NULL; } else { - d3d11CommandBuffer->vertexUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + D3D11_INTERNAL_AcquireUniformBuffer( renderer, - pipeline->vertexUniformBlockSize - ); - } - - if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) - { - D3D11_INTERNAL_BindUniformBuffer( d3d11CommandBuffer, - d3d11CommandBuffer->fragmentUniformBuffer + &d3d11CommandBuffer->vertexUniformBuffer, + pipeline->vertexUniformBlockSize ); } @@ -2541,8 +2514,10 @@ static void D3D11_BindGraphicsPipeline( } else { - d3d11CommandBuffer->fragmentUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + D3D11_INTERNAL_AcquireUniformBuffer( renderer, + d3d11CommandBuffer, + &d3d11CommandBuffer->fragmentUniformBuffer, pipeline->fragmentUniformBlockSize ); } @@ -2693,22 +2668,16 @@ static void D3D11_BindComputePipeline( d3d11CommandBuffer->computePipeline = pipeline; - if (d3d11CommandBuffer->computeUniformBuffer != NULL) - { - D3D11_INTERNAL_BindUniformBuffer( - d3d11CommandBuffer, - d3d11CommandBuffer->computeUniformBuffer - ); - } - if (pipeline->computeUniformBlockSize == 0) { d3d11CommandBuffer->computeUniformBuffer = NULL; } else { - d3d11CommandBuffer->computeUniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool( + D3D11_INTERNAL_AcquireUniformBuffer( renderer, + d3d11CommandBuffer, + &d3d11CommandBuffer->computeUniformBuffer, pipeline->computeUniformBlockSize ); } @@ -3049,7 +3018,6 @@ static void D3D11_UnclaimWindow( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle); - uint32_t i; if (windowData == NULL) { @@ -3065,7 +3033,7 @@ static void D3D11_UnclaimWindow( ); } - for (i = 0; i < renderer->claimedWindowCount; i += 1) + for (uint32_t i = 0; i < renderer->claimedWindowCount; i += 1) { if (renderer->claimedWindows[i]->windowHandle == windowHandle) { -- 2.25.1 From ca7f64eb9a7e5df4f6ac609e97887ddf0571598c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 8 Feb 2024 23:59:13 -0600 Subject: [PATCH 43/69] Clean up fence logic --- src/Refresh_Driver_D3D11.c | 91 ++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ac1cc48..dd2bf97 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -521,7 +521,7 @@ typedef struct D3D11Renderer SDL_mutex *contextLock; SDL_mutex *acquireCommandBufferLock; SDL_mutex *uniformBufferLock; - SDL_mutex *acquireFenceLock; + SDL_mutex *fenceLock; } D3D11Renderer; /* Logging */ @@ -652,7 +652,7 @@ static void D3D11_DestroyDevice( SDL_DestroyMutex(renderer->acquireCommandBufferLock); SDL_DestroyMutex(renderer->contextLock); SDL_DestroyMutex(renderer->uniformBufferLock); - SDL_DestroyMutex(renderer->acquireFenceLock); + SDL_DestroyMutex(renderer->fenceLock); /* Release the device and associated objects */ ID3D11DeviceContext_Release(renderer->immediateContext); @@ -2267,57 +2267,71 @@ static D3D11CommandBuffer* D3D11_INTERNAL_GetInactiveCommandBufferFromPool( return commandBuffer; } -static void D3D11_INTERNAL_AllocateFences( - D3D11Renderer *renderer, - uint32_t allocateCount +static uint8_t D3D11_INTERNAL_CreateFence( + D3D11Renderer *renderer ) { - D3D11Fence *fence; D3D11_QUERY_DESC queryDesc; + ID3D11Query *queryHandle; + D3D11Fence* fence; HRESULT res; - renderer->availableFenceCapacity += allocateCount; - - renderer->availableFences = SDL_realloc( - renderer->availableFences, - sizeof(D3D11Fence*) * renderer->availableFenceCapacity + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + res = ID3D11Device_CreateQuery( + renderer->device, + &queryDesc, + &queryHandle ); + ERROR_CHECK_RETURN("Could not create query", 0); - for (uint32_t i = 0; i < allocateCount; i += 1) + fence = SDL_malloc(sizeof(D3D11Fence)); + fence->handle = queryHandle; + + /* Add it to the available pool */ + if (renderer->availableFenceCount >= renderer->availableFenceCapacity) { - fence = SDL_malloc(sizeof(D3D11Fence)); + renderer->availableFenceCapacity *= 2; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - res = ID3D11Device_CreateQuery( - renderer->device, - &queryDesc, - &fence->handle + renderer->availableFences = SDL_realloc( + renderer->availableFences, + sizeof(D3D11Fence*) * renderer->availableFenceCapacity ); - ERROR_CHECK("Could not create query"); /* FIXME: Should this return an error code? */ - - renderer->availableFences[renderer->availableFenceCount] = fence; - renderer->availableFenceCount += 1; } + + renderer->availableFences[renderer->availableFenceCount] = fence; + renderer->availableFenceCount += 1; + + return 1; } -static D3D11Fence* D3D11_INTERNAL_GetFenceFromPool( - D3D11Renderer* renderer +static uint8_t D3D11_INTERNAL_AcquireFence( + D3D11Renderer *renderer, + D3D11CommandBuffer *commandBuffer ) { D3D11Fence *fence; - SDL_LockMutex(renderer->acquireFenceLock); + /* Acquire a fence from the pool */ + SDL_LockMutex(renderer->fenceLock); if (renderer->availableFenceCount == 0) { - D3D11_INTERNAL_AllocateFences(renderer, renderer->availableFenceCapacity); + if (!D3D11_INTERNAL_CreateFence(renderer)) + { + SDL_UnlockMutex(renderer->fenceLock); + Refresh_LogError("Failed to create fence!"); + return 0; + } } fence = renderer->availableFences[renderer->availableFenceCount - 1]; renderer->availableFenceCount -= 1; - SDL_UnlockMutex(renderer->acquireFenceLock); + SDL_UnlockMutex(renderer->fenceLock); - return fence; + /* Associate the fence with the command buffer */ + commandBuffer->fence = fence; + + return 1; } static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( @@ -2344,9 +2358,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->rtViews[i] = NULL; } - SDL_LockMutex(renderer->acquireFenceLock); - commandBuffer->fence = D3D11_INTERNAL_GetFenceFromPool(renderer); - SDL_UnlockMutex(renderer->acquireFenceLock); + D3D11_INTERNAL_AcquireFence(renderer, commandBuffer); SDL_UnlockMutex(renderer->acquireCommandBufferLock); @@ -3121,8 +3133,6 @@ static void D3D11_INTERNAL_CleanCommandBuffer( D3D11Renderer *renderer, D3D11CommandBuffer *commandBuffer ) { - /* FIXME: All kinds of stuff should go here... */ - /* Bound uniform buffers are now available */ SDL_LockMutex(renderer->uniformBufferLock); for (uint32_t i = 0; i < commandBuffer->boundUniformBufferCount; i += 1) @@ -3145,7 +3155,7 @@ static void D3D11_INTERNAL_CleanCommandBuffer( /* The fence is now available */ /* FIXME: Not if auto-release is false! */ - SDL_LockMutex(renderer->acquireFenceLock); + SDL_LockMutex(renderer->fenceLock); if (renderer->availableFenceCount == renderer->availableFenceCapacity) { renderer->availableFenceCapacity *= 2; @@ -3154,14 +3164,12 @@ static void D3D11_INTERNAL_CleanCommandBuffer( renderer->availableFenceCapacity * sizeof(D3D11Fence*) ); } - renderer->availableFences[renderer->availableFenceCount] = commandBuffer->fence; renderer->availableFenceCount += 1; - SDL_UnlockMutex(renderer->acquireFenceLock); + SDL_UnlockMutex(renderer->fenceLock); /* Return command buffer to pool */ SDL_LockMutex(renderer->acquireCommandBufferLock); - if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) { renderer->availableCommandBufferCapacity += 1; @@ -3170,10 +3178,8 @@ static void D3D11_INTERNAL_CleanCommandBuffer( renderer->availableCommandBufferCapacity * sizeof(D3D11CommandBuffer*) ); } - renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; renderer->availableCommandBufferCount += 1; - SDL_UnlockMutex(renderer->acquireCommandBufferLock); /* Remove this command buffer from the submitted list */ @@ -3661,7 +3667,7 @@ tryCreateDevice: renderer->contextLock = SDL_CreateMutex(); renderer->acquireCommandBufferLock = SDL_CreateMutex(); renderer->uniformBufferLock = SDL_CreateMutex(); - renderer->acquireFenceLock = SDL_CreateMutex(); + renderer->fenceLock = SDL_CreateMutex(); /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); @@ -3674,7 +3680,8 @@ tryCreateDevice: renderer->availableUniformBuffers = SDL_malloc(sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity); /* Create fence pool */ - D3D11_INTERNAL_AllocateFences(renderer, 2); + renderer->availableFenceCapacity = 2; + renderer->availableFences = SDL_malloc(sizeof(D3D11Fence*) * renderer->availableFenceCapacity); /* Create the Refresh Device */ result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); -- 2.25.1 From ecff6f55dfea28ccc2a75853c2087514ded17acf Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 00:31:54 -0600 Subject: [PATCH 44/69] Fence API --- src/Refresh_Driver_D3D11.c | 132 +++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 28 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index dd2bf97..0fea013 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -465,6 +465,7 @@ typedef struct D3D11CommandBuffer /* State */ SDL_threadID threadID; D3D11Fence *fence; + uint8_t autoReleaseFence; /* Uniforms */ D3D11UniformBuffer *vertexUniformBuffer; @@ -2359,6 +2360,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( } D3D11_INTERNAL_AcquireFence(renderer, commandBuffer); + commandBuffer->autoReleaseFence = 1; SDL_UnlockMutex(renderer->acquireCommandBufferLock); @@ -3129,6 +3131,26 @@ static void D3D11_SetSwapchainPresentMode( /* Submission and Fences */ +static void D3D11_INTERNAL_ReleaseFenceToPool( + D3D11Renderer *renderer, + D3D11Fence *fence +) { + SDL_LockMutex(renderer->fenceLock); + + if (renderer->availableFenceCount == renderer->availableFenceCapacity) + { + renderer->availableFenceCapacity *= 2; + renderer->availableFences = SDL_realloc( + renderer->availableFences, + renderer->availableFenceCapacity * sizeof(D3D11Fence*) + ); + } + renderer->availableFences[renderer->availableFenceCount] = fence; + renderer->availableFenceCount += 1; + + SDL_UnlockMutex(renderer->fenceLock); +} + static void D3D11_INTERNAL_CleanCommandBuffer( D3D11Renderer *renderer, D3D11CommandBuffer *commandBuffer @@ -3153,20 +3175,11 @@ static void D3D11_INTERNAL_CleanCommandBuffer( commandBuffer->boundUniformBufferCount = 0; - /* The fence is now available */ - /* FIXME: Not if auto-release is false! */ - SDL_LockMutex(renderer->fenceLock); - if (renderer->availableFenceCount == renderer->availableFenceCapacity) + /* The fence is now available (unless SubmitAndAcquireFence was called) */ + if (commandBuffer->autoReleaseFence) { - renderer->availableFenceCapacity *= 2; - renderer->availableFences = SDL_realloc( - renderer->availableFences, - renderer->availableFenceCapacity * sizeof(D3D11Fence*) - ); + D3D11_INTERNAL_ReleaseFenceToPool(renderer, commandBuffer->fence); } - renderer->availableFences[renderer->availableFenceCount] = commandBuffer->fence; - renderer->availableFenceCount += 1; - SDL_UnlockMutex(renderer->fenceLock); /* Return command buffer to pool */ SDL_LockMutex(renderer->acquireCommandBufferLock); @@ -3193,6 +3206,23 @@ static void D3D11_INTERNAL_CleanCommandBuffer( } } +static void D3D11_INTERNAL_WaitForFence( + D3D11Renderer *renderer, + D3D11Fence *fence +) { + BOOL queryData; + + while (S_OK != ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous*) fence->handle, + &queryData, + sizeof(queryData), + 0 + )) { + /* Spin until we get a result back... */ + } +} + static void D3D11_Submit( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer @@ -3280,8 +3310,13 @@ static Refresh_Fence* D3D11_SubmitAndAcquireFence( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer ) { - NOT_IMPLEMENTED - return NULL; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Fence *fence = d3d11CommandBuffer->fence; + + d3d11CommandBuffer->autoReleaseFence = 0; + D3D11_Submit(driverData, commandBuffer); + + return (Refresh_Fence*) fence; } static void D3D11_Wait( @@ -3289,7 +3324,6 @@ static void D3D11_Wait( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *commandBuffer; - BOOL queryData; /* * Wait for all submitted command buffers to complete. @@ -3297,15 +3331,10 @@ static void D3D11_Wait( */ for (uint32_t i = 0; i < renderer->submittedCommandBufferCount; i += 1) { - while (S_OK != ID3D11DeviceContext_GetData( - renderer->immediateContext, - (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->fence->handle, - &queryData, - sizeof(queryData), - 0 - )) { - /* Spin until we get a result back... */ - } + D3D11_INTERNAL_WaitForFence( + renderer, + renderer->submittedCommandBuffers[i]->fence + ); } SDL_LockMutex(renderer->contextLock); @@ -3325,22 +3354,69 @@ static void D3D11_WaitForFences( uint32_t fenceCount, Refresh_Fence **pFences ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11Fence *fence; + BOOL queryData; + HRESULT res = S_FALSE; + + if (waitAll) + { + for (uint32_t i = 0; i < fenceCount; i += 1) + { + fence = (D3D11Fence*) pFences[i]; + D3D11_INTERNAL_WaitForFence(renderer, fence); + } + } + else + { + while (res != S_OK) + { + for (uint32_t i = 0; i < fenceCount; i += 1) + { + fence = (D3D11Fence*) pFences[i]; + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous*) fence->handle, + &queryData, + sizeof(queryData), + 0 + ); + if (res == S_OK) + { + break; + } + } + } + } } static int D3D11_QueryFence( Refresh_Renderer *driverData, Refresh_Fence *fence ) { - NOT_IMPLEMENTED - return 0; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11Fence *d3d11Fence = (D3D11Fence*) fence; + BOOL queryData; + + HRESULT res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous*) d3d11Fence->handle, + &queryData, + sizeof(queryData), + 0 + ); + + return res == S_OK; } static void D3D11_ReleaseFence( Refresh_Renderer *driverData, Refresh_Fence *fence ) { - NOT_IMPLEMENTED + D3D11_INTERNAL_ReleaseFenceToPool( + (D3D11Renderer*) driverData, + (D3D11Fence*) fence + ); } /* Device Creation */ -- 2.25.1 From 17bc9f90eb788e31bf31a06162572f40d9e60d68 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 00:35:19 -0600 Subject: [PATCH 45/69] QueueDestroyComputePipeline + style cleanup for QueueDestroyGraphicsPipeline --- src/Refresh_Driver_D3D11.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 0fea013..0b6bf0d 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2183,7 +2183,8 @@ static void D3D11_QueueDestroyComputePipeline( Refresh_Renderer *driverData, Refresh_ComputePipeline *computePipeline ) { - NOT_IMPLEMENTED + D3D11ComputePipeline *d3d11ComputePipeline = (D3D11ComputePipeline*) computePipeline; + SDL_free(d3d11ComputePipeline); } static void D3D11_QueueDestroyGraphicsPipeline( @@ -2191,22 +2192,22 @@ static void D3D11_QueueDestroyGraphicsPipeline( Refresh_GraphicsPipeline *graphicsPipeline ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11GraphicsPipeline *d3dGraphicsPipeline = (D3D11GraphicsPipeline*) graphicsPipeline; + D3D11GraphicsPipeline *d3d11GraphicsPipeline = (D3D11GraphicsPipeline*) graphicsPipeline; - ID3D11BlendState_Release(d3dGraphicsPipeline->colorAttachmentBlendState); - ID3D11DepthStencilState_Release(d3dGraphicsPipeline->depthStencilState); - ID3D11RasterizerState_Release(d3dGraphicsPipeline->rasterizerState); + ID3D11BlendState_Release(d3d11GraphicsPipeline->colorAttachmentBlendState); + ID3D11DepthStencilState_Release(d3d11GraphicsPipeline->depthStencilState); + ID3D11RasterizerState_Release(d3d11GraphicsPipeline->rasterizerState); - if (d3dGraphicsPipeline->inputLayout) + if (d3d11GraphicsPipeline->inputLayout) { - ID3D11InputLayout_Release(d3dGraphicsPipeline->inputLayout); + ID3D11InputLayout_Release(d3d11GraphicsPipeline->inputLayout); } - if (d3dGraphicsPipeline->vertexStrides) + if (d3d11GraphicsPipeline->vertexStrides) { - SDL_free(d3dGraphicsPipeline->vertexStrides); + SDL_free(d3d11GraphicsPipeline->vertexStrides); } - SDL_free(d3dGraphicsPipeline); + SDL_free(d3d11GraphicsPipeline); } /* Graphics State */ -- 2.25.1 From 463c298c96f6da95819f4fcb662109df5fc67a01 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 00:57:26 -0600 Subject: [PATCH 46/69] GetBufferData --- src/Refresh_Driver_D3D11.c | 70 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 0b6bf0d..fbb38e6 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1852,7 +1852,73 @@ static void D3D11_GetBufferData( void* data, uint32_t dataLengthInBytes ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + D3D11_BUFFER_DESC stagingBufferDesc; + ID3D11Resource *stagingBuffer; + D3D11_BOX srcBox = { 0, 0, 0, dataLengthInBytes, 1, 1 }; + D3D11_MAPPED_SUBRESOURCE mappedSubresource; + HRESULT res; + + /* Create staging buffer */ + stagingBufferDesc.ByteWidth = dataLengthInBytes; + stagingBufferDesc.Usage = D3D11_USAGE_STAGING; + stagingBufferDesc.BindFlags = 0; + stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingBufferDesc.MiscFlags = 0; + stagingBufferDesc.StructureByteStride = 0; + + res = ID3D11Device_CreateBuffer( + renderer->device, + &stagingBufferDesc, + NULL, + (ID3D11Buffer**) &stagingBuffer + ); + ERROR_CHECK_RETURN("Could not create staging buffer for readback", ); + + /* Copy data into staging buffer */ + ID3D11DeviceContext_CopySubresourceRegion( + renderer->immediateContext, + stagingBuffer, + 0, + 0, + 0, + 0, + (ID3D11Resource*) d3d11Buffer->handle, + 0, + &srcBox + ); + + /* Read from the staging buffer */ + res = ID3D11DeviceContext_Map( + renderer->immediateContext, + stagingBuffer, + 0, + D3D11_MAP_READ, + 0, + &mappedSubresource + ); + if (FAILED(res)) + { + D3D11_INTERNAL_LogError( + renderer->device, + "Failed to map staging buffer for read!", + res + ); + ID3D11Buffer_Release(stagingBuffer); + return; + } + + SDL_memcpy(data, mappedSubresource.pData, dataLengthInBytes); + + ID3D11DeviceContext_Unmap( + renderer->immediateContext, + stagingBuffer, + 0 + ); + + /* Clean up the staging buffer */ + ID3D11Resource_Release(stagingBuffer); } /* Uniforms */ @@ -3741,7 +3807,7 @@ tryCreateDevice: Refresh_LogInfo("D3D11 Adapter: %S", adapterDesc.Description); /* Create mutexes */ - renderer->contextLock = SDL_CreateMutex(); + renderer->contextLock = SDL_CreateMutex(); /* FIXME: We should be using this *everywhere* the immediate context is accessed! */ renderer->acquireCommandBufferLock = SDL_CreateMutex(); renderer->uniformBufferLock = SDL_CreateMutex(); renderer->fenceLock = SDL_CreateMutex(); -- 2.25.1 From 3f6ecd38a004e9e2b55ad2b3e61fc0c1190210ea Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 02:02:41 -0600 Subject: [PATCH 47/69] Actually compile compute shaders --- src/Refresh_Driver_D3D11.c | 57 ++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index fbb38e6..63f2a0d 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1124,14 +1124,48 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_Renderer *driverData, Refresh_ComputeShaderInfo *computeShaderInfo ) { + D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11ComputePipeline* pipeline = (D3D11ComputePipeline*) SDL_malloc(sizeof(D3D11ComputePipeline)); D3D11ShaderModule* shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule; + ID3D10Blob *errorBlob; + HRESULT res; - pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; pipeline->numTextures = computeShaderInfo->imageBindingCount; pipeline->numBuffers = computeShaderInfo->bufferBindingCount; pipeline->computeUniformBlockSize = computeShaderInfo->uniformBufferSize; + if (shaderModule->shader == NULL) + { + res = renderer->D3DCompileFunc( + shaderModule->shaderSource, + shaderModule->shaderSourceLength, + NULL, + NULL, + NULL, + "main", /* FIXME: Is this correct or should this be computeShaderInfo.entryPoint? */ + "cs_5_0", + 0, + 0, + &shaderModule->blob, + &errorBlob + ); + if (FAILED(res)) + { + Refresh_LogError("Compute Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); + return NULL; + } + + res = ID3D11Device_CreateComputeShader( + renderer->device, + ID3D10Blob_GetBufferPointer(shaderModule->blob), + ID3D10Blob_GetBufferSize(shaderModule->blob), + NULL, + (ID3D11ComputeShader**) &shaderModule->shader + ); + ERROR_CHECK_RETURN("Could not create compute shader", NULL); /* FIXME: This leaks the pipeline! */ + } + pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; + return (Refresh_ComputePipeline*) pipeline; } @@ -1196,10 +1230,6 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( if (vertShaderModule->shader == NULL) { - /* FIXME: - * Could we store a flag in the shaderc output to mark if a shader is vertex/fragment? - * Then we could compile on shader module creation instead of at bind time. - */ res = renderer->D3DCompileFunc( vertShaderModule->shaderSource, vertShaderModule->shaderSourceLength, @@ -1226,7 +1256,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( NULL, (ID3D11VertexShader**) &vertShaderModule->shader ); - ERROR_CHECK_RETURN("Could not create vertex shader", NULL); + ERROR_CHECK_RETURN("Could not create vertex shader", NULL); /* FIXME: This leaks the pipeline! */ } pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shader; pipeline->numVertexSamplers = pipelineCreateInfo->vertexShaderInfo.samplerBindingCount; @@ -1291,7 +1321,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( NULL, (ID3D11PixelShader**) &fragShaderModule->shader ); - ERROR_CHECK_RETURN("Could not create pixel shader", NULL); + ERROR_CHECK_RETURN("Could not create pixel shader", NULL); /* FIXME: This leaks the pipeline! */ } pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader; pipeline->numFragmentSamplers = pipelineCreateInfo->fragmentShaderInfo.samplerBindingCount; @@ -1358,8 +1388,11 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule)); - /* We don't know whether this is a vertex or fragment shader, + /* We don't know whether this is a vertex, fragment, or compute shader, * so wait to compile until we bind to a pipeline... + * + * FIXME: Could we store a flag in the shaderc output to mark if a shader is vertex/fragment/compute? + * Then we could compile on shader module creation instead of at bind time. */ shaderModule->shader = NULL; shaderModule->blob = NULL; @@ -1419,11 +1452,7 @@ static Refresh_Texture* D3D11_CreateTexture( desc2D.CPUAccessFlags = 0; desc2D.Format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; desc2D.MipLevels = textureCreateInfo->levelCount; - desc2D.MiscFlags = ( - (textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT) ? - D3D11_RESOURCE_MISC_GENERATE_MIPS : - 0 - ); + desc2D.MiscFlags = isRenderTarget ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; desc2D.SampleDesc.Quality = 0; desc2D.Usage = D3D11_USAGE_DEFAULT; @@ -2218,7 +2247,7 @@ static void D3D11_QueueDestroyBuffer( if (d3d11Buffer->uav) { - ID3D11UnorderedAccessView_Release(d3d11Buffer->handle); + ID3D11UnorderedAccessView_Release(d3d11Buffer->uav); } ID3D11Buffer_Release(d3d11Buffer->handle); -- 2.25.1 From 06d93a55a3cb490bd42446c8f444d77af300386e Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 02:17:08 -0600 Subject: [PATCH 48/69] PushComputeShaderUniforms + CreateComputePipeline fix --- src/Refresh_Driver_D3D11.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 63f2a0d..74f1ae8 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1132,7 +1132,6 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( pipeline->numTextures = computeShaderInfo->imageBindingCount; pipeline->numBuffers = computeShaderInfo->bufferBindingCount; - pipeline->computeUniformBlockSize = computeShaderInfo->uniformBufferSize; if (shaderModule->shader == NULL) { @@ -1165,6 +1164,10 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( ERROR_CHECK_RETURN("Could not create compute shader", NULL); /* FIXME: This leaks the pipeline! */ } pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; + pipeline->computeUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( + (uint32_t) computeShaderInfo->uniformBufferSize, + 256 + ); return (Refresh_ComputePipeline*) pipeline; } @@ -2130,8 +2133,37 @@ static uint32_t D3D11_PushComputeShaderUniforms( void *data, uint32_t dataLengthInBytes ) { - NOT_IMPLEMENTED - return 0; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11ComputePipeline *computePipeline = d3d11CommandBuffer->computePipeline; + uint32_t offset; + + if (d3d11CommandBuffer->computeUniformBuffer->offset + computePipeline->computeUniformBlockSize >= UBO_BUFFER_SIZE) + { + /* Out of space! Get a new uniform buffer. */ + D3D11_INTERNAL_AcquireUniformBuffer( + renderer, + d3d11CommandBuffer, + &d3d11CommandBuffer->computeUniformBuffer, + computePipeline->computeUniformBlockSize + ); + } + + offset = d3d11CommandBuffer->computeUniformBuffer->offset; + + D3D11_INTERNAL_SetBufferData( + renderer, + d3d11CommandBuffer, + d3d11CommandBuffer->computeUniformBuffer->d3d11Buffer, + d3d11CommandBuffer->computeUniformBuffer->offset, + data, + dataLengthInBytes, + 0 /* FIXME: Should be NoOverwrite! */ + ); + + d3d11CommandBuffer->computeUniformBuffer->offset += (uint32_t) computePipeline->computeUniformBlockSize; /* FIXME: Is this cast safe? */ + + return offset; } /* Samplers */ -- 2.25.1 From 9b8dfd8207220bd95645108e7c5fd92272cf662e Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 11:04:32 -0600 Subject: [PATCH 49/69] Fix repeated buffer writes by using USAGE_DEFAULT/UpdateSubresource instead of DYNAMIC/Map for non-uniform buffers --- src/Refresh_Driver_D3D11.c | 88 ++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 74f1ae8..4dd899f 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -432,9 +432,8 @@ typedef struct D3D11ComputePipeline typedef struct D3D11Buffer { ID3D11Buffer *handle; + ID3D11UnorderedAccessView* uav; uint32_t size; - uint8_t isDynamic; - ID3D11UnorderedAccessView *uav; } D3D11Buffer; typedef struct D3D11UniformBuffer @@ -1648,26 +1647,23 @@ static Refresh_Buffer* D3D11_CreateBuffer( D3D11Buffer *d3d11Buffer; HRESULT res; - uint8_t isDynamic = 1; - uint32_t bindFlags = 0; + bufferDesc.BindFlags = 0; if (usageFlags & REFRESH_BUFFERUSAGE_VERTEX_BIT) { - bindFlags |= D3D11_BIND_VERTEX_BUFFER; + bufferDesc.BindFlags |= D3D11_BIND_VERTEX_BUFFER; } if (usageFlags & REFRESH_BUFFERUSAGE_INDEX_BIT) { - bindFlags |= D3D11_BIND_INDEX_BUFFER; + bufferDesc.BindFlags |= D3D11_BIND_INDEX_BUFFER; } if ((usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) || (usageFlags & REFRESH_BUFFERUSAGE_INDIRECT_BIT)) { - bindFlags |= D3D11_BIND_UNORDERED_ACCESS; - isDynamic = 0; + bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; } - bufferDesc.BindFlags = bindFlags; bufferDesc.ByteWidth = sizeInBytes; - bufferDesc.Usage = isDynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; - bufferDesc.CPUAccessFlags = isDynamic ? D3D11_CPU_ACCESS_WRITE : 0; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = (usageFlags & REFRESH_BUFFERUSAGE_INDIRECT_BIT) ? D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS : 0; bufferDesc.StructureByteStride = 0; @@ -1705,7 +1701,6 @@ static Refresh_Buffer* D3D11_CreateBuffer( d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); d3d11Buffer->handle = bufferHandle; d3d11Buffer->size = sizeInBytes; - d3d11Buffer->isDynamic = isDynamic; d3d11Buffer->uav = uav; return (Refresh_Buffer*) d3d11Buffer; @@ -1807,56 +1802,56 @@ static void D3D11_INTERNAL_SetBufferData( uint32_t offsetInBytes, void* data, uint32_t dataLength, - uint8_t noOverwrite + uint8_t isUniformBuffer ) { D3D11_BOX dstBox; D3D11_MAPPED_SUBRESOURCE subres; HRESULT res; - /* Use UpdateSubresource for non-dynamic buffers (i.e. compute/indirect) */ - if (!buffer->isDynamic) + if (isUniformBuffer) { - dstBox.left = 0; - dstBox.right = dataLength; + res = ID3D11DeviceContext_Map( + commandBuffer->context, + (ID3D11Resource*) buffer->handle, + 0, + D3D11_MAP_WRITE_DISCARD, /* FIXME: Use NoOverwrite for subsequent writes! */ + 0, + &subres + ); + ERROR_CHECK_RETURN("Could not map buffer for writing!", ); + + SDL_memcpy( + (uint8_t*) subres.pData + offsetInBytes, + data, + dataLength + ); + + ID3D11DeviceContext_Unmap( + commandBuffer->context, + (ID3D11Resource*) buffer->handle, + 0 + ); + } + else + { + dstBox.left = offsetInBytes; + dstBox.right = offsetInBytes + dataLength; dstBox.top = 0; dstBox.bottom = 1; dstBox.front = 0; dstBox.back = 1; - ID3D11DeviceContext_UpdateSubresource( + ID3D11DeviceContext1_UpdateSubresource1( commandBuffer->context, (ID3D11Resource*) buffer->handle, 0, &dstBox, data, dataLength, - 1 + 1, + dataLength == buffer->size ? D3D11_COPY_DISCARD : 0 ); - - return; } - - res = ID3D11DeviceContext_Map( - commandBuffer->context, - (ID3D11Resource*) buffer->handle, - 0, - noOverwrite ? D3D11_MAP_WRITE_NO_OVERWRITE : D3D11_MAP_WRITE_DISCARD, - 0, - &subres - ); - ERROR_CHECK_RETURN("Could not map buffer for writing!", ); - - SDL_memcpy( - (uint8_t*) subres.pData + offsetInBytes, - data, - dataLength - ); - - ID3D11DeviceContext_Unmap( - commandBuffer->context, - (ID3D11Resource*) buffer->handle, - 0 - ); } static void D3D11_SetBufferData( @@ -1983,7 +1978,6 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( uniformBuffer->d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); uniformBuffer->d3d11Buffer->handle = bufferHandle; uniformBuffer->d3d11Buffer->size = UBO_BUFFER_SIZE; - uniformBuffer->d3d11Buffer->isDynamic = 1; uniformBuffer->d3d11Buffer->uav = NULL; /* Add it to the available pool */ @@ -2080,7 +2074,7 @@ static uint32_t D3D11_PushVertexShaderUniforms( d3d11CommandBuffer->vertexUniformBuffer->offset, data, dataLengthInBytes, - 0 /* FIXME: Should be NoOverwrite! */ + 1 ); d3d11CommandBuffer->vertexUniformBuffer->offset += graphicsPipeline->vertexUniformBlockSize; @@ -2119,7 +2113,7 @@ static uint32_t D3D11_PushFragmentShaderUniforms( d3d11CommandBuffer->fragmentUniformBuffer->offset, data, dataLengthInBytes, - 0 /* FIXME: Should be NoOverwrite! */ + 1 ); d3d11CommandBuffer->fragmentUniformBuffer->offset += graphicsPipeline->fragmentUniformBlockSize; @@ -2158,7 +2152,7 @@ static uint32_t D3D11_PushComputeShaderUniforms( d3d11CommandBuffer->computeUniformBuffer->offset, data, dataLengthInBytes, - 0 /* FIXME: Should be NoOverwrite! */ + 1 ); d3d11CommandBuffer->computeUniformBuffer->offset += (uint32_t) computePipeline->computeUniformBlockSize; /* FIXME: Is this cast safe? */ -- 2.25.1 From 917896e5f4cda60162573bd92a5a8e1f4842e851 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 11:19:51 -0600 Subject: [PATCH 50/69] Use NO_OVERWRITE on uniform buffers after the initial WRITE_DISCARD + SetBufferData cleanup --- src/Refresh_Driver_D3D11.c | 137 +++++++++++++++---------------------- 1 file changed, 57 insertions(+), 80 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 4dd899f..ee49475 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -440,6 +440,7 @@ typedef struct D3D11UniformBuffer { D3D11Buffer *d3d11Buffer; uint32_t offset; + uint8_t hasDiscarded; } D3D11UniformBuffer; typedef struct D3D11Fence @@ -1795,65 +1796,6 @@ static void D3D11_CopyTextureToBuffer( /* Buffer Data */ -static void D3D11_INTERNAL_SetBufferData( - D3D11Renderer *renderer, - D3D11CommandBuffer *commandBuffer, - D3D11Buffer *buffer, - uint32_t offsetInBytes, - void* data, - uint32_t dataLength, - uint8_t isUniformBuffer -) { - D3D11_BOX dstBox; - D3D11_MAPPED_SUBRESOURCE subres; - HRESULT res; - - if (isUniformBuffer) - { - res = ID3D11DeviceContext_Map( - commandBuffer->context, - (ID3D11Resource*) buffer->handle, - 0, - D3D11_MAP_WRITE_DISCARD, /* FIXME: Use NoOverwrite for subsequent writes! */ - 0, - &subres - ); - ERROR_CHECK_RETURN("Could not map buffer for writing!", ); - - SDL_memcpy( - (uint8_t*) subres.pData + offsetInBytes, - data, - dataLength - ); - - ID3D11DeviceContext_Unmap( - commandBuffer->context, - (ID3D11Resource*) buffer->handle, - 0 - ); - } - else - { - dstBox.left = offsetInBytes; - dstBox.right = offsetInBytes + dataLength; - dstBox.top = 0; - dstBox.bottom = 1; - dstBox.front = 0; - dstBox.back = 1; - - ID3D11DeviceContext1_UpdateSubresource1( - commandBuffer->context, - (ID3D11Resource*) buffer->handle, - 0, - &dstBox, - data, - dataLength, - 1, - dataLength == buffer->size ? D3D11_COPY_DISCARD : 0 - ); - } -} - static void D3D11_SetBufferData( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -1862,14 +1804,19 @@ static void D3D11_SetBufferData( void* data, uint32_t dataLength ) { - D3D11_INTERNAL_SetBufferData( - (D3D11Renderer*) driverData, - (D3D11CommandBuffer*) commandBuffer, - (D3D11Buffer*) buffer, - offsetInBytes, + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + D3D11_BOX dstBox = { offsetInBytes, 0, 0, offsetInBytes + dataLength, 1, 1 }; + + ID3D11DeviceContext1_UpdateSubresource1( + d3d11CommandBuffer->context, + (ID3D11Resource*) d3d11Buffer->handle, + 0, + &dstBox, data, dataLength, - 0 + 1, + dataLength == d3d11Buffer->size ? D3D11_COPY_DISCARD : 0 ); } @@ -1975,6 +1922,7 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer)); uniformBuffer->offset = 0; + uniformBuffer->hasDiscarded = 0; uniformBuffer->d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); uniformBuffer->d3d11Buffer->handle = bufferHandle; uniformBuffer->d3d11Buffer->size = UBO_BUFFER_SIZE; @@ -2024,6 +1972,7 @@ static uint8_t D3D11_INTERNAL_AcquireUniformBuffer( SDL_UnlockMutex(renderer->uniformBufferLock); /* Reset the uniform buffer */ + uniformBuffer->hasDiscarded = 0; uniformBuffer->offset = 0; /* Bind the uniform buffer to the command buffer */ @@ -2043,6 +1992,40 @@ static uint8_t D3D11_INTERNAL_AcquireUniformBuffer( return 1; } +static void D3D11_INTERNAL_SetUniformBufferData( + D3D11Renderer *renderer, + D3D11CommandBuffer *commandBuffer, + D3D11UniformBuffer *uniformBuffer, + void* data, + uint32_t dataLength +) { + D3D11_MAPPED_SUBRESOURCE subres; + + HRESULT res = ID3D11DeviceContext_Map( + commandBuffer->context, + (ID3D11Resource*) uniformBuffer->d3d11Buffer->handle, + 0, + uniformBuffer->hasDiscarded ? D3D11_MAP_WRITE_NO_OVERWRITE : D3D11_MAP_WRITE_DISCARD, + 0, + &subres + ); + ERROR_CHECK_RETURN("Could not map buffer for writing!", ); + + SDL_memcpy( + (uint8_t*) subres.pData + uniformBuffer->offset, + data, + dataLength + ); + + ID3D11DeviceContext_Unmap( + commandBuffer->context, + (ID3D11Resource*) uniformBuffer->d3d11Buffer->handle, + 0 + ); + + uniformBuffer->hasDiscarded = 1; +} + static uint32_t D3D11_PushVertexShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -2067,14 +2050,12 @@ static uint32_t D3D11_PushVertexShaderUniforms( offset = d3d11CommandBuffer->vertexUniformBuffer->offset; - D3D11_INTERNAL_SetBufferData( + D3D11_INTERNAL_SetUniformBufferData( renderer, d3d11CommandBuffer, - d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer, - d3d11CommandBuffer->vertexUniformBuffer->offset, + d3d11CommandBuffer->vertexUniformBuffer, data, - dataLengthInBytes, - 1 + dataLengthInBytes ); d3d11CommandBuffer->vertexUniformBuffer->offset += graphicsPipeline->vertexUniformBlockSize; @@ -2106,14 +2087,12 @@ static uint32_t D3D11_PushFragmentShaderUniforms( offset = d3d11CommandBuffer->fragmentUniformBuffer->offset; - D3D11_INTERNAL_SetBufferData( + D3D11_INTERNAL_SetUniformBufferData( renderer, d3d11CommandBuffer, - d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer, - d3d11CommandBuffer->fragmentUniformBuffer->offset, + d3d11CommandBuffer->fragmentUniformBuffer, data, - dataLengthInBytes, - 1 + dataLengthInBytes ); d3d11CommandBuffer->fragmentUniformBuffer->offset += graphicsPipeline->fragmentUniformBlockSize; @@ -2145,14 +2124,12 @@ static uint32_t D3D11_PushComputeShaderUniforms( offset = d3d11CommandBuffer->computeUniformBuffer->offset; - D3D11_INTERNAL_SetBufferData( + D3D11_INTERNAL_SetUniformBufferData( renderer, d3d11CommandBuffer, - d3d11CommandBuffer->computeUniformBuffer->d3d11Buffer, - d3d11CommandBuffer->computeUniformBuffer->offset, + d3d11CommandBuffer->computeUniformBuffer, data, - dataLengthInBytes, - 1 + dataLengthInBytes ); d3d11CommandBuffer->computeUniformBuffer->offset += (uint32_t) computePipeline->computeUniformBlockSize; /* FIXME: Is this cast safe? */ -- 2.25.1 From 7093ce0094e4d13d99434fee0322e748a1d00c63 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 12:09:29 -0600 Subject: [PATCH 51/69] First rough pass at color RTs --- src/Refresh_Driver_D3D11.c | 107 +++++++++++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 22 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ee49475..a740290 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1413,6 +1413,7 @@ static Refresh_Texture* D3D11_CreateTexture( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; uint8_t isSampler, isCompute, isRenderTarget, isDepthStencil; + DXGI_FORMAT format; ID3D11Resource *textureHandle; ID3D11ShaderResourceView *srv = NULL; ID3D11RenderTargetView *rtv = NULL; @@ -1426,6 +1427,8 @@ static Refresh_Texture* D3D11_CreateTexture( isSampler = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT; isCompute = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COMPUTE_BIT; + format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; + if (textureCreateInfo->depth <= 1) { D3D11_TEXTURE2D_DESC desc2D; @@ -1453,7 +1456,7 @@ static Refresh_Texture* D3D11_CreateTexture( desc2D.ArraySize = textureCreateInfo->isCube ? 6 : 1; desc2D.CPUAccessFlags = 0; - desc2D.Format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; + desc2D.Format = format; desc2D.MipLevels = textureCreateInfo->levelCount; desc2D.MiscFlags = isRenderTarget ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; @@ -1472,7 +1475,7 @@ static Refresh_Texture* D3D11_CreateTexture( if (isSampler) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = desc2D.Format; + srvDesc.Format = format; if (textureCreateInfo->isCube) { @@ -1505,9 +1508,9 @@ static Refresh_Texture* D3D11_CreateTexture( if (isCompute) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; - uavDesc.Format = desc2D.Format; + uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; - uavDesc.Texture2D.MipSlice = 0; /* FIXME: Is this right? */ + uavDesc.Texture2D.MipSlice = 0; /* FIXME */ res = ID3D11Device_CreateUnorderedAccessView( renderer->device, @@ -1526,6 +1529,40 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } + + /* Create the RTV, if applicable */ + if (isRenderTarget) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = format; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; /* FIXME: MSAA? */ + rtvDesc.Texture2D.MipSlice = 0; /* FIXME */ + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + textureHandle, + &rtvDesc, + &rtv + ); + if (FAILED(res)) + { + ID3D11Resource_Release(textureHandle); + if (srv != NULL) + { + ID3D11ShaderResourceView_Release(srv); + } + if (uav != NULL) + { + ID3D11UnorderedAccessView_Release(uav); + } + D3D11_INTERNAL_LogError(renderer->device, "Could not create RTV for 2D texture", res); + return NULL; + } + } + else if (isDepthStencil) + { + NOT_IMPLEMENTED + } } else { @@ -1544,9 +1581,13 @@ static Refresh_Texture* D3D11_CreateTexture( { desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; } + if (isRenderTarget) + { + desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET; + } desc3D.CPUAccessFlags = 0; - desc3D.Format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; + desc3D.Format = format; desc3D.MipLevels = textureCreateInfo->levelCount; desc3D.MiscFlags = 0; desc3D.Usage = D3D11_USAGE_DEFAULT; @@ -1563,8 +1604,7 @@ static Refresh_Texture* D3D11_CreateTexture( if (isSampler) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - - srvDesc.Format = desc3D.Format; + srvDesc.Format = format; srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE3D; srvDesc.Texture3D.MipLevels = desc3D.MipLevels; srvDesc.Texture3D.MostDetailedMip = 0; @@ -1587,10 +1627,11 @@ static Refresh_Texture* D3D11_CreateTexture( if (isCompute) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; - uavDesc.Texture3D.MipSlice = 0; + uavDesc.Texture3D.MipSlice = 0; /* FIXME */ uavDesc.Texture3D.FirstWSlice = 0; /* FIXME */ - uavDesc.Texture3D.WSize = 0; /* FIXME */ + uavDesc.Texture3D.WSize = -1; /* FIXME */ res = ID3D11Device_CreateUnorderedAccessView( renderer->device, @@ -1609,16 +1650,38 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } - } - /* Create the RTV or DSV, if applicable */ - if (isRenderTarget) - { - NOT_IMPLEMENTED - } - else if (isDepthStencil) - { - NOT_IMPLEMENTED + /* Create the RTV, if applicable */ + if (isRenderTarget) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = format; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = 0; /* FIXME */ + rtvDesc.Texture3D.FirstWSlice = 0; /* FIXME */ + rtvDesc.Texture3D.WSize = -1; /* FIXME */ + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + textureHandle, + &rtvDesc, + &rtv + ); + if (FAILED(res)) + { + ID3D11Resource_Release(textureHandle); + if (srv != NULL) + { + ID3D11ShaderResourceView_Release(srv); + } + if (uav != NULL) + { + ID3D11UnorderedAccessView_Release(uav); + } + D3D11_INTERNAL_LogError(renderer->device, "Could not create RTV for 3D texture", res); + return NULL; + } + } } d3d11Texture = (D3D11Texture*) SDL_malloc(sizeof(D3D11Texture)); @@ -2219,14 +2282,14 @@ static void D3D11_QueueDestroyTexture( { ID3D11ShaderResourceView_Release(d3d11Texture->shaderView); } - if (d3d11Texture->targetView) - { - ID3D11View_Release(d3d11Texture->targetView); - } if (d3d11Texture->unorderedAccessView) { ID3D11UnorderedAccessView_Release(d3d11Texture->unorderedAccessView); } + if (d3d11Texture->targetView) + { + ID3D11View_Release(d3d11Texture->targetView); + } ID3D11Resource_Release(d3d11Texture->handle); -- 2.25.1 From a6f88ec73a8387f088f106375ca5bba2c7a06195 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 15:28:08 -0600 Subject: [PATCH 52/69] RTV overhaul to fix binding an RT with a specific depth/mip level --- src/Refresh_Driver_D3D11.c | 242 ++++++++++++++++++++++--------------- 1 file changed, 145 insertions(+), 97 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index a740290..8260079 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -355,13 +355,24 @@ static D3D11_FILTER RefreshToD3D11_Filter(Refresh_SamplerStateCreateInfo *create /* Structs */ +typedef struct D3D11TargetView +{ + ID3D11View *view; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ + uint32_t level; + uint32_t depth; + uint32_t layer; +} D3D11TargetView; + typedef struct D3D11Texture { /* D3D Handles */ ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ ID3D11ShaderResourceView *shaderView; - ID3D11View *targetView; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ - ID3D11UnorderedAccessView *unorderedAccessView; + ID3D11UnorderedAccessView *unorderedAccessView; /* FIXME: This needs to be a dynamic array! */ + + D3D11TargetView *targetViews; + uint32_t targetViewCount; + uint32_t targetViewCapacity; /* Basic Info */ Refresh_TextureFormat format; @@ -370,6 +381,7 @@ typedef struct D3D11Texture uint32_t depth; uint32_t levelCount; uint8_t isCube; + uint8_t isRenderTarget; } D3D11Texture; typedef struct D3D11SwapchainData @@ -1120,6 +1132,8 @@ static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout( return result; } +/* Pipeline Creation */ + static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_Renderer *driverData, Refresh_ComputeShaderInfo *computeShaderInfo @@ -1336,6 +1350,8 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( return (Refresh_GraphicsPipeline*) pipeline; } +/* Resource Creation */ + static Refresh_Sampler* D3D11_CreateSampler( Refresh_Renderer *driverData, Refresh_SamplerStateCreateInfo *samplerStateCreateInfo @@ -1377,7 +1393,6 @@ static Refresh_Sampler* D3D11_CreateSampler( ); ERROR_CHECK_RETURN("Could not create sampler state", NULL); - /* FIXME: Is there even a point to having a D3D11Sampler struct if it's just a wrapper? */ d3d11Sampler = (D3D11Sampler*) SDL_malloc(sizeof(D3D11Sampler)); d3d11Sampler->handle = samplerStateHandle; @@ -1412,17 +1427,15 @@ static Refresh_Texture* D3D11_CreateTexture( Refresh_TextureCreateInfo *textureCreateInfo ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - uint8_t isSampler, isCompute, isRenderTarget, isDepthStencil; + uint8_t isSampler, isCompute, isColorTarget, isDepthStencil; DXGI_FORMAT format; ID3D11Resource *textureHandle; ID3D11ShaderResourceView *srv = NULL; - ID3D11RenderTargetView *rtv = NULL; - ID3D11DepthStencilView *dsv = NULL; ID3D11UnorderedAccessView *uav = NULL; D3D11Texture *d3d11Texture; HRESULT res; - isRenderTarget = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT; + isColorTarget = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT; isDepthStencil = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT; isSampler = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT; isCompute = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COMPUTE_BIT; @@ -1445,7 +1458,7 @@ static Refresh_Texture* D3D11_CreateTexture( { desc2D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; } - if (isRenderTarget) + if (isColorTarget) { desc2D.BindFlags |= D3D11_BIND_RENDER_TARGET; } @@ -1458,7 +1471,7 @@ static Refresh_Texture* D3D11_CreateTexture( desc2D.CPUAccessFlags = 0; desc2D.Format = format; desc2D.MipLevels = textureCreateInfo->levelCount; - desc2D.MiscFlags = isRenderTarget ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; + desc2D.MiscFlags = 0; desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; desc2D.SampleDesc.Quality = 0; desc2D.Usage = D3D11_USAGE_DEFAULT; @@ -1529,40 +1542,6 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } - - /* Create the RTV, if applicable */ - if (isRenderTarget) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = format; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; /* FIXME: MSAA? */ - rtvDesc.Texture2D.MipSlice = 0; /* FIXME */ - - res = ID3D11Device_CreateRenderTargetView( - renderer->device, - textureHandle, - &rtvDesc, - &rtv - ); - if (FAILED(res)) - { - ID3D11Resource_Release(textureHandle); - if (srv != NULL) - { - ID3D11ShaderResourceView_Release(srv); - } - if (uav != NULL) - { - ID3D11UnorderedAccessView_Release(uav); - } - D3D11_INTERNAL_LogError(renderer->device, "Could not create RTV for 2D texture", res); - return NULL; - } - } - else if (isDepthStencil) - { - NOT_IMPLEMENTED - } } else { @@ -1581,7 +1560,7 @@ static Refresh_Texture* D3D11_CreateTexture( { desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; } - if (isRenderTarget) + if (isColorTarget) { desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET; } @@ -1650,38 +1629,6 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } - - /* Create the RTV, if applicable */ - if (isRenderTarget) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = format; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = 0; /* FIXME */ - rtvDesc.Texture3D.FirstWSlice = 0; /* FIXME */ - rtvDesc.Texture3D.WSize = -1; /* FIXME */ - - res = ID3D11Device_CreateRenderTargetView( - renderer->device, - textureHandle, - &rtvDesc, - &rtv - ); - if (FAILED(res)) - { - ID3D11Resource_Release(textureHandle); - if (srv != NULL) - { - ID3D11ShaderResourceView_Release(srv); - } - if (uav != NULL) - { - ID3D11UnorderedAccessView_Release(uav); - } - D3D11_INTERNAL_LogError(renderer->device, "Could not create RTV for 3D texture", res); - return NULL; - } - } } d3d11Texture = (D3D11Texture*) SDL_malloc(sizeof(D3D11Texture)); @@ -1692,9 +1639,23 @@ static Refresh_Texture* D3D11_CreateTexture( d3d11Texture->depth = textureCreateInfo->depth; d3d11Texture->levelCount = textureCreateInfo->levelCount; d3d11Texture->isCube = textureCreateInfo->isCube; - d3d11Texture->targetView = isRenderTarget ? (ID3D11View*) rtv : (ID3D11View*) dsv; + d3d11Texture->isRenderTarget = isColorTarget | isDepthStencil; d3d11Texture->shaderView = srv; d3d11Texture->unorderedAccessView = uav; + d3d11Texture->targetViewCount = 0; + + if (d3d11Texture->isRenderTarget) + { + d3d11Texture->targetViewCapacity = d3d11Texture->isCube ? 6 : 1; + d3d11Texture->targetViews = SDL_malloc( + sizeof(ID3D11RenderTargetView) * d3d11Texture->targetViewCount + ); + } + else + { + d3d11Texture->targetViewCapacity = 0; + d3d11Texture->targetViews = NULL; + } return (Refresh_Texture*) d3d11Texture; } @@ -2286,9 +2247,13 @@ static void D3D11_QueueDestroyTexture( { ID3D11UnorderedAccessView_Release(d3d11Texture->unorderedAccessView); } - if (d3d11Texture->targetView) + if (d3d11Texture->targetViewCount > 0) { - ID3D11View_Release(d3d11Texture->targetView); + for (uint32_t i = 0; i < d3d11Texture->targetViewCount; i += 1) + { + ID3D11View_Release(d3d11Texture->targetViews[i].view); + } + SDL_free(d3d11Texture->targetViews); } ID3D11Resource_Release(d3d11Texture->handle); @@ -2529,6 +2494,80 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( return (Refresh_CommandBuffer*) commandBuffer; } +static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( + D3D11Renderer *renderer, + Refresh_ColorAttachmentInfo *info +) { + D3D11Texture *texture = (D3D11Texture*) info->texture; + D3D11TargetView *targetView; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + ID3D11RenderTargetView *rtv; + HRESULT res; + + /* Does this target already exist? */ + for (uint32_t i = 0; i < texture->targetViewCount; i += 1) + { + targetView = &texture->targetViews[i]; + + if ( targetView->depth == info->depth && + targetView->layer == info->layer && + targetView->level == info->level ) + { + return (ID3D11RenderTargetView*) targetView->view; + } + } + + /* Let's create a new RTV! */ + rtvDesc.Format = RefreshToD3D11_TextureFormat[texture->format]; + if (texture->isCube) + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; /* FIXME: MSAA? */ + rtvDesc.Texture2DArray.ArraySize = 6; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.MipSlice = info->level; + } + else if (texture->depth > 1) + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = info->level; + rtvDesc.Texture3D.FirstWSlice = info->depth; + rtvDesc.Texture3D.WSize = 1; + } + else + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = info->level; + } + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + texture->handle, + &rtvDesc, + &rtv + ); + ERROR_CHECK_RETURN("Could not create RTV!", NULL); + + /* Create the D3D11TargetView to wrap our new RTV */ + if (texture->targetViewCount == texture->targetViewCapacity) + { + texture->targetViewCapacity *= 2; + texture->targetViews = SDL_realloc( + texture->targetViews, + sizeof(D3D11TargetView) * texture->targetViewCapacity + ); + } + + targetView = &texture->targetViews[texture->targetViewCount]; + targetView->depth = info->depth; + targetView->layer = info->layer; + targetView->level = info->level; + targetView->view = (ID3D11View*) rtv; + + texture->targetViewCount += 1; + + return rtv; +} + static void D3D11_BeginRenderPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -2543,11 +2582,6 @@ static void D3D11_BeginRenderPass( D3D11_VIEWPORT viewport; D3D11_RECT scissorRect; - /* FIXME: - * We need to unbind the RT textures on the Refresh side - * if they're bound for sampling on the command buffer! - */ - /* Clear the bound RTs for the current command buffer */ for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { @@ -2558,15 +2592,19 @@ static void D3D11_BeginRenderPass( /* Get RTVs for the color attachments */ for (uint32_t i = 0; i < colorAttachmentCount; i += 1) { - /* FIXME: Cube RTs */ - - d3d11CommandBuffer->rtViews[i] = (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->targetView; + d3d11CommandBuffer->rtViews[i] = D3D11_INTERNAL_FetchRTV( + renderer, + &colorAttachmentInfos[i] + ); } /* Get the DSV for the depth stencil attachment, if applicable */ if (depthStencilAttachmentInfo != NULL) { - d3d11CommandBuffer->dsView = (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->targetView; + NOT_IMPLEMENTED + //d3d11CommandBuffer->dsView = D3D11_INTERNAL_FetchDSV( + // &depthStencilAttachmentInfo + //); } /* Actually set the RTs */ @@ -2589,7 +2627,7 @@ static void D3D11_BeginRenderPass( ID3D11DeviceContext_ClearRenderTargetView( d3d11CommandBuffer->context, - (ID3D11RenderTargetView*) ((D3D11Texture*) colorAttachmentInfos[i].texture)->targetView, + d3d11CommandBuffer->rtViews[i], clearColors ); } @@ -2611,7 +2649,7 @@ static void D3D11_BeginRenderPass( { ID3D11DeviceContext_ClearDepthStencilView( d3d11CommandBuffer->context, - (ID3D11DepthStencilView*) ((D3D11Texture*) depthStencilAttachmentInfo->texture)->targetView, + d3d11CommandBuffer->dsView, dsClearFlags, depthStencilAttachmentInfo->depthStencilClearValue.depth, (uint8_t) depthStencilAttachmentInfo->depthStencilClearValue.stencil @@ -2932,6 +2970,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( ID3D11Texture2D *swapchainTexture; D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; D3D11_TEXTURE2D_DESC textureDesc; + ID3D11RenderTargetView *rtv; HRESULT res; /* Clear all the texture data */ @@ -2955,7 +2994,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( renderer->device, (ID3D11Resource*) swapchainTexture, &rtvDesc, - (ID3D11RenderTargetView**) &pTexture->targetView + &rtv ); if (FAILED(res)) { @@ -2964,16 +3003,22 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( return 0; } - /* Fill out the rest of the texture struct */ - pTexture->handle = NULL; + /* Fill out the texture struct */ + pTexture->handle = NULL; /* The texture does not "own" the swapchain texture, and it can change dynamically. */ pTexture->shaderView = NULL; - pTexture->depth = 1; - pTexture->isCube = 0; + pTexture->unorderedAccessView = NULL; + pTexture->targetViewCapacity = 1; + pTexture->targetViewCount = 1; + pTexture->targetViews = SDL_calloc(1, sizeof(D3D11TargetView)); + pTexture->targetViews[0].view = (ID3D11View*) rtv; ID3D11Texture2D_GetDesc(swapchainTexture, &textureDesc); pTexture->levelCount = textureDesc.MipLevels; pTexture->width = textureDesc.Width; pTexture->height = textureDesc.Height; + pTexture->depth = 1; + pTexture->isCube = 0; + pTexture->isRenderTarget = 1; /* Cleanup */ ID3D11Texture2D_Release(swapchainTexture); @@ -3096,7 +3141,8 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( HRESULT res; /* Release the old RTV */ - ID3D11RenderTargetView_Release(swapchainData->texture.targetView); + ID3D11RenderTargetView_Release(swapchainData->texture.targetViews[0].view); + SDL_free(swapchainData->texture.targetViews); /* Resize the swapchain */ res = IDXGISwapChain_ResizeBuffers( @@ -3135,7 +3181,9 @@ static void D3D11_INTERNAL_DestroySwapchain( return; } - ID3D11RenderTargetView_Release(swapchainData->texture.targetView); + ID3D11RenderTargetView_Release(swapchainData->texture.targetViews[0].view); + SDL_free(swapchainData->texture.targetViews); + IDXGISwapChain_Release(swapchainData->swapchain); windowData->swapchainData = NULL; -- 2.25.1 From 1a87a284c4a85e21f98a133dd55773457ebae475 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 16:03:57 -0600 Subject: [PATCH 53/69] DepthStencilView creation + DS state fixes --- src/Refresh_Driver_D3D11.c | 103 +++++++++++++++++++++++++++++++------ 1 file changed, 86 insertions(+), 17 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 8260079..02b1c53 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -973,26 +973,26 @@ static ID3D11DepthStencilState* D3D11_INTERNAL_FetchDepthStencilState( */ dsDesc.DepthEnable = depthStencilState.depthTestEnable; dsDesc.StencilEnable = depthStencilState.stencilTestEnable; - dsDesc.DepthFunc = depthStencilState.compareOp; + dsDesc.DepthFunc = RefreshToD3D11_CompareOp[depthStencilState.compareOp]; dsDesc.DepthWriteMask = ( depthStencilState.depthWriteEnable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO ); - dsDesc.BackFace.StencilFunc = depthStencilState.backStencilState.compareOp; - dsDesc.BackFace.StencilDepthFailOp = depthStencilState.backStencilState.depthFailOp; - dsDesc.BackFace.StencilFailOp = depthStencilState.backStencilState.failOp; - dsDesc.BackFace.StencilPassOp = depthStencilState.backStencilState.passOp; + dsDesc.BackFace.StencilFunc = RefreshToD3D11_CompareOp[depthStencilState.backStencilState.compareOp]; + dsDesc.BackFace.StencilDepthFailOp = RefreshToD3D11_CompareOp[depthStencilState.backStencilState.depthFailOp]; + dsDesc.BackFace.StencilFailOp = RefreshToD3D11_CompareOp[depthStencilState.backStencilState.failOp]; + dsDesc.BackFace.StencilPassOp = RefreshToD3D11_CompareOp[depthStencilState.backStencilState.passOp]; - dsDesc.FrontFace.StencilFunc = depthStencilState.frontStencilState.compareOp; - dsDesc.FrontFace.StencilDepthFailOp = depthStencilState.frontStencilState.depthFailOp; - dsDesc.FrontFace.StencilFailOp = depthStencilState.frontStencilState.failOp; - dsDesc.FrontFace.StencilPassOp = depthStencilState.frontStencilState.passOp; + dsDesc.FrontFace.StencilFunc = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.compareOp]; + dsDesc.FrontFace.StencilDepthFailOp = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.depthFailOp]; + dsDesc.FrontFace.StencilFailOp = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.failOp]; + dsDesc.FrontFace.StencilPassOp = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.passOp]; /* FIXME: D3D11 doesn't have separate read/write masks for each stencil side. What should we do? */ - dsDesc.StencilReadMask = depthStencilState.backStencilState.compareMask; - dsDesc.StencilWriteMask = depthStencilState.backStencilState.writeMask; + dsDesc.StencilReadMask = depthStencilState.frontStencilState.compareMask; + dsDesc.StencilWriteMask = depthStencilState.frontStencilState.writeMask; /* FIXME: What do we do with these? * depthStencilState.depthBoundsTestEnable @@ -1233,7 +1233,8 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( pipeline->depthStencilAttachmentFormat = RefreshToD3D11_TextureFormat[ pipelineCreateInfo->attachmentInfo.depthStencilFormat ]; - pipeline->stencilRef = pipelineCreateInfo->depthStencilState.backStencilState.reference; /* FIXME: Should we use front or back? */ + /* FIXME: D3D11 doesn't have separate references for each stencil side. What should we do? */ + pipeline->stencilRef = pipelineCreateInfo->depthStencilState.frontStencilState.reference; /* Rasterizer */ @@ -1471,7 +1472,7 @@ static Refresh_Texture* D3D11_CreateTexture( desc2D.CPUAccessFlags = 0; desc2D.Format = format; desc2D.MipLevels = textureCreateInfo->levelCount; - desc2D.MiscFlags = 0; + desc2D.MiscFlags = textureCreateInfo->isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0; desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; desc2D.SampleDesc.Quality = 0; desc2D.Usage = D3D11_USAGE_DEFAULT; @@ -2568,6 +2569,74 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( return rtv; } +static ID3D11DepthStencilView* D3D11_INTERNAL_FetchDSV( + D3D11Renderer* renderer, + Refresh_DepthStencilAttachmentInfo* info +) { + D3D11Texture *texture = (D3D11Texture*)info->texture; + D3D11TargetView *targetView; + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + ID3D11DepthStencilView *dsv; + HRESULT res; + + /* Does this target already exist? */ + for (uint32_t i = 0; i < texture->targetViewCount; i += 1) + { + targetView = &texture->targetViews[i]; + + if ( targetView->depth == info->depth && + targetView->layer == info->layer && + targetView->level == info->level ) + { + return (ID3D11DepthStencilView*) targetView->view; + } + } + + /* Let's create a new DSV! */ + dsvDesc.Format = RefreshToD3D11_TextureFormat[texture->format]; + dsvDesc.Flags = 0; + if (texture->isCube) + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; /* FIXME: MSAA? */ + dsvDesc.Texture2DArray.ArraySize = 6; + dsvDesc.Texture2DArray.FirstArraySlice = 0; + dsvDesc.Texture2DArray.MipSlice = info->level; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = info->level; + } + + res = ID3D11Device_CreateDepthStencilView( + renderer->device, + texture->handle, + &dsvDesc, + &dsv + ); + ERROR_CHECK_RETURN("Could not create DSV!", NULL); + + /* Create the D3D11TargetView to wrap our new DSV */ + if (texture->targetViewCount == texture->targetViewCapacity) + { + texture->targetViewCapacity *= 2; + texture->targetViews = SDL_realloc( + texture->targetViews, + sizeof(D3D11TargetView) * texture->targetViewCapacity + ); + } + + targetView = &texture->targetViews[texture->targetViewCount]; + targetView->depth = info->depth; + targetView->layer = info->layer; + targetView->level = info->level; + targetView->view = (ID3D11View*) dsv; + + texture->targetViewCount += 1; + + return dsv; +} + static void D3D11_BeginRenderPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -2601,10 +2670,10 @@ static void D3D11_BeginRenderPass( /* Get the DSV for the depth stencil attachment, if applicable */ if (depthStencilAttachmentInfo != NULL) { - NOT_IMPLEMENTED - //d3d11CommandBuffer->dsView = D3D11_INTERNAL_FetchDSV( - // &depthStencilAttachmentInfo - //); + d3d11CommandBuffer->dsView = D3D11_INTERNAL_FetchDSV( + renderer, + depthStencilAttachmentInfo + ); } /* Actually set the RTs */ -- 2.25.1 From ac5aa0d40cf311896b77d14142dbfb48ef8280f6 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 16:37:08 -0600 Subject: [PATCH 54/69] Do some type shenanigans to allow depth textures to be sampled + fix viewport sizing logic --- src/Refresh_Driver_D3D11.c | 86 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 02b1c53..fbd4a65 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -612,6 +612,43 @@ static inline uint32_t D3D11_INTERNAL_NextHighestAlignment( return align * ((n + align - 1) / align); } +static DXGI_FORMAT D3D11_INTERNAL_GetTypelessFormat( + DXGI_FORMAT typedFormat +) { + switch (typedFormat) + { + case DXGI_FORMAT_D16_UNORM: + return DXGI_FORMAT_R16_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: + return DXGI_FORMAT_R32_TYPELESS; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return DXGI_FORMAT_R24G8_TYPELESS; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return DXGI_FORMAT_R32G8X24_TYPELESS; + default: + Refresh_LogError("Cannot get typeless DXGI format of format %d", typedFormat); + return 0; + } +} + +static DXGI_FORMAT D3D11_INTERNAL_GetSampleableFormat( + DXGI_FORMAT format +) { + switch (format) + { + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_R16_UNORM; + case DXGI_FORMAT_R32_TYPELESS: + return DXGI_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + case DXGI_FORMAT_R32G8X24_TYPELESS: + return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + default: + return format; + } +} + /* Quit */ static void D3D11_DestroyDevice( @@ -1442,6 +1479,10 @@ static Refresh_Texture* D3D11_CreateTexture( isCompute = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COMPUTE_BIT; format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; + if (isDepthStencil) + { + format = D3D11_INTERNAL_GetTypelessFormat(format); + } if (textureCreateInfo->depth <= 1) { @@ -1489,7 +1530,7 @@ static Refresh_Texture* D3D11_CreateTexture( if (isSampler) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; + srvDesc.Format = D3D11_INTERNAL_GetSampleableFormat(format); if (textureCreateInfo->isCube) { @@ -2573,7 +2614,7 @@ static ID3D11DepthStencilView* D3D11_INTERNAL_FetchDSV( D3D11Renderer* renderer, Refresh_DepthStencilAttachmentInfo* info ) { - D3D11Texture *texture = (D3D11Texture*)info->texture; + D3D11Texture *texture = (D3D11Texture*) info->texture; D3D11TargetView *targetView; D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; ID3D11DepthStencilView *dsv; @@ -2648,6 +2689,8 @@ static void D3D11_BeginRenderPass( D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; float clearColors[4]; D3D11_CLEAR_FLAG dsClearFlags; + uint32_t vpWidth = UINT_MAX; + uint32_t vpHeight = UINT_MAX; D3D11_VIEWPORT viewport; D3D11_RECT scissorRect; @@ -2726,11 +2769,46 @@ static void D3D11_BeginRenderPass( } } + /* The viewport cannot be larger than the smallest attachment. */ + for (uint32_t i = 0; i < colorAttachmentCount; i += 1) + { + D3D11Texture *texture = (D3D11Texture*) colorAttachmentInfos[i].texture; + uint32_t w = texture->width >> colorAttachmentInfos[i].level; + uint32_t h = texture->height >> colorAttachmentInfos[i].level; + + if (w < vpWidth) + { + vpWidth = w; + } + + if (h < vpHeight) + { + vpHeight = h; + } + } + + if (depthStencilAttachmentInfo != NULL) + { + D3D11Texture *texture = (D3D11Texture*) depthStencilAttachmentInfo->texture; + uint32_t w = texture->width >> depthStencilAttachmentInfo->level; + uint32_t h = texture->height >> depthStencilAttachmentInfo->level; + + if (w < vpWidth) + { + vpWidth = w; + } + + if (h < vpHeight) + { + vpHeight = h; + } + } + /* Set default viewport and scissor state */ viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->width; - viewport.Height = (float) ((D3D11Texture*) colorAttachmentInfos[0].texture)->height; + viewport.Width = (FLOAT) vpWidth; + viewport.Height = (FLOAT) vpHeight; viewport.MinDepth = 0; viewport.MaxDepth = 1; -- 2.25.1 From c121492e47a8b019ad7de4c7d69313d8def55755 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 16:39:55 -0600 Subject: [PATCH 55/69] Fix copy-paste error from last commit --- src/Refresh_Driver_D3D11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index fbd4a65..b359cde 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -640,7 +640,7 @@ static DXGI_FORMAT D3D11_INTERNAL_GetSampleableFormat( return DXGI_FORMAT_R16_UNORM; case DXGI_FORMAT_R32_TYPELESS: return DXGI_FORMAT_R32_FLOAT; - case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_R24G8_TYPELESS: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; case DXGI_FORMAT_R32G8X24_TYPELESS: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; -- 2.25.1 From e0dcaa222b03284c51c7ed9c482372a5a9617c2e Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 17:23:48 -0600 Subject: [PATCH 56/69] Two typos in the same malloc... + cube RT fixes --- src/Refresh_Driver_D3D11.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b359cde..9d9a90c 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1690,7 +1690,7 @@ static Refresh_Texture* D3D11_CreateTexture( { d3d11Texture->targetViewCapacity = d3d11Texture->isCube ? 6 : 1; d3d11Texture->targetViews = SDL_malloc( - sizeof(ID3D11RenderTargetView) * d3d11Texture->targetViewCount + sizeof(D3D11TargetView) * d3d11Texture->targetViewCapacity ); } else @@ -2564,8 +2564,8 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( if (texture->isCube) { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; /* FIXME: MSAA? */ - rtvDesc.Texture2DArray.ArraySize = 6; - rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = 1; + rtvDesc.Texture2DArray.FirstArraySlice = info->layer; rtvDesc.Texture2DArray.MipSlice = info->level; } else if (texture->depth > 1) @@ -2590,7 +2590,7 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( ERROR_CHECK_RETURN("Could not create RTV!", NULL); /* Create the D3D11TargetView to wrap our new RTV */ - if (texture->targetViewCount == texture->targetViewCapacity) + if (texture->targetViewCount >= texture->targetViewCapacity) { texture->targetViewCapacity *= 2; texture->targetViews = SDL_realloc( -- 2.25.1 From 25cec457b4a1834b1f646899cb5a1dbc1d941815 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 17:52:47 -0600 Subject: [PATCH 57/69] SetTextureDataYUV --- src/Refresh_Driver_D3D11.c | 46 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 9d9a90c..525b100 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1816,7 +1816,7 @@ static void D3D11_SetTextureData( data, BytesPerRow(w, d3d11Texture->format), BytesPerImage(w, h, d3d11Texture->format), - D3D11_COPY_DISCARD /* FIXME: Is this right? */ + 0 /* FIXME: Could DISCARD here if we know we're overwriting the whole image... */ ); } @@ -1838,7 +1838,49 @@ static void D3D11_SetTextureDataYUV( uint32_t yStride, uint32_t uvStride ) { - NOT_IMPLEMENTED + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Texture *yTex = (D3D11Texture*) y; + D3D11Texture *uTex = (D3D11Texture*) u; + D3D11Texture *vTex = (D3D11Texture*) v; + D3D11_BOX yBox = { 0, 0, 0, yWidth, yHeight, 1 }; + D3D11_BOX uvBox = { 0, 0, 0, uvWidth, uvHeight, 1 }; + + /* Y */ + ID3D11DeviceContext1_UpdateSubresource1( + d3d11CommandBuffer->context, + yTex->handle, + 0, + &yBox, + yDataPtr, + yStride, + 0, + D3D11_COPY_DISCARD + ); + + /* U */ + ID3D11DeviceContext1_UpdateSubresource1( + d3d11CommandBuffer->context, + uTex->handle, + 0, + &uvBox, + uDataPtr, + uvStride, + 0, + D3D11_COPY_DISCARD + ); + + /* V */ + ID3D11DeviceContext1_UpdateSubresource1( + d3d11CommandBuffer->context, + vTex->handle, + 0, + &uvBox, + vDataPtr, + uvStride, + 0, + D3D11_COPY_DISCARD + ); } static void D3D11_CopyTextureToTexture( -- 2.25.1 From 81351a1c1bda894fca7c2d0a53e189e4f8dbf309 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 23:56:36 -0600 Subject: [PATCH 58/69] MSAA for color and depth targets --- src/Refresh_Driver_D3D11.c | 174 ++++++++++++++++++++++++++----------- 1 file changed, 123 insertions(+), 51 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 525b100..693585f 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -368,6 +368,7 @@ typedef struct D3D11Texture /* D3D Handles */ ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ ID3D11ShaderResourceView *shaderView; + ID3D11Resource *msaaHandle; ID3D11UnorderedAccessView *unorderedAccessView; /* FIXME: This needs to be a dynamic array! */ D3D11TargetView *targetViews; @@ -460,6 +461,14 @@ typedef struct D3D11Fence ID3D11Query *handle; } D3D11Fence; +typedef struct D3D11TargetBinding +{ + D3D11Texture *texture; + uint32_t layer; +} D3D11TargetBinding; + +static const D3D11TargetBinding NullTargetBinding = { NULL, 0 }; + typedef struct D3D11CommandBuffer { /* D3D11 Object References */ @@ -467,8 +476,8 @@ typedef struct D3D11CommandBuffer D3D11SwapchainData *swapchainData; /* Render Pass */ - ID3D11RenderTargetView *rtViews[MAX_COLOR_TARGET_BINDINGS]; - ID3D11DepthStencilView *dsView; + D3D11TargetBinding colorTargets[MAX_COLOR_TARGET_BINDINGS]; + D3D11TargetBinding depthStencilTarget; D3D11GraphicsPipeline *graphicsPipeline; /* Compute Pass */ @@ -1465,9 +1474,10 @@ static Refresh_Texture* D3D11_CreateTexture( Refresh_TextureCreateInfo *textureCreateInfo ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - uint8_t isSampler, isCompute, isColorTarget, isDepthStencil; + uint8_t isColorTarget, isDepthStencil, isSampler, isCompute, isMultisample; DXGI_FORMAT format; ID3D11Resource *textureHandle; + ID3D11Resource *msaaHandle = NULL; ID3D11ShaderResourceView *srv = NULL; ID3D11UnorderedAccessView *uav = NULL; D3D11Texture *d3d11Texture; @@ -1477,6 +1487,7 @@ static Refresh_Texture* D3D11_CreateTexture( isDepthStencil = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT; isSampler = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT; isCompute = textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_COMPUTE_BIT; + isMultisample = textureCreateInfo->sampleCount > 1; format = RefreshToD3D11_TextureFormat[textureCreateInfo->format]; if (isDepthStencil) @@ -1488,9 +1499,6 @@ static Refresh_Texture* D3D11_CreateTexture( { D3D11_TEXTURE2D_DESC desc2D; - desc2D.Width = textureCreateInfo->width; - desc2D.Height = textureCreateInfo->height; - desc2D.BindFlags = 0; if (isSampler) { @@ -1509,12 +1517,14 @@ static Refresh_Texture* D3D11_CreateTexture( desc2D.BindFlags |= D3D11_BIND_DEPTH_STENCIL; } + desc2D.Width = textureCreateInfo->width; + desc2D.Height = textureCreateInfo->height; desc2D.ArraySize = textureCreateInfo->isCube ? 6 : 1; desc2D.CPUAccessFlags = 0; desc2D.Format = format; desc2D.MipLevels = textureCreateInfo->levelCount; desc2D.MiscFlags = textureCreateInfo->isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0; - desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; + desc2D.SampleDesc.Count = 1; desc2D.SampleDesc.Quality = 0; desc2D.Usage = D3D11_USAGE_DEFAULT; @@ -1584,15 +1594,42 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } + + /* Create the MSAA handle, if applicable */ + if (isMultisample) + { + desc2D.MiscFlags = 0; + desc2D.MipLevels = 1; + desc2D.ArraySize = 1; + desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; + desc2D.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN; + + res = ID3D11Device_CreateTexture2D( + renderer->device, + &desc2D, + NULL, + (ID3D11Texture2D**) &msaaHandle + ); + if (FAILED(res)) + { + ID3D11Resource_Release(textureHandle); + if (srv != NULL) + { + ID3D11ShaderResourceView_Release(srv); + } + if (uav != NULL) + { + ID3D11UnorderedAccessView_Release(uav); + } + D3D11_INTERNAL_LogError(renderer->device, "Could not create MSAA texture", res); + return NULL; + } + } } else { D3D11_TEXTURE3D_DESC desc3D; - desc3D.Width = textureCreateInfo->width; - desc3D.Height = textureCreateInfo->height; - desc3D.Depth = textureCreateInfo->depth; - desc3D.BindFlags = 0; if (isSampler) { @@ -1607,6 +1644,9 @@ static Refresh_Texture* D3D11_CreateTexture( desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET; } + desc3D.Width = textureCreateInfo->width; + desc3D.Height = textureCreateInfo->height; + desc3D.Depth = textureCreateInfo->depth; desc3D.CPUAccessFlags = 0; desc3D.Format = format; desc3D.MipLevels = textureCreateInfo->levelCount; @@ -1675,6 +1715,7 @@ static Refresh_Texture* D3D11_CreateTexture( d3d11Texture = (D3D11Texture*) SDL_malloc(sizeof(D3D11Texture)); d3d11Texture->handle = textureHandle; + d3d11Texture->msaaHandle = msaaHandle; d3d11Texture->format = textureCreateInfo->format; d3d11Texture->width = textureCreateInfo->width; d3d11Texture->height = textureCreateInfo->height; @@ -2339,6 +2380,10 @@ static void D3D11_QueueDestroyTexture( } SDL_free(d3d11Texture->targetViews); } + if (d3d11Texture->msaaHandle) + { + ID3D11Resource_Release(d3d11Texture->msaaHandle); + } ID3D11Resource_Release(d3d11Texture->handle); @@ -2563,12 +2608,12 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->vertexUniformBuffer = NULL; commandBuffer->fragmentUniformBuffer = NULL; commandBuffer->computeUniformBuffer = NULL; - commandBuffer->dsView = NULL; for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { - commandBuffer->rtViews[i] = NULL; + commandBuffer->colorTargets[i] = NullTargetBinding; } + commandBuffer->depthStencilTarget = NullTargetBinding; D3D11_INTERNAL_AcquireFence(renderer, commandBuffer); commandBuffer->autoReleaseFence = 1; @@ -2584,6 +2629,7 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( ) { D3D11Texture *texture = (D3D11Texture*) info->texture; D3D11TargetView *targetView; + uint8_t isMultisample = texture->msaaHandle != NULL; D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; ID3D11RenderTargetView *rtv; HRESULT res; @@ -2603,14 +2649,7 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( /* Let's create a new RTV! */ rtvDesc.Format = RefreshToD3D11_TextureFormat[texture->format]; - if (texture->isCube) - { - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; /* FIXME: MSAA? */ - rtvDesc.Texture2DArray.ArraySize = 1; - rtvDesc.Texture2DArray.FirstArraySlice = info->layer; - rtvDesc.Texture2DArray.MipSlice = info->level; - } - else if (texture->depth > 1) + if (texture->depth > 1) { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; rtvDesc.Texture3D.MipSlice = info->level; @@ -2619,13 +2658,20 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( } else { - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = info->level; + if (isMultisample) + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + } + else + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = info->level; + } } res = ID3D11Device_CreateRenderTargetView( renderer->device, - texture->handle, + isMultisample ? texture->msaaHandle : texture->handle, &rtvDesc, &rtv ); @@ -2658,6 +2704,7 @@ static ID3D11DepthStencilView* D3D11_INTERNAL_FetchDSV( ) { D3D11Texture *texture = (D3D11Texture*) info->texture; D3D11TargetView *targetView; + uint8_t isMultisample = texture->msaaHandle != NULL; D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; ID3D11DepthStencilView *dsv; HRESULT res; @@ -2678,12 +2725,9 @@ static ID3D11DepthStencilView* D3D11_INTERNAL_FetchDSV( /* Let's create a new DSV! */ dsvDesc.Format = RefreshToD3D11_TextureFormat[texture->format]; dsvDesc.Flags = 0; - if (texture->isCube) + if (isMultisample) { - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; /* FIXME: MSAA? */ - dsvDesc.Texture2DArray.ArraySize = 6; - dsvDesc.Texture2DArray.FirstArraySlice = 0; - dsvDesc.Texture2DArray.MipSlice = info->level; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; } else { @@ -2693,7 +2737,7 @@ static ID3D11DepthStencilView* D3D11_INTERNAL_FetchDSV( res = ID3D11Device_CreateDepthStencilView( renderer->device, - texture->handle, + isMultisample ? texture->msaaHandle : texture->handle, &dsvDesc, &dsv ); @@ -2729,24 +2773,27 @@ static void D3D11_BeginRenderPass( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - float clearColors[4]; - D3D11_CLEAR_FLAG dsClearFlags; + ID3D11RenderTargetView* rtvs[MAX_COLOR_TARGET_BINDINGS]; + ID3D11DepthStencilView *dsv = NULL; uint32_t vpWidth = UINT_MAX; uint32_t vpHeight = UINT_MAX; D3D11_VIEWPORT viewport; D3D11_RECT scissorRect; - /* Clear the bound RTs for the current command buffer */ + /* Clear the bound targets for the current command buffer */ for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { - d3d11CommandBuffer->rtViews[i] = NULL; + d3d11CommandBuffer->colorTargets[i] = NullTargetBinding; } - d3d11CommandBuffer->dsView = NULL; + d3d11CommandBuffer->depthStencilTarget = NullTargetBinding; - /* Get RTVs for the color attachments */ + /* Set up the new color target bindings */ for (uint32_t i = 0; i < colorAttachmentCount; i += 1) { - d3d11CommandBuffer->rtViews[i] = D3D11_INTERNAL_FetchRTV( + d3d11CommandBuffer->colorTargets[i].texture = (D3D11Texture*) colorAttachmentInfos[i].texture; + d3d11CommandBuffer->colorTargets[i].layer = colorAttachmentInfos[i].layer; + + rtvs[i] = D3D11_INTERNAL_FetchRTV( renderer, &colorAttachmentInfos[i] ); @@ -2755,7 +2802,10 @@ static void D3D11_BeginRenderPass( /* Get the DSV for the depth stencil attachment, if applicable */ if (depthStencilAttachmentInfo != NULL) { - d3d11CommandBuffer->dsView = D3D11_INTERNAL_FetchDSV( + d3d11CommandBuffer->depthStencilTarget.texture = (D3D11Texture*) depthStencilAttachmentInfo->texture; + d3d11CommandBuffer->depthStencilTarget.layer = depthStencilAttachmentInfo->layer; + + dsv = D3D11_INTERNAL_FetchDSV( renderer, depthStencilAttachmentInfo ); @@ -2765,8 +2815,8 @@ static void D3D11_BeginRenderPass( ID3D11DeviceContext_OMSetRenderTargets( d3d11CommandBuffer->context, colorAttachmentCount, - d3d11CommandBuffer->rtViews, - d3d11CommandBuffer->dsView + rtvs, + dsv ); /* Perform load ops on the RTs */ @@ -2774,22 +2824,24 @@ static void D3D11_BeginRenderPass( { if (colorAttachmentInfos[i].loadOp == REFRESH_LOADOP_CLEAR) { - clearColors[0] = colorAttachmentInfos[i].clearColor.x; - clearColors[1] = colorAttachmentInfos[i].clearColor.y; - clearColors[2] = colorAttachmentInfos[i].clearColor.z; - clearColors[3] = colorAttachmentInfos[i].clearColor.w; - + float clearColors[] = + { + colorAttachmentInfos[i].clearColor.x, + colorAttachmentInfos[i].clearColor.y, + colorAttachmentInfos[i].clearColor.z, + colorAttachmentInfos[i].clearColor.w + }; ID3D11DeviceContext_ClearRenderTargetView( d3d11CommandBuffer->context, - d3d11CommandBuffer->rtViews[i], + rtvs[i], clearColors ); } } - if (d3d11CommandBuffer->dsView != NULL) + if (depthStencilAttachmentInfo != NULL) { - dsClearFlags = 0; + D3D11_CLEAR_FLAG dsClearFlags = 0; if (depthStencilAttachmentInfo->loadOp == REFRESH_LOADOP_CLEAR) { dsClearFlags |= D3D11_CLEAR_DEPTH; @@ -2803,7 +2855,7 @@ static void D3D11_BeginRenderPass( { ID3D11DeviceContext_ClearDepthStencilView( d3d11CommandBuffer->context, - d3d11CommandBuffer->dsView, + dsv, dsClearFlags, depthStencilAttachmentInfo->depthStencilClearValue.depth, (uint8_t) depthStencilAttachmentInfo->depthStencilClearValue.stencil @@ -2882,8 +2934,28 @@ static void D3D11_EndRenderPass( d3d11CommandBuffer->fragmentUniformBuffer = NULL; d3d11CommandBuffer->computeUniformBuffer = NULL; - /* FIXME: Resolve MSAA here! */ - /* FIXME: Anything else we need to do...? */ + /* Resolve MSAA color render targets */ + for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) + { + D3D11Texture *texture = d3d11CommandBuffer->colorTargets[i].texture; + if (texture != NULL && texture->msaaHandle != NULL) + { + uint32_t subresource = D3D11_INTERNAL_CalcSubresource( + 0, /* FIXME: Is this right? */ + d3d11CommandBuffer->colorTargets[i].layer, + texture->levelCount + ); + + ID3D11DeviceContext_ResolveSubresource( + d3d11CommandBuffer->context, + texture->handle, + subresource, + texture->msaaHandle, + 0, + RefreshToD3D11_TextureFormat[texture->format] + ); + } + } } static void D3D11_BindGraphicsPipeline( -- 2.25.1 From 01a36b940b59ed80011a5c0a26e7a7d213c4a3d6 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 00:19:11 -0600 Subject: [PATCH 59/69] Fix non-MSAA cube RTs --- src/Refresh_Driver_D3D11.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 693585f..218d00b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2649,7 +2649,14 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( /* Let's create a new RTV! */ rtvDesc.Format = RefreshToD3D11_TextureFormat[texture->format]; - if (texture->depth > 1) + if (texture->isCube && !isMultisample) + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.FirstArraySlice = info->layer; + rtvDesc.Texture2DArray.ArraySize = 1; + rtvDesc.Texture2DArray.MipSlice = info->level; + } + else if (texture->depth > 1) { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; rtvDesc.Texture3D.MipSlice = info->level; -- 2.25.1 From 91b389f351e608d01ac9f4679b04cd46201976a5 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 17:07:56 -0600 Subject: [PATCH 60/69] SetSwapchainPresentMode + other swapchain-y features from FNA3D D3D11 --- src/Refresh_Driver_D3D11.c | 103 +++++++++++++++++++++++----- src/Refresh_Driver_D3D11_cdefines.h | 2 + 2 files changed, 87 insertions(+), 18 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 218d00b..b413f41 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -389,12 +389,13 @@ typedef struct D3D11SwapchainData { IDXGISwapChain *swapchain; D3D11Texture texture; + Refresh_PresentMode presentMode; } D3D11SwapchainData; +/* FIXME: Why do we have WindowData separate from SwapchainData? */ typedef struct D3D11WindowData { void* windowHandle; - uint8_t allowTearing; D3D11SwapchainData *swapchainData; } D3D11WindowData; @@ -517,7 +518,8 @@ typedef struct D3D11Renderer void *d3dcompiler_dll; uint8_t debugMode; - D3D_FEATURE_LEVEL featureLevel; /* FIXME: Do we need this? */ + BOOL supportsTearing; + PFN_D3DCOMPILE D3DCompileFunc; D3D11WindowData **claimedWindows; @@ -3296,12 +3298,14 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( static uint8_t D3D11_INTERNAL_CreateSwapchain( D3D11Renderer *renderer, - D3D11WindowData *windowData + D3D11WindowData *windowData, + Refresh_PresentMode presentMode ) { SDL_SysWMinfo info; HWND dxgiHandle; int width, height; DXGI_SWAP_CHAIN_DESC swapchainDesc; + IDXGIFactory4 *factory4; IDXGIFactory1 *pParent; IDXGISwapChain *swapchain; D3D11SwapchainData *swapchainData; @@ -3328,11 +3332,35 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( swapchainDesc.SampleDesc.Count = 1; swapchainDesc.SampleDesc.Quality = 0; swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapchainDesc.BufferCount = 3; + swapchainDesc.BufferCount = 2; swapchainDesc.OutputWindow = dxgiHandle; swapchainDesc.Windowed = 1; - swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - swapchainDesc.Flags = 0; + + if (renderer->supportsTearing) + { + swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + } + else + { + 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! */ res = IDXGIFactory1_CreateSwapChain( @@ -3341,7 +3369,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( &swapchainDesc, &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 @@ -3385,6 +3413,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( /* Create the swapchain data */ swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData)); swapchainData->swapchain = swapchain; + swapchainData->presentMode = presentMode; if (!D3D11_INTERNAL_InitializeSwapchainTexture( renderer, @@ -3415,11 +3444,11 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( /* Resize the swapchain */ res = IDXGISwapChain_ResizeBuffers( swapchainData->swapchain, - 0, /* Keep buffer count the same */ + 0, /* Keep buffer count the same */ width, height, - DXGI_FORMAT_UNKNOWN, /* Keep the old format */ - 0 + DXGI_FORMAT_UNKNOWN, /* Keep the old format */ + renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 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->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); @@ -3604,7 +3632,9 @@ static void D3D11_SetSwapchainPresentMode( void *windowHandle, Refresh_PresentMode presentMode ) { - NOT_IMPLEMENTED + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle); + D3D11SwapchainData *swapchainData = windowData->swapchainData; + swapchainData->presentMode = presentMode; } /* Submission and Fences */ @@ -3737,7 +3767,7 @@ static void D3D11_Submit( ID3D11CommandList_Release(commandList); /* Mark the command buffer as submitted */ - if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) + if (renderer->submittedCommandBufferCount >= renderer->submittedCommandBufferCapacity) { renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1; @@ -3753,10 +3783,24 @@ static void D3D11_Submit( /* Present, if applicable */ 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( d3d11CommandBuffer->swapchainData->swapchain, - 1, /* FIXME: Assumes vsync! */ - 0 + syncInterval, + presentFlags ); } @@ -4040,6 +4084,7 @@ static Refresh_Device* D3D11_CreateDevice( PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 }; + IDXGIFactory5 *factory5; IDXGIFactory6 *factory6; uint32_t flags; DXGI_ADAPTER_DESC1 adapterDesc; @@ -4094,7 +4139,28 @@ static Refresh_Device* D3D11_CreateDevice( ); 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( renderer->factory, &D3D_IID_IDXGIFactory6, @@ -4109,6 +4175,7 @@ static Refresh_Device* D3D11_CreateDevice( &D3D_IID_IDXGIAdapter1, &renderer->adapter ); + IDXGIFactory6_Release(factory6); } else { @@ -4166,7 +4233,7 @@ tryCreateDevice: SDL_arraysize(levels), D3D11_SDK_VERSION, &d3d11Device, - &renderer->featureLevel, + NULL, &renderer->immediateContext ); if (FAILED(res) && debugMode) diff --git a/src/Refresh_Driver_D3D11_cdefines.h b/src/Refresh_Driver_D3D11_cdefines.h index da87aef..3caa2e6 100644 --- a/src/Refresh_Driver_D3D11_cdefines.h +++ b/src/Refresh_Driver_D3D11_cdefines.h @@ -30,6 +30,8 @@ typedef HRESULT(WINAPI* PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID* riid, void** p /* 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_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_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} }; -- 2.25.1 From 54ffdc180d68f3065ac683751e3e0c2db556aec3 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 18:00:12 -0600 Subject: [PATCH 61/69] PresentMode fixes --- src/Refresh_Driver_D3D11.c | 50 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b413f41..5c1caea 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -519,6 +519,7 @@ typedef struct D3D11Renderer uint8_t debugMode; BOOL supportsTearing; + uint8_t supportsFlipDiscard; PFN_D3DCOMPILE D3DCompileFunc; @@ -3305,7 +3306,6 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( HWND dxgiHandle; int width, height; DXGI_SWAP_CHAIN_DESC swapchainDesc; - IDXGIFactory4 *factory4; IDXGIFactory1 *pParent; IDXGISwapChain *swapchain; D3D11SwapchainData *swapchainData; @@ -3339,27 +3339,17 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( if (renderer->supportsTearing) { swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + /* We know this is supported because tearing support implies DXGI 1.5+ */ swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; } else { swapchainDesc.Flags = 0; - - /* For Windows 10+, use a better form of discard swap behavior */ - res = IDXGIFactory1_QueryInterface( - renderer->factory, - &D3D_IID_IDXGIFactory4, - &factory4 + swapchainDesc.SwapEffect = ( + renderer->supportsFlipDiscard ? + DXGI_SWAP_EFFECT_FLIP_DISCARD : + DXGI_SWAP_EFFECT_DISCARD ); - if (SUCCEEDED(res)) - { - swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - IDXGIFactory4_Release(factory4); - } - else - { - swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - } } /* Create the swapchain! */ @@ -3369,7 +3359,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( &swapchainDesc, &swapchain ); - ERROR_CHECK("Could not create swapchain", 0); + ERROR_CHECK_RETURN("Could not create swapchain", 0); /* * The swapchain's parent is a separate factory from the factory that @@ -3783,17 +3773,18 @@ static void D3D11_Submit( /* Present, if applicable */ if (d3d11CommandBuffer->swapchainData) { + /* FIXME: Is there some way to emulate FIFO_RELAXED? */ + uint32_t syncInterval = 1; - if (d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE) - { + if ( d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE || + (renderer->supportsFlipDiscard && d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_MAILBOX) + ) { syncInterval = 0; } uint32_t presentFlags = 0; - if ( renderer->supportsTearing && - (d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE || - d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_FIFO_RELAXED) - ) { + if (renderer->supportsTearing && d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE) + { presentFlags = DXGI_PRESENT_ALLOW_TEARING; } @@ -4084,6 +4075,7 @@ static Refresh_Device* D3D11_CreateDevice( PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 }; + IDXGIFactory4 *factory4; IDXGIFactory5 *factory5; IDXGIFactory6 *factory6; uint32_t flags; @@ -4139,6 +4131,18 @@ static Refresh_Device* D3D11_CreateDevice( ); ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL); + /* Check for flip-model discard support (supported on Windows 10+) */ + res = IDXGIFactory1_QueryInterface( + renderer->factory, + &D3D_IID_IDXGIFactory4, + &factory4 + ); + if (SUCCEEDED(res)) + { + renderer->supportsFlipDiscard = 1; + IDXGIFactory4_Release(factory4); + } + /* Check for explicit tearing support */ res = IDXGIFactory1_QueryInterface( renderer->factory, -- 2.25.1 From 506c2e48194bf7cb067273ba5adc752c35f40dc5 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 21:49:19 -0600 Subject: [PATCH 62/69] FIXME fixups, mostly for contextLock --- src/Refresh_Driver_D3D11.c | 43 +++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 5c1caea..b6e2b01 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -484,8 +484,7 @@ typedef struct D3D11CommandBuffer /* Compute Pass */ D3D11ComputePipeline *computePipeline; - /* State */ - SDL_threadID threadID; + /* Fences */ D3D11Fence *fence; uint8_t autoReleaseFence; @@ -686,6 +685,7 @@ static void D3D11_DestroyDevice( { D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i]; ID3D11DeviceContext_Release(commandBuffer->context); + SDL_free(commandBuffer->boundUniformBuffers); SDL_free(commandBuffer); } SDL_free(renderer->availableCommandBuffers); @@ -2003,6 +2003,7 @@ static void D3D11_GetBufferData( ERROR_CHECK_RETURN("Could not create staging buffer for readback", ); /* Copy data into staging buffer */ + SDL_LockMutex(renderer->contextLock); ID3D11DeviceContext_CopySubresourceRegion( renderer->immediateContext, stagingBuffer, @@ -2032,6 +2033,7 @@ static void D3D11_GetBufferData( res ); ID3D11Buffer_Release(stagingBuffer); + SDL_UnlockMutex(renderer->contextLock); return; } @@ -2042,6 +2044,7 @@ static void D3D11_GetBufferData( stagingBuffer, 0 ); + SDL_UnlockMutex(renderer->contextLock); /* Clean up the staging buffer */ ID3D11Resource_Release(stagingBuffer); @@ -2603,15 +2606,12 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( SDL_LockMutex(renderer->acquireCommandBufferLock); commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer); - - commandBuffer->threadID = SDL_ThreadID(); commandBuffer->swapchainData = NULL; commandBuffer->graphicsPipeline = NULL; commandBuffer->computePipeline = NULL; commandBuffer->vertexUniformBuffer = NULL; commandBuffer->fragmentUniformBuffer = NULL; commandBuffer->computeUniformBuffer = NULL; - for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { commandBuffer->colorTargets[i] = NullTargetBinding; @@ -3182,7 +3182,7 @@ static void D3D11_BindComputeBuffers( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - ID3D11UnorderedAccessView* uavs[MAX_BUFFER_BINDINGS]; /* FIXME: Is this limit right? */ + ID3D11UnorderedAccessView* uavs[MAX_BUFFER_BINDINGS]; int32_t numBuffers = d3d11CommandBuffer->computePipeline->numBuffers; @@ -3207,7 +3207,7 @@ static void D3D11_BindComputeTextures( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - ID3D11UnorderedAccessView *uavs[MAX_TEXTURE_SAMPLERS]; /* FIXME: Is this limit right? */ + ID3D11UnorderedAccessView *uavs[MAX_TEXTURE_SAMPLERS]; int32_t numTextures = d3d11CommandBuffer->computePipeline->numTextures; @@ -3709,16 +3709,23 @@ static void D3D11_INTERNAL_WaitForFence( D3D11Fence *fence ) { BOOL queryData; + HRESULT res; - while (S_OK != ID3D11DeviceContext_GetData( + SDL_LockMutex(renderer->contextLock); + + res = ID3D11DeviceContext_GetData( renderer->immediateContext, (ID3D11Asynchronous*) fence->handle, &queryData, sizeof(queryData), 0 - )) { + ); + while (res != S_OK) + { /* Spin until we get a result back... */ } + + SDL_UnlockMutex(renderer->contextLock); } static void D3D11_Submit( @@ -3730,8 +3737,6 @@ static void D3D11_Submit( ID3D11CommandList *commandList; HRESULT res; - /* FIXME: Should add sanity check that current thread ID matches the command buffer's threadID. */ - SDL_LockMutex(renderer->contextLock); /* Notify the command buffer completion query that we have completed recording */ @@ -3799,7 +3804,6 @@ static void D3D11_Submit( for (int32_t i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) { BOOL queryData; - res = ID3D11DeviceContext_GetData( renderer->immediateContext, (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->fence->handle, @@ -3850,7 +3854,7 @@ static void D3D11_Wait( ); } - SDL_LockMutex(renderer->contextLock); + SDL_LockMutex(renderer->contextLock); /* This effectively acts as a lock around submittedCommandBuffers */ for (int32_t i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) { @@ -3882,6 +3886,8 @@ static void D3D11_WaitForFences( } else { + SDL_LockMutex(renderer->contextLock); + while (res != S_OK) { for (uint32_t i = 0; i < fenceCount; i += 1) @@ -3900,6 +3906,8 @@ static void D3D11_WaitForFences( } } } + + SDL_UnlockMutex(renderer->contextLock); } } @@ -3910,8 +3918,11 @@ static int D3D11_QueryFence( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11Fence *d3d11Fence = (D3D11Fence*) fence; BOOL queryData; + HRESULT res; - HRESULT res = ID3D11DeviceContext_GetData( + SDL_LockMutex(renderer->contextLock); + + res = ID3D11DeviceContext_GetData( renderer->immediateContext, (ID3D11Asynchronous*) d3d11Fence->handle, &queryData, @@ -3919,6 +3930,8 @@ static int D3D11_QueryFence( 0 ); + SDL_UnlockMutex(renderer->contextLock); + return res == S_OK; } @@ -4289,7 +4302,7 @@ tryCreateDevice: Refresh_LogInfo("D3D11 Adapter: %S", adapterDesc.Description); /* Create mutexes */ - renderer->contextLock = SDL_CreateMutex(); /* FIXME: We should be using this *everywhere* the immediate context is accessed! */ + renderer->contextLock = SDL_CreateMutex(); renderer->acquireCommandBufferLock = SDL_CreateMutex(); renderer->uniformBufferLock = SDL_CreateMutex(); renderer->fenceLock = SDL_CreateMutex(); -- 2.25.1 From e81926712e2f8ccbd1b620e0c5964d6e4bec576c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 22:18:25 -0600 Subject: [PATCH 63/69] Combine swapchain and window data structs + actually allocate claimedWindows... --- src/Refresh_Driver_D3D11.c | 150 +++++++++++++++---------------------- 1 file changed, 59 insertions(+), 91 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b6e2b01..3fd6511 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -385,18 +385,12 @@ typedef struct D3D11Texture uint8_t isRenderTarget; } D3D11Texture; -typedef struct D3D11SwapchainData -{ - IDXGISwapChain *swapchain; - D3D11Texture texture; - Refresh_PresentMode presentMode; -} D3D11SwapchainData; - -/* FIXME: Why do we have WindowData separate from SwapchainData? */ typedef struct D3D11WindowData { void* windowHandle; - D3D11SwapchainData *swapchainData; + IDXGISwapChain *swapchain; + D3D11Texture texture; + Refresh_PresentMode presentMode; } D3D11WindowData; typedef struct D3D11ShaderModule @@ -472,9 +466,11 @@ static const D3D11TargetBinding NullTargetBinding = { NULL, 0 }; typedef struct D3D11CommandBuffer { - /* D3D11 Object References */ + /* Deferred Context */ ID3D11DeviceContext1 *context; - D3D11SwapchainData *swapchainData; + + /* Window */ + D3D11WindowData *windowData; /* Render Pass */ D3D11TargetBinding colorTargets[MAX_COLOR_TARGET_BINDINGS]; @@ -546,6 +542,7 @@ typedef struct D3D11Renderer SDL_mutex *acquireCommandBufferLock; SDL_mutex *uniformBufferLock; SDL_mutex *fenceLock; + SDL_mutex *windowLock; } D3D11Renderer; /* Logging */ @@ -677,9 +674,6 @@ static void D3D11_DestroyDevice( } SDL_free(renderer->claimedWindows); - /* FIXME: Copied this from Vulkan, is it actually necessary? */ - D3D11_Wait(device->driverData); - /* Release command buffer infrastructure */ for (uint32_t i = 0; i < renderer->availableCommandBufferCount; i += 1) { @@ -715,6 +709,7 @@ static void D3D11_DestroyDevice( SDL_DestroyMutex(renderer->contextLock); SDL_DestroyMutex(renderer->uniformBufferLock); SDL_DestroyMutex(renderer->fenceLock); + SDL_DestroyMutex(renderer->windowLock); /* Release the device and associated objects */ ID3D11DeviceContext_Release(renderer->immediateContext); @@ -2606,7 +2601,7 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( SDL_LockMutex(renderer->acquireCommandBufferLock); commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer); - commandBuffer->swapchainData = NULL; + commandBuffer->windowData = NULL; commandBuffer->graphicsPipeline = NULL; commandBuffer->computePipeline = NULL; commandBuffer->vertexUniformBuffer = NULL; @@ -2951,7 +2946,7 @@ static void D3D11_EndRenderPass( if (texture != NULL && texture->msaaHandle != NULL) { uint32_t subresource = D3D11_INTERNAL_CalcSubresource( - 0, /* FIXME: Is this right? */ + 0, /* FIXME: This should probably the color target's mip level */ d3d11CommandBuffer->colorTargets[i].layer, texture->levelCount ); @@ -3308,7 +3303,6 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( DXGI_SWAP_CHAIN_DESC swapchainDesc; IDXGIFactory1 *pParent; IDXGISwapChain *swapchain; - D3D11SwapchainData *swapchainData; HRESULT res; /* Get the DXGI handle */ @@ -3400,40 +3394,35 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( IDXGIFactory1_Release(pParent); } - /* Create the swapchain data */ - swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData)); - swapchainData->swapchain = swapchain; - swapchainData->presentMode = presentMode; + /* Initialize the swapchain data */ + windowData->swapchain = swapchain; + windowData->presentMode = presentMode; if (!D3D11_INTERNAL_InitializeSwapchainTexture( renderer, swapchain, - &swapchainData->texture + &windowData->texture )) { - SDL_free(swapchainData); IDXGISwapChain_Release(swapchain); return 0; } - windowData->swapchainData = swapchainData; return 1; } static uint8_t D3D11_INTERNAL_ResizeSwapchain( D3D11Renderer *renderer, - D3D11SwapchainData *swapchainData, + D3D11WindowData *windowData, int32_t width, int32_t height ) { - HRESULT res; - /* Release the old RTV */ - ID3D11RenderTargetView_Release(swapchainData->texture.targetViews[0].view); - SDL_free(swapchainData->texture.targetViews); + ID3D11RenderTargetView_Release(windowData->texture.targetViews[0].view); + SDL_free(windowData->texture.targetViews); /* Resize the swapchain */ - res = IDXGISwapChain_ResizeBuffers( - swapchainData->swapchain, + HRESULT res = IDXGISwapChain_ResizeBuffers( + windowData->swapchain, 0, /* Keep buffer count the same */ width, height, @@ -3445,38 +3434,11 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( /* Create the Refresh-side texture for the swapchain */ return D3D11_INTERNAL_InitializeSwapchainTexture( renderer, - swapchainData->swapchain, - &swapchainData->texture + windowData->swapchain, + &windowData->texture ); } -static void D3D11_INTERNAL_DestroySwapchain( - D3D11Renderer *renderer, - D3D11WindowData *windowData -) { - D3D11SwapchainData *swapchainData; - - if (windowData == NULL) - { - return; - } - - swapchainData = windowData->swapchainData; - - if (swapchainData == NULL) - { - return; - } - - ID3D11RenderTargetView_Release(swapchainData->texture.targetViews[0].view); - SDL_free(swapchainData->texture.targetViews); - - IDXGISwapChain_Release(swapchainData->swapchain); - - windowData->swapchainData = NULL; - SDL_free(swapchainData); -} - static uint8_t D3D11_ClaimWindow( Refresh_Renderer *driverData, void *windowHandle, @@ -3494,6 +3456,8 @@ static uint8_t D3D11_ClaimWindow( { SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_DATA, windowData); + SDL_LockMutex(renderer->windowLock); + if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) { renderer->claimedWindowCapacity *= 2; @@ -3502,10 +3466,11 @@ static uint8_t D3D11_ClaimWindow( renderer->claimedWindowCapacity * sizeof(D3D11WindowData*) ); } - renderer->claimedWindows[renderer->claimedWindowCount] = windowData; renderer->claimedWindowCount += 1; + SDL_UnlockMutex(renderer->windowLock); + return 1; } else @@ -3534,15 +3499,13 @@ static void D3D11_UnclaimWindow( return; } - if (windowData->swapchainData != NULL) - { - D3D11_Wait(driverData); - D3D11_INTERNAL_DestroySwapchain( - (D3D11Renderer*) driverData, - windowData - ); - } + D3D11_Wait(driverData); + ID3D11RenderTargetView_Release(windowData->texture.targetViews[0].view); + SDL_free(windowData->texture.targetViews); + IDXGISwapChain_Release(windowData->swapchain); + + SDL_LockMutex(renderer->windowLock); for (uint32_t i = 0; i < renderer->claimedWindowCount; i += 1) { if (renderer->claimedWindows[i]->windowHandle == windowHandle) @@ -3552,6 +3515,7 @@ static void D3D11_UnclaimWindow( break; } } + SDL_UnlockMutex(renderer->windowLock); SDL_free(windowData); SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_DATA, NULL); @@ -3567,7 +3531,6 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11WindowData *windowData; - D3D11SwapchainData *swapchainData; DXGI_SWAP_CHAIN_DESC swapchainDesc; int w, h; HRESULT res; @@ -3578,21 +3541,15 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( return NULL; } - swapchainData = windowData->swapchainData; - if (swapchainData == NULL) - { - return NULL; - } - /* Check for window size changes and resize the swapchain if needed. */ - IDXGISwapChain_GetDesc(swapchainData->swapchain, &swapchainDesc); + IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc); SDL_GetWindowSize((SDL_Window*) windowHandle, &w, &h); if (w != swapchainDesc.BufferDesc.Width || h != swapchainDesc.BufferDesc.Height) { res = D3D11_INTERNAL_ResizeSwapchain( renderer, - swapchainData, + windowData, w, h ); @@ -3600,14 +3557,14 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( } /* Let the command buffer know it's associated with this swapchain. */ - d3d11CommandBuffer->swapchainData = swapchainData; + d3d11CommandBuffer->windowData = windowData; /* Send the dimensions to the out parameters. */ - *pWidth = swapchainData->texture.width; - *pHeight = swapchainData->texture.height; + *pWidth = windowData->texture.width; + *pHeight = windowData->texture.height; /* Return the swapchain texture */ - return (Refresh_Texture*) &swapchainData->texture; + return (Refresh_Texture*) &windowData->texture; } static Refresh_TextureFormat D3D11_GetSwapchainFormat( @@ -3623,8 +3580,7 @@ static void D3D11_SetSwapchainPresentMode( Refresh_PresentMode presentMode ) { D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle); - D3D11SwapchainData *swapchainData = windowData->swapchainData; - swapchainData->presentMode = presentMode; + windowData->presentMode = presentMode; } /* Submission and Fences */ @@ -3776,25 +3732,26 @@ static void D3D11_Submit( renderer->submittedCommandBufferCount += 1; /* Present, if applicable */ - if (d3d11CommandBuffer->swapchainData) + if (d3d11CommandBuffer->windowData) { /* FIXME: Is there some way to emulate FIFO_RELAXED? */ uint32_t syncInterval = 1; - if ( d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE || - (renderer->supportsFlipDiscard && d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_MAILBOX) + if ( d3d11CommandBuffer->windowData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE || + (renderer->supportsFlipDiscard && d3d11CommandBuffer->windowData->presentMode == REFRESH_PRESENTMODE_MAILBOX) ) { syncInterval = 0; } uint32_t presentFlags = 0; - if (renderer->supportsTearing && d3d11CommandBuffer->swapchainData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE) + if ( renderer->supportsTearing && + d3d11CommandBuffer->windowData->presentMode == REFRESH_PRESENTMODE_IMMEDIATE ) { presentFlags = DXGI_PRESENT_ALLOW_TEARING; } IDXGISwapChain_Present( - d3d11CommandBuffer->swapchainData->swapchain, + d3d11CommandBuffer->windowData->swapchain, syncInterval, presentFlags ); @@ -4306,6 +4263,7 @@ tryCreateDevice: renderer->acquireCommandBufferLock = SDL_CreateMutex(); renderer->uniformBufferLock = SDL_CreateMutex(); renderer->fenceLock = SDL_CreateMutex(); + renderer->windowLock = SDL_CreateMutex(); /* Initialize miscellaneous renderer members */ renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); @@ -4315,11 +4273,21 @@ tryCreateDevice: /* Create uniform buffer pool */ renderer->availableUniformBufferCapacity = 2; - renderer->availableUniformBuffers = SDL_malloc(sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity); + renderer->availableUniformBuffers = SDL_malloc( + sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity + ); /* Create fence pool */ renderer->availableFenceCapacity = 2; - renderer->availableFences = SDL_malloc(sizeof(D3D11Fence*) * renderer->availableFenceCapacity); + renderer->availableFences = SDL_malloc( + sizeof(D3D11Fence*) * renderer->availableFenceCapacity + ); + + /* Create claimed window list */ + renderer->claimedWindowCapacity = 1; + renderer->claimedWindows = SDL_malloc( + sizeof(D3D11WindowData*) * renderer->claimedWindowCapacity + ); /* Create the Refresh Device */ result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); -- 2.25.1 From 617ce4edf8c16c5f83181e0f00b92d047975e5ef Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 22:21:01 -0600 Subject: [PATCH 64/69] Note which FIXME's require a Refresh API update --- src/Refresh_Driver_D3D11.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 3fd6511..3bc697c 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -369,7 +369,7 @@ typedef struct D3D11Texture ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ ID3D11ShaderResourceView *shaderView; ID3D11Resource *msaaHandle; - ID3D11UnorderedAccessView *unorderedAccessView; /* FIXME: This needs to be a dynamic array! */ + ID3D11UnorderedAccessView *unorderedAccessView; /* API FIXME: This needs to be a dynamic array! */ D3D11TargetView *targetViews; uint32_t targetViewCount; @@ -1034,7 +1034,7 @@ static ID3D11DepthStencilState* D3D11_INTERNAL_FetchDepthStencilState( dsDesc.FrontFace.StencilFailOp = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.failOp]; dsDesc.FrontFace.StencilPassOp = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.passOp]; - /* FIXME: D3D11 doesn't have separate read/write masks for each stencil side. What should we do? */ + /* API FIXME: D3D11 doesn't have separate read/write masks for each stencil side. What should we do? */ dsDesc.StencilReadMask = depthStencilState.frontStencilState.compareMask; dsDesc.StencilWriteMask = depthStencilState.frontStencilState.writeMask; @@ -1277,7 +1277,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( pipeline->depthStencilAttachmentFormat = RefreshToD3D11_TextureFormat[ pipelineCreateInfo->attachmentInfo.depthStencilFormat ]; - /* FIXME: D3D11 doesn't have separate references for each stencil side. What should we do? */ + /* API FIXME: D3D11 doesn't have separate references for each stencil side. What should we do? */ pipeline->stencilRef = pipelineCreateInfo->depthStencilState.frontStencilState.reference; /* Rasterizer */ @@ -2282,7 +2282,8 @@ static uint32_t D3D11_PushComputeShaderUniforms( dataLengthInBytes ); - d3d11CommandBuffer->computeUniformBuffer->offset += (uint32_t) computePipeline->computeUniformBlockSize; /* FIXME: Is this cast safe? */ + d3d11CommandBuffer->computeUniformBuffer->offset += + (uint32_t) computePipeline->computeUniformBlockSize; /* API FIXME: Is this cast safe? */ return offset; } -- 2.25.1 From 74bd056adf45cffe500da665400e29e6e5c99405 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 23:00:55 -0600 Subject: [PATCH 65/69] Fix a few more FIXME's --- src/Refresh_Driver_D3D11.c | 158 +++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 75 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 3bc697c..95ff71b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1038,11 +1038,10 @@ static ID3D11DepthStencilState* D3D11_INTERNAL_FetchDepthStencilState( dsDesc.StencilReadMask = depthStencilState.frontStencilState.compareMask; dsDesc.StencilWriteMask = depthStencilState.frontStencilState.writeMask; - /* FIXME: What do we do with these? - * depthStencilState.depthBoundsTestEnable - * depthStencilState.maxDepthBounds - * depthStencilState.minDepthBounds - */ + if (depthStencilState.depthBoundsTestEnable) + { + Refresh_LogWarn("D3D11 does not support Depth Bounds tests!"); + } res = ID3D11Device_CreateDepthStencilState( renderer->device, @@ -1067,9 +1066,9 @@ static ID3D11RasterizerState* D3D11_INTERNAL_FetchRasterizerState( */ rasterizerDesc.AntialiasedLineEnable = FALSE; rasterizerDesc.CullMode = RefreshToD3D11_CullMode[rasterizerState.cullMode]; - rasterizerDesc.DepthBias = (INT) rasterizerState.depthBiasConstantFactor; /* FIXME: Is this cast correct? */ + rasterizerDesc.DepthBias = (INT) rasterizerState.depthBiasConstantFactor; rasterizerDesc.DepthBiasClamp = rasterizerState.depthBiasClamp; - rasterizerDesc.DepthClipEnable = TRUE; /* FIXME: Do we want this...? */ + rasterizerDesc.DepthClipEnable = TRUE; rasterizerDesc.FillMode = (rasterizerState.fillMode == REFRESH_FILLMODE_FILL) ? D3D11_FILL_SOLID : D3D11_FILL_WIREFRAME; rasterizerDesc.FrontCounterClockwise = (rasterizerState.frontFace == REFRESH_FRONTFACE_COUNTER_CLOCKWISE); rasterizerDesc.MultisampleEnable = TRUE; /* only applies to MSAA render targets */ @@ -1183,14 +1182,12 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( Refresh_ComputeShaderInfo *computeShaderInfo ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11ComputePipeline* pipeline = (D3D11ComputePipeline*) SDL_malloc(sizeof(D3D11ComputePipeline)); - D3D11ShaderModule* shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule; + D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule; ID3D10Blob *errorBlob; + D3D11ComputePipeline *pipeline; HRESULT res; - pipeline->numTextures = computeShaderInfo->imageBindingCount; - pipeline->numBuffers = computeShaderInfo->bufferBindingCount; - + /* First, compile the shader since we didn't do that when creating the shader module */ if (shaderModule->shader == NULL) { res = renderer->D3DCompileFunc( @@ -1199,7 +1196,7 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( NULL, NULL, NULL, - "main", /* FIXME: Is this correct or should this be computeShaderInfo.entryPoint? */ + "main", "cs_5_0", 0, 0, @@ -1219,8 +1216,13 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( NULL, (ID3D11ComputeShader**) &shaderModule->shader ); - ERROR_CHECK_RETURN("Could not create compute shader", NULL); /* FIXME: This leaks the pipeline! */ + ERROR_CHECK_RETURN("Could not create compute shader", NULL); } + + /* Allocate and set up the pipeline */ + pipeline = SDL_malloc(sizeof(D3D11ComputePipeline)); + pipeline->numTextures = computeShaderInfo->imageBindingCount; + pipeline->numBuffers = computeShaderInfo->bufferBindingCount; pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; pipeline->computeUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( (uint32_t) computeShaderInfo->uniformBufferSize, @@ -1235,12 +1237,78 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( Refresh_GraphicsPipelineCreateInfo *pipelineCreateInfo ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline*) SDL_malloc(sizeof(D3D11GraphicsPipeline)); D3D11ShaderModule *vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule; D3D11ShaderModule *fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule; ID3D10Blob *errorBlob; + D3D11GraphicsPipeline *pipeline; HRESULT res; + /* First, compile the shaders since we didn't do that when creating the shader modules */ + if (vertShaderModule->shader == NULL) + { + res = renderer->D3DCompileFunc( + vertShaderModule->shaderSource, + vertShaderModule->shaderSourceLength, + NULL, + NULL, + NULL, + "main", + "vs_5_0", + 0, + 0, + &vertShaderModule->blob, + &errorBlob + ); + if (FAILED(res)) + { + Refresh_LogError("Vertex Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); + return NULL; + } + + res = ID3D11Device_CreateVertexShader( + renderer->device, + ID3D10Blob_GetBufferPointer(vertShaderModule->blob), + ID3D10Blob_GetBufferSize(vertShaderModule->blob), + NULL, + (ID3D11VertexShader**) &vertShaderModule->shader + ); + ERROR_CHECK_RETURN("Could not create vertex shader", NULL); + } + + if (fragShaderModule->shader == NULL) + { + res = renderer->D3DCompileFunc( + fragShaderModule->shaderSource, + fragShaderModule->shaderSourceLength, + NULL, + NULL, + NULL, + "main", + "ps_5_0", + 0, + 0, + &fragShaderModule->blob, + &errorBlob + ); + if (FAILED(res)) + { + Refresh_LogError("Fragment Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); + return NULL; + } + + res = ID3D11Device_CreatePixelShader( + renderer->device, + ID3D10Blob_GetBufferPointer(fragShaderModule->blob), + ID3D10Blob_GetBufferSize(fragShaderModule->blob), + NULL, + (ID3D11PixelShader**) &fragShaderModule->shader + ); + ERROR_CHECK_RETURN("Could not create pixel shader", NULL); + } + + /* Allocate and set up the pipeline */ + pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline)); + /* Blend */ pipeline->colorAttachmentBlendState = D3D11_INTERNAL_FetchBlendState( @@ -1290,36 +1358,6 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( /* Vertex Shader */ - if (vertShaderModule->shader == NULL) - { - res = renderer->D3DCompileFunc( - vertShaderModule->shaderSource, - vertShaderModule->shaderSourceLength, - NULL, - NULL, - NULL, - "main", /* FIXME: Is this correct or should this be vertexShaderInfo.entryPoint? */ - "vs_5_0", - 0, - 0, - &vertShaderModule->blob, - &errorBlob - ); - if (FAILED(res)) - { - Refresh_LogError("Vertex Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); - return NULL; - } - - res = ID3D11Device_CreateVertexShader( - renderer->device, - ID3D10Blob_GetBufferPointer(vertShaderModule->blob), - ID3D10Blob_GetBufferSize(vertShaderModule->blob), - NULL, - (ID3D11VertexShader**) &vertShaderModule->shader - ); - ERROR_CHECK_RETURN("Could not create vertex shader", NULL); /* FIXME: This leaks the pipeline! */ - } pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shader; pipeline->numVertexSamplers = pipelineCreateInfo->vertexShaderInfo.samplerBindingCount; pipeline->vertexUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( @@ -1355,36 +1393,6 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( /* Fragment Shader */ - if (fragShaderModule->shader == NULL) - { - res = renderer->D3DCompileFunc( - fragShaderModule->shaderSource, - fragShaderModule->shaderSourceLength, - NULL, - NULL, - NULL, - "main", /* FIXME: Is this correct or should this be fragmentShaderInfo.entryPoint? */ - "ps_5_0", - 0, - 0, - &fragShaderModule->blob, - &errorBlob - ); - if (FAILED(res)) - { - Refresh_LogError("Fragment Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); - return NULL; - } - - res = ID3D11Device_CreatePixelShader( - renderer->device, - ID3D10Blob_GetBufferPointer(fragShaderModule->blob), - ID3D10Blob_GetBufferSize(fragShaderModule->blob), - NULL, - (ID3D11PixelShader**) &fragShaderModule->shader - ); - ERROR_CHECK_RETURN("Could not create pixel shader", NULL); /* FIXME: This leaks the pipeline! */ - } pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader; pipeline->numFragmentSamplers = pipelineCreateInfo->fragmentShaderInfo.samplerBindingCount; pipeline->fragmentUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( -- 2.25.1 From 19c6c48021eaff1aff290cfff5dbc799b3a7d2d4 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:07:01 -0600 Subject: [PATCH 66/69] Add shader type to the .refresh shader bytecode format --- shadercompiler/Program.cs | 11 ++ src/Refresh.c | 22 +++- src/Refresh_Driver.h | 18 ++- src/Refresh_Driver_D3D11.c | 209 ++++++++++++++------------------ src/Refresh_Driver_Template.txt | 2 +- src/Refresh_Driver_Vulkan.c | 2 +- 6 files changed, 134 insertions(+), 130 deletions(-) diff --git a/shadercompiler/Program.cs b/shadercompiler/Program.cs index a76a1de..7e3f10d 100644 --- a/shadercompiler/Program.cs +++ b/shadercompiler/Program.cs @@ -194,6 +194,17 @@ partial class Program // Magic writer.Write(new char[] { 'R', 'F', 'S', 'H'}); + // Type + uint shaderTypeIndex; + switch (shaderType) + { + default: + case ".vert": shaderTypeIndex = 0; break; + case ".frag": shaderTypeIndex = 1; break; + case ".comp": shaderTypeIndex = 2; break; + } + writer.Write(shaderTypeIndex); + if (data.vulkan) { string inputPath = Path.Combine(tempDir, $"{shaderName}.spv"); diff --git a/src/Refresh.c b/src/Refresh.c index 4b2ad46..6af6de1 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -345,7 +345,7 @@ Refresh_ShaderModule* Refresh_CreateShaderModule( Refresh_Device *device, Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo ) { - Refresh_ShaderModuleCreateInfo driverSpecificCreateInfo = { 0, NULL }; + Refresh_Driver_ShaderModuleCreateInfo driverSpecificCreateInfo = { 0, NULL, 0 }; uint8_t *bytes; uint32_t i, size; @@ -355,12 +355,24 @@ Refresh_ShaderModule* Refresh_CreateShaderModule( bytes = (uint8_t*) shaderModuleCreateInfo->byteCode; if (bytes[0] != 'R' || bytes[1] != 'F' || bytes[2] != 'S' || bytes[3] != 'H') { - Refresh_LogError("Cannot parse malformed Refresh shader blob!"); + Refresh_LogError("Cannot parse malformed Refresh shader blob: Incorrect magic number"); + return NULL; + } + + /* get the type of shader */ + driverSpecificCreateInfo.type = (Refresh_Driver_ShaderType) *((uint32_t*) &bytes[4]); + if ( driverSpecificCreateInfo.type < 0 || + driverSpecificCreateInfo.type > REFRESH_DRIVER_SHADERTYPE_COMPUTE ) + { + Refresh_LogError( + "Cannot parse malformed Refresh shader blob: Unknown shader type (%d)", + driverSpecificCreateInfo.type + ); return NULL; } /* find the code for the selected backend */ - i = 4; + i = 8; while (i < shaderModuleCreateInfo->codeSize) { size = *((uint32_t*) &bytes[i + 1]); @@ -947,9 +959,7 @@ int Refresh_QueryFence( Refresh_Device *device, Refresh_Fence *fence ) { - if (device == NULL) { - return 0; - } + if (device == NULL) { return 0; } return device->QueryFence( device->driverData, diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index b8ae8a2..9d1de52 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -211,6 +211,22 @@ static inline int32_t BytesPerImage( #define MAX_COLOR_TARGET_BINDINGS 4 #define MAX_PRESENT_COUNT 16 +/* Internal Shader Module Create Info */ + +typedef enum Refresh_Driver_ShaderType +{ + REFRESH_DRIVER_SHADERTYPE_VERTEX, + REFRESH_DRIVER_SHADERTYPE_FRAGMENT, + REFRESH_DRIVER_SHADERTYPE_COMPUTE +} Refresh_Driver_ShaderType; + +typedef struct Refresh_Driver_ShaderModuleCreateInfo +{ + size_t codeSize; + const uint32_t* byteCode; + Refresh_Driver_ShaderType type; +} Refresh_Driver_ShaderModuleCreateInfo; + /* Refresh_Device Definition */ typedef struct Refresh_Renderer Refresh_Renderer; @@ -292,7 +308,7 @@ struct Refresh_Device Refresh_ShaderModule* (*CreateShaderModule)( Refresh_Renderer *driverData, - Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo + Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo ); Refresh_Texture* (*CreateTexture)( diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 95ff71b..746d4a2 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -397,8 +397,6 @@ typedef struct D3D11ShaderModule { ID3D11DeviceChild *shader; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */ ID3D10Blob *blob; - char *shaderSource; - size_t shaderSourceLength; } D3D11ShaderModule; typedef struct D3D11GraphicsPipeline @@ -1183,44 +1181,8 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule; - ID3D10Blob *errorBlob; - D3D11ComputePipeline *pipeline; - HRESULT res; - /* First, compile the shader since we didn't do that when creating the shader module */ - if (shaderModule->shader == NULL) - { - res = renderer->D3DCompileFunc( - shaderModule->shaderSource, - shaderModule->shaderSourceLength, - NULL, - NULL, - NULL, - "main", - "cs_5_0", - 0, - 0, - &shaderModule->blob, - &errorBlob - ); - if (FAILED(res)) - { - Refresh_LogError("Compute Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); - return NULL; - } - - res = ID3D11Device_CreateComputeShader( - renderer->device, - ID3D10Blob_GetBufferPointer(shaderModule->blob), - ID3D10Blob_GetBufferSize(shaderModule->blob), - NULL, - (ID3D11ComputeShader**) &shaderModule->shader - ); - ERROR_CHECK_RETURN("Could not create compute shader", NULL); - } - - /* Allocate and set up the pipeline */ - pipeline = SDL_malloc(sizeof(D3D11ComputePipeline)); + D3D11ComputePipeline *pipeline = SDL_malloc(sizeof(D3D11ComputePipeline)); pipeline->numTextures = computeShaderInfo->imageBindingCount; pipeline->numBuffers = computeShaderInfo->bufferBindingCount; pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; @@ -1239,75 +1201,8 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11ShaderModule *vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule; D3D11ShaderModule *fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule; - ID3D10Blob *errorBlob; - D3D11GraphicsPipeline *pipeline; - HRESULT res; - /* First, compile the shaders since we didn't do that when creating the shader modules */ - if (vertShaderModule->shader == NULL) - { - res = renderer->D3DCompileFunc( - vertShaderModule->shaderSource, - vertShaderModule->shaderSourceLength, - NULL, - NULL, - NULL, - "main", - "vs_5_0", - 0, - 0, - &vertShaderModule->blob, - &errorBlob - ); - if (FAILED(res)) - { - Refresh_LogError("Vertex Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); - return NULL; - } - - res = ID3D11Device_CreateVertexShader( - renderer->device, - ID3D10Blob_GetBufferPointer(vertShaderModule->blob), - ID3D10Blob_GetBufferSize(vertShaderModule->blob), - NULL, - (ID3D11VertexShader**) &vertShaderModule->shader - ); - ERROR_CHECK_RETURN("Could not create vertex shader", NULL); - } - - if (fragShaderModule->shader == NULL) - { - res = renderer->D3DCompileFunc( - fragShaderModule->shaderSource, - fragShaderModule->shaderSourceLength, - NULL, - NULL, - NULL, - "main", - "ps_5_0", - 0, - 0, - &fragShaderModule->blob, - &errorBlob - ); - if (FAILED(res)) - { - Refresh_LogError("Fragment Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob)); - return NULL; - } - - res = ID3D11Device_CreatePixelShader( - renderer->device, - ID3D10Blob_GetBufferPointer(fragShaderModule->blob), - ID3D10Blob_GetBufferSize(fragShaderModule->blob), - NULL, - (ID3D11PixelShader**) &fragShaderModule->shader - ); - ERROR_CHECK_RETURN("Could not create pixel shader", NULL); - } - - /* Allocate and set up the pipeline */ - pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline)); + D3D11GraphicsPipeline *pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline)); /* Blend */ @@ -1454,23 +1349,96 @@ static Refresh_Sampler* D3D11_CreateSampler( static Refresh_ShaderModule* D3D11_CreateShaderModule( Refresh_Renderer *driverData, - Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo + Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule)); + D3D11ShaderModule* shaderModule; + Refresh_Driver_ShaderType shaderType = shaderModuleCreateInfo->type; + const char *profileNames[] = { "vs_5_0", "ps_5_0", "cs_5_0" }; + ID3D10Blob *blob, *errorBlob; + ID3D11DeviceChild *shader = NULL; + HRESULT res; - /* We don't know whether this is a vertex, fragment, or compute shader, - * so wait to compile until we bind to a pipeline... - * - * FIXME: Could we store a flag in the shaderc output to mark if a shader is vertex/fragment/compute? - * Then we could compile on shader module creation instead of at bind time. - */ - shaderModule->shader = NULL; - shaderModule->blob = NULL; + /* Compile HLSL to DXBC */ + res = renderer->D3DCompileFunc( + shaderModuleCreateInfo->byteCode, + shaderModuleCreateInfo->codeSize, + NULL, + NULL, + NULL, + "main", /* API FIXME: Intentionally ignoring entryPointName because it MUST be "main" anyway */ + profileNames[shaderType], + 0, + 0, + &blob, + &errorBlob + ); + if (FAILED(res)) + { + Refresh_LogError( + "D3DCompile Error (%s): %s", + profileNames[shaderType], + ID3D10Blob_GetBufferPointer(errorBlob) + ); + ID3D10Blob_Release(errorBlob); + return NULL; + } - shaderModule->shaderSourceLength = shaderModuleCreateInfo->codeSize; - shaderModule->shaderSource = (char*) SDL_malloc(shaderModule->shaderSourceLength); - SDL_memcpy(shaderModule->shaderSource, shaderModuleCreateInfo->byteCode, shaderModuleCreateInfo->codeSize); + /* Actually create the shader */ + if (shaderType == REFRESH_DRIVER_SHADERTYPE_VERTEX) + { + res = ID3D11Device_CreateVertexShader( + renderer->device, + ID3D10Blob_GetBufferPointer(blob), + ID3D10Blob_GetBufferSize(blob), + NULL, + (ID3D11VertexShader**) &shader + ); + if (FAILED(res)) + { + D3D11_INTERNAL_LogError(renderer->device, "Could not compile vertex shader", res); + ID3D10Blob_Release(blob); + return NULL; + } + } + else if (shaderType == REFRESH_DRIVER_SHADERTYPE_FRAGMENT) + { + res = ID3D11Device_CreatePixelShader( + renderer->device, + ID3D10Blob_GetBufferPointer(blob), + ID3D10Blob_GetBufferSize(blob), + NULL, + (ID3D11PixelShader**) &shader + ); + if (FAILED(res)) + { + D3D11_INTERNAL_LogError(renderer->device, "Could not compile pixel shader", res); + ID3D10Blob_Release(blob); + return NULL; + } + } + else if (shaderType == REFRESH_DRIVER_SHADERTYPE_COMPUTE) + { + res = ID3D11Device_CreateComputeShader( + renderer->device, + ID3D10Blob_GetBufferPointer(blob), + ID3D10Blob_GetBufferSize(blob), + NULL, + (ID3D11ComputeShader**) &shader + ); + if (FAILED(res)) + { + D3D11_INTERNAL_LogError(renderer->device, "Could not compile compute shader", res); + ID3D10Blob_Release(blob); + return NULL; + } + } + + + /* Allocate and set up the shader module */ + shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule)); + shaderModule->shader = shader; + shaderModule->blob = blob; return (Refresh_ShaderModule*) shaderModule; } @@ -2440,7 +2408,6 @@ static void D3D11_QueueDestroyShaderModule( ID3D10Blob_Release(d3dShaderModule->blob); } - SDL_free(d3dShaderModule->shaderSource); SDL_free(d3dShaderModule); } diff --git a/src/Refresh_Driver_Template.txt b/src/Refresh_Driver_Template.txt index a56ffb1..8052dfb 100644 --- a/src/Refresh_Driver_Template.txt +++ b/src/Refresh_Driver_Template.txt @@ -318,7 +318,7 @@ static Refresh_Sampler* TEMPLATE_CreateSampler( static Refresh_ShaderModule* TEMPLATE_CreateShaderModule( Refresh_Renderer *driverData, - Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo + Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo ) { NOT_IMPLEMENTED } diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index c16934a..b481609 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -6956,7 +6956,7 @@ static Refresh_Sampler* VULKAN_CreateSampler( static Refresh_ShaderModule* VULKAN_CreateShaderModule( Refresh_Renderer *driverData, - Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo + Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo ) { VulkanShaderModule *vulkanShaderModule = SDL_malloc(sizeof(VulkanShaderModule)); VkResult vulkanResult; -- 2.25.1 From 9ea76e92dc58b2c84c46b7c5224591191236ea78 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:08:34 -0600 Subject: [PATCH 67/69] Move uav FIXME's to API FIXME's --- src/Refresh_Driver_D3D11.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 746d4a2..ade9e83 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1544,12 +1544,13 @@ static Refresh_Texture* D3D11_CreateTexture( } /* Create the UAV, if applicable */ + /* API FIXME: Create these dynamically as needed per mip level! */ if (isCompute) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; - uavDesc.Texture2D.MipSlice = 0; /* FIXME */ + uavDesc.Texture2D.MipSlice = 0; res = ID3D11Device_CreateUnorderedAccessView( renderer->device, @@ -1659,14 +1660,15 @@ static Refresh_Texture* D3D11_CreateTexture( } /* Create the UAV, if applicable */ + /* API FIXME: Create these dynamically as needed per mip level! */ if (isCompute) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; uavDesc.Format = format; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; - uavDesc.Texture3D.MipSlice = 0; /* FIXME */ - uavDesc.Texture3D.FirstWSlice = 0; /* FIXME */ - uavDesc.Texture3D.WSize = -1; /* FIXME */ + uavDesc.Texture3D.MipSlice = 0; + uavDesc.Texture3D.FirstWSlice = 0; + uavDesc.Texture3D.WSize = -1; res = ID3D11Device_CreateUnorderedAccessView( renderer->device, -- 2.25.1 From b827713cb0091a90772e9ce3041eaef0d3963629 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:36:41 -0600 Subject: [PATCH 68/69] Compute buffer creation fixes --- src/Refresh_Driver_D3D11.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ade9e83..ac5a676 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1434,7 +1434,6 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule( } } - /* Allocate and set up the shader module */ shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule)); shaderModule->shader = shader; @@ -1748,9 +1747,18 @@ static Refresh_Buffer* D3D11_CreateBuffer( bufferDesc.ByteWidth = sizeInBytes; bufferDesc.Usage = D3D11_USAGE_DEFAULT; bufferDesc.CPUAccessFlags = 0; - bufferDesc.MiscFlags = (usageFlags & REFRESH_BUFFERUSAGE_INDIRECT_BIT) ? D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS : 0; bufferDesc.StructureByteStride = 0; + bufferDesc.MiscFlags = 0; + if (usageFlags & REFRESH_BUFFERUSAGE_INDIRECT_BIT) + { + bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; + } + if (usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) + { + bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + } + res = ID3D11Device_CreateBuffer( renderer->device, &bufferDesc, @@ -1763,11 +1771,11 @@ static Refresh_Buffer* D3D11_CreateBuffer( if (usageFlags & REFRESH_BUFFERUSAGE_COMPUTE_BIT) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; - uavDesc.Format = DXGI_FORMAT_R8_UINT; + uavDesc.Format = DXGI_FORMAT_R32_TYPELESS; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; uavDesc.Buffer.FirstElement = 0; - uavDesc.Buffer.Flags = 0; - uavDesc.Buffer.NumElements = sizeInBytes; + uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; + uavDesc.Buffer.NumElements = sizeInBytes / sizeof(uint32_t); res = ID3D11Device_CreateUnorderedAccessView( renderer->device, -- 2.25.1 From 345924f12d795625aa45172fa6c6ea2b9c83ee4c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:40:48 -0600 Subject: [PATCH 69/69] Fix infinite while loop in D3D11_INTERNAL_WaitForFence --- src/Refresh_Driver_D3D11.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ac5a676..dd77729 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -3655,17 +3655,17 @@ static void D3D11_INTERNAL_WaitForFence( SDL_LockMutex(renderer->contextLock); - res = ID3D11DeviceContext_GetData( - renderer->immediateContext, - (ID3D11Asynchronous*) fence->handle, - &queryData, - sizeof(queryData), - 0 - ); - while (res != S_OK) + do { - /* Spin until we get a result back... */ + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous*)fence->handle, + &queryData, + sizeof(queryData), + 0 + ); } + while (res != S_OK); /* Spin until we get a result back... */ SDL_UnlockMutex(renderer->contextLock); } -- 2.25.1