From d6378aba7461a7e8086074fb5770e35c8d5d9f81 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 22 Sep 2023 20:44:20 -0500 Subject: [PATCH 01/98] 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 3e1a490..feb22d8 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -343,6 +343,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 08cdfb4..9abf005 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 a7d58c7..678e18b 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -661,6 +661,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 5385f02bbd075d478c55630f04795dd7a8c56d8f Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 24 Sep 2023 19:25:49 -0500 Subject: [PATCH 02/98] 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 b9d7cec252f8953f19e9e1ae83c775f08ac114e4 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 24 Sep 2023 21:20:04 -0500 Subject: [PATCH 03/98] 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 dd1060373d35cbb9037a5d693291feb08d9267c7 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 24 Sep 2023 21:29:11 -0500 Subject: [PATCH 04/98] 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 08ba4675519c1a4d0c0e0684e21f8ce528c73719 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Mon, 25 Sep 2023 21:24:01 -0500 Subject: [PATCH 05/98] 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 dd9ae93696b16ee734f933e845188cced080f7fd Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Mon, 25 Sep 2023 22:10:36 -0500 Subject: [PATCH 06/98] 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 cbd8f4aee08def9b07aa0a332e9b6ec256e85ea1 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 27 Sep 2023 21:01:45 -0500 Subject: [PATCH 07/98] 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 0948537fe07151c69df1ce4f142bfadced0d615f Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 27 Sep 2023 21:12:28 -0500 Subject: [PATCH 08/98] 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 acae35ebfa55b47b2f207783e56f1f3764c82534 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 29 Sep 2023 20:52:14 -0500 Subject: [PATCH 09/98] 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 9abf005..5bffa44 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 acf64d51f09a994ed43aa5cb77ccf050a72f8e67 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 8 Oct 2023 16:05:33 -0500 Subject: [PATCH 10/98] 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 b74666a6d70e0816da4068ef9f779b60648bbf08 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 8 Oct 2023 16:16:11 -0500 Subject: [PATCH 11/98] 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 f008408965e866d7fdceb4e77c7f035b9d5a54ce Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:27:36 -0500 Subject: [PATCH 12/98] 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 dda7db1d9299899154ffb8b8b57565fd0d16cb1a Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:32:12 -0500 Subject: [PATCH 13/98] 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 01cd001b074390045c2e23f1f779dc1b701cb518 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:45:32 -0500 Subject: [PATCH 14/98] 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 afeb7ebd1661ff70c7707032bf4ddfd8753503f2 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 10 Oct 2023 21:51:34 -0500 Subject: [PATCH 15/98] 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 740fb56aa14cbb9959a042972b9989816e96651d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 08:18:39 -0500 Subject: [PATCH 16/98] 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 d7290c5e2b50ce8dc41d5137bde1d38d0508331d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 08:18:53 -0500 Subject: [PATCH 17/98] 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 abfdb2c7d98ca8ddfb23d75dd6cd175d9fa85df9 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 08:42:32 -0500 Subject: [PATCH 18/98] 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 15a73854b672bb5c6a612e85d685db87847471a0 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 21:31:04 -0500 Subject: [PATCH 19/98] 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 7f4ddde607ad0c2685f5964ab0c6c8c6d2725c9e Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 22:07:46 -0500 Subject: [PATCH 20/98] 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 b906ec9c69ae9964391006f41f1074a4f5056263 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 22:11:55 -0500 Subject: [PATCH 21/98] 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 ba842d855e07f121ff9aabd4f858a637fb4514ce Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 12 Oct 2023 22:12:55 -0500 Subject: [PATCH 22/98] 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 a7bbc51653e5a6a556ce8a8880d15a5747ddd703 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 20:37:27 -0500 Subject: [PATCH 23/98] 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 6a1c4ba80f4fa5ef5ff9462fa9cbef9c1bdd8f01 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 21:25:03 -0500 Subject: [PATCH 24/98] 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 678e18b..5e06f2e 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 ce3b222529b6cd27dab07eb4bfa73ceb6d5b6d96 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 21:39:15 -0500 Subject: [PATCH 25/98] 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 cdad57d1ddeccd169c972c665bb239e7d089378c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 26 Oct 2023 23:03:05 -0500 Subject: [PATCH 26/98] 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 eb956a2f8b8f671f4914d83c7e3a097aa93cf5d0 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 5 Nov 2023 14:17:23 -0600 Subject: [PATCH 27/98] 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 a3c8ab6a5576318bd27ae953a4414b735266a89b Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 5 Nov 2023 19:20:37 -0600 Subject: [PATCH 28/98] 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 c9f23dd73baf6ef53de030abafc556a4d01319d7 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 6 Feb 2024 21:48:16 -0600 Subject: [PATCH 29/98] 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 ca29f3b7da4a28c0eec54d53e21bda3f32aa9735 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Tue, 6 Feb 2024 22:40:16 -0600 Subject: [PATCH 30/98] 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 0108b26d3174e0b72aff1ec4153eaa0ac7756d07 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 07:33:23 -0600 Subject: [PATCH 31/98] 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 db6ad7fb6a70d11ebb9f52a1d5f208c16c5df314 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 07:34:07 -0600 Subject: [PATCH 32/98] 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 5f3dd6ba8a618218cc8b23094b5aa7973a24715e Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 08:02:49 -0600 Subject: [PATCH 33/98] 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 b712bda8a3a8d56158e475f63c5ca41d81fae0d9 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 09:09:01 -0600 Subject: [PATCH 34/98] 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 e7be43e835855b6aa513a430e614821426892845 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 09:09:30 -0600 Subject: [PATCH 35/98] 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 5d069f006d7f4e5da65b283df6da4c92f352ded0 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 09:35:03 -0600 Subject: [PATCH 36/98] 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 4d11afa422c081bb31445b9d0c4362e9e3e789bc Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 10:08:23 -0600 Subject: [PATCH 37/98] 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 60a0ecab92ce64033f1f15544a706fa29a57a321 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 10:18:49 -0600 Subject: [PATCH 38/98] 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 f598b65be52f1bb8471af9a9916eb334aab53427 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 11:53:18 -0600 Subject: [PATCH 39/98] 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 297b8b2cd206fea4af650195a89b26f7d4d760ac Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Wed, 7 Feb 2024 21:03:21 -0600 Subject: [PATCH 40/98] 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 06f00c77a0bc12171c88b602e6508e0790574b68 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 8 Feb 2024 22:53:36 -0600 Subject: [PATCH 41/98] 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 155d01ed92ae970dcadf31d1df5b55f58fe9b04b Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 8 Feb 2024 23:47:25 -0600 Subject: [PATCH 42/98] 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 105ef1aebb3554adcf9721d8c665b5a2d7b66a92 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 8 Feb 2024 23:59:13 -0600 Subject: [PATCH 43/98] 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 d76d223f6874b1955acdb87188ae4d4cb543d598 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 00:31:54 -0600 Subject: [PATCH 44/98] 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 508d077c267f4bc331637327ec63fedc2b1b4432 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 00:35:19 -0600 Subject: [PATCH 45/98] 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 f7fae4d3148078084c9bd16bc2f8b87c03ca512a Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 00:57:26 -0600 Subject: [PATCH 46/98] 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 11cbfca702940d4e4505c6d6a69c6eb21c54425b Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 02:02:41 -0600 Subject: [PATCH 47/98] 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 557ce50737700883b622d333aecda78a55c2d51c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 02:17:08 -0600 Subject: [PATCH 48/98] 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 c9b98c6e2b481ac5ee4a412ce23e9d65119951fc Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 11:04:32 -0600 Subject: [PATCH 49/98] 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 dcac27b5d867ddfa440c60dfc5c0bf866c0836fc Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 11:19:51 -0600 Subject: [PATCH 50/98] 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 0f2aacbae9ba3d46ea082f2a0022c65cae398669 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 12:09:29 -0600 Subject: [PATCH 51/98] 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 92f344d2f6e24e06c1da16a5e1f694566f1ed570 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 15:28:08 -0600 Subject: [PATCH 52/98] 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 9f78f833225e72d68715330d9d35f24e94ea5b7d Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 16:03:57 -0600 Subject: [PATCH 53/98] 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 e3d112a9714b2ade3f66f223f401f56a81c5e6f3 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 16:37:08 -0600 Subject: [PATCH 54/98] 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 02aaf582d468018309ac6f7a81735a4912487772 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 16:39:55 -0600 Subject: [PATCH 55/98] 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 95781e337837bd3a91ed24ef309d0be67d06941e Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 17:23:48 -0600 Subject: [PATCH 56/98] 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 b3addd6e0bfb156c56227acc899a69a12ea5bb80 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 17:52:47 -0600 Subject: [PATCH 57/98] 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 644763f004cc5b714ea300051605962395b85cc8 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Fri, 9 Feb 2024 23:56:36 -0600 Subject: [PATCH 58/98] 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 a5284ba0cd2afb2c6d4e37078fa75d1744d03760 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 00:19:11 -0600 Subject: [PATCH 59/98] 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 17f932269882ecfb295cf8497a8406c1e8bd728a Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 17:07:56 -0600 Subject: [PATCH 60/98] 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 539ee66d41593db8d96e8ab6258f314df66d74d8 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 18:00:12 -0600 Subject: [PATCH 61/98] 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 4fe02e8571bb91c14c5958fd33298b10a5e21c08 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 21:49:19 -0600 Subject: [PATCH 62/98] 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 0a520f7a664a9dda60c758a380ffeffd419f97da Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 22:18:25 -0600 Subject: [PATCH 63/98] 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 56f292f98709c482fee8ee75e4fe21f46da651f7 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 22:21:01 -0600 Subject: [PATCH 64/98] 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 c497402f1d2958118491323d3bcf582726aded7c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 10 Feb 2024 23:00:55 -0600 Subject: [PATCH 65/98] 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 7274173b440a7065ed53ff3af7494f93f32455bc Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:07:01 -0600 Subject: [PATCH 66/98] 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 5bffa44..c3b0fbe 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -242,7 +242,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; @@ -252,12 +252,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]); @@ -1074,9 +1086,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 5e06f2e..f1cf090 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; @@ -240,7 +256,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 c4a34e5..890644a 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -6670,7 +6670,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 27b166dfdedc7a4da9c5a552aec4ca48e70fa192 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:08:34 -0600 Subject: [PATCH 67/98] 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 e7d258dd36351668b3c87258bd256c8c149a605c Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:36:41 -0600 Subject: [PATCH 68/98] 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 8f2e70948d09ce0662f09ff595059c19f0acd4a4 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sun, 11 Feb 2024 00:40:48 -0600 Subject: [PATCH 69/98] 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 From 172348e65f7e6ce9c9b2e8d614fc83c8f31a1230 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 2 Mar 2024 23:02:44 -0800 Subject: [PATCH 70/98] fix stencil API --- CMakeLists.txt | 2 +- src/Refresh_Driver_D3D11.c | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8aecf23..c79d471 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,7 @@ add_library(Refresh # Internal Headers src/Refresh_Driver.h src/Refresh_Driver_Vulkan_vkfuncs.h - Refresh_Driver_D3D11_cdefines.h + src/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 dd77729..1b0caa7 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1032,9 +1032,8 @@ static ID3D11DepthStencilState* D3D11_INTERNAL_FetchDepthStencilState( dsDesc.FrontFace.StencilFailOp = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.failOp]; dsDesc.FrontFace.StencilPassOp = RefreshToD3D11_CompareOp[depthStencilState.frontStencilState.passOp]; - /* 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; + dsDesc.StencilReadMask = depthStencilState.compareMask; + dsDesc.StencilWriteMask = depthStencilState.writeMask; if (depthStencilState.depthBoundsTestEnable) { @@ -1240,8 +1239,7 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline( pipeline->depthStencilAttachmentFormat = RefreshToD3D11_TextureFormat[ pipelineCreateInfo->attachmentInfo.depthStencilFormat ]; - /* API FIXME: D3D11 doesn't have separate references for each stencil side. What should we do? */ - pipeline->stencilRef = pipelineCreateInfo->depthStencilState.frontStencilState.reference; + pipeline->stencilRef = pipelineCreateInfo->depthStencilState.reference; /* Rasterizer */ -- 2.25.1 From f61938011b40d10f4c8e9f2d351ded74fe226081 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 2 Mar 2024 23:33:36 -0800 Subject: [PATCH 71/98] draw and uniform push API change --- src/Refresh_Driver_D3D11.c | 67 ++++++++++++++------------------------ 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 1b0caa7..d7d6019 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -445,7 +445,8 @@ typedef struct D3D11Buffer typedef struct D3D11UniformBuffer { D3D11Buffer *d3d11Buffer; - uint32_t offset; + uint32_t offset; /* number of bytes written */ + uint32_t drawOffset; /* parameter for SetConstantBuffers */ uint8_t hasDiscarded; } D3D11UniformBuffer; @@ -753,13 +754,11 @@ static void D3D11_DrawInstancedPrimitives( uint32_t baseVertex, uint32_t startIndex, uint32_t primitiveCount, - uint32_t instanceCount, - uint32_t vertexParamOffset, - uint32_t fragmentParamOffset + uint32_t instanceCount ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - uint32_t vertexOffsetInConstants = vertexParamOffset / 16; - uint32_t fragmentOffsetInConstants = fragmentParamOffset / 16; + uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16; + uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16; uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; @@ -802,9 +801,7 @@ static void D3D11_DrawIndexedPrimitives( Refresh_CommandBuffer *commandBuffer, uint32_t baseVertex, uint32_t startIndex, - uint32_t primitiveCount, - uint32_t vertexParamOffset, - uint32_t fragmentParamOffset + uint32_t primitiveCount ) { D3D11_DrawInstancedPrimitives( driverData, @@ -812,9 +809,7 @@ static void D3D11_DrawIndexedPrimitives( baseVertex, startIndex, primitiveCount, - 1, - vertexParamOffset, - fragmentParamOffset + 1 ); } @@ -822,13 +817,11 @@ static void D3D11_DrawPrimitives( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, uint32_t vertexStart, - uint32_t primitiveCount, - uint32_t vertexParamOffset, - uint32_t fragmentParamOffset + uint32_t primitiveCount ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - uint32_t vertexOffsetInConstants = vertexParamOffset / 16; - uint32_t fragmentOffsetInConstants = fragmentParamOffset / 16; + uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16; + uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16; uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; @@ -866,17 +859,15 @@ static void D3D11_DrawPrimitives( static void D3D11_DrawPrimitivesIndirect( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer *buffer, + Refresh_GpuBuffer *gpuBuffer, uint32_t offsetInBytes, uint32_t drawCount, - uint32_t stride, - uint32_t vertexParamOffset, - uint32_t fragmentParamOffset + uint32_t stride ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; - uint32_t vertexOffsetInConstants = vertexParamOffset / 16; - uint32_t fragmentOffsetInConstants = fragmentParamOffset / 16; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; + uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16; + uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16; uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; @@ -918,15 +909,14 @@ static void D3D11_DrawPrimitivesIndirect( } static void D3D11_DispatchCompute( - Refresh_Renderer *device, + Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, uint32_t groupCountX, uint32_t groupCountY, - uint32_t groupCountZ, - uint32_t computeParamOffset + uint32_t groupCountZ ) { D3D11CommandBuffer* d3d11CommandBuffer = (D3D11CommandBuffer*)commandBuffer; - uint32_t computeOffsetInConstants = computeParamOffset / 16; + uint32_t computeOffsetInConstants = d3d11CommandBuffer->computeUniformBuffer->drawOffset / 16; uint32_t computeBlockSizeInConstants = (uint32_t) (d3d11CommandBuffer->computePipeline->computeUniformBlockSize / 16); if (d3d11CommandBuffer->computeUniformBuffer != NULL) @@ -2056,6 +2046,7 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer)); uniformBuffer->offset = 0; + uniformBuffer->drawOffset = 0; uniformBuffer->hasDiscarded = 0; uniformBuffer->d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); uniformBuffer->d3d11Buffer->handle = bufferHandle; @@ -2108,6 +2099,7 @@ static uint8_t D3D11_INTERNAL_AcquireUniformBuffer( /* Reset the uniform buffer */ uniformBuffer->hasDiscarded = 0; uniformBuffer->offset = 0; + uniformBuffer->drawOffset = 0; /* Bind the uniform buffer to the command buffer */ if (commandBuffer->boundUniformBufferCount >= commandBuffer->boundUniformBufferCapacity) @@ -2160,7 +2152,7 @@ static void D3D11_INTERNAL_SetUniformBufferData( uniformBuffer->hasDiscarded = 1; } -static uint32_t D3D11_PushVertexShaderUniforms( +static void D3D11_PushVertexShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *data, @@ -2169,7 +2161,6 @@ static uint32_t D3D11_PushVertexShaderUniforms( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11GraphicsPipeline *graphicsPipeline = d3d11CommandBuffer->graphicsPipeline; - uint32_t offset; if (d3d11CommandBuffer->vertexUniformBuffer->offset + graphicsPipeline->vertexUniformBlockSize >= UBO_BUFFER_SIZE) { @@ -2182,7 +2173,7 @@ static uint32_t D3D11_PushVertexShaderUniforms( ); } - offset = d3d11CommandBuffer->vertexUniformBuffer->offset; + d3d11CommandBuffer->vertexUniformBuffer->drawOffset = d3d11CommandBuffer->vertexUniformBuffer->offset; D3D11_INTERNAL_SetUniformBufferData( renderer, @@ -2193,11 +2184,9 @@ static uint32_t D3D11_PushVertexShaderUniforms( ); d3d11CommandBuffer->vertexUniformBuffer->offset += graphicsPipeline->vertexUniformBlockSize; - - return offset; } -static uint32_t D3D11_PushFragmentShaderUniforms( +static void D3D11_PushFragmentShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *data, @@ -2206,7 +2195,6 @@ static uint32_t D3D11_PushFragmentShaderUniforms( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11GraphicsPipeline *graphicsPipeline = d3d11CommandBuffer->graphicsPipeline; - uint32_t offset; if (d3d11CommandBuffer->fragmentUniformBuffer->offset + graphicsPipeline->fragmentUniformBlockSize >= UBO_BUFFER_SIZE) { @@ -2219,7 +2207,7 @@ static uint32_t D3D11_PushFragmentShaderUniforms( ); } - offset = d3d11CommandBuffer->fragmentUniformBuffer->offset; + d3d11CommandBuffer->fragmentUniformBuffer->drawOffset = d3d11CommandBuffer->fragmentUniformBuffer->offset; D3D11_INTERNAL_SetUniformBufferData( renderer, @@ -2230,8 +2218,6 @@ static uint32_t D3D11_PushFragmentShaderUniforms( ); d3d11CommandBuffer->fragmentUniformBuffer->offset += graphicsPipeline->fragmentUniformBlockSize; - - return offset; } static uint32_t D3D11_PushComputeShaderUniforms( @@ -2243,7 +2229,6 @@ static uint32_t D3D11_PushComputeShaderUniforms( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11ComputePipeline *computePipeline = d3d11CommandBuffer->computePipeline; - uint32_t offset; if (d3d11CommandBuffer->computeUniformBuffer->offset + computePipeline->computeUniformBlockSize >= UBO_BUFFER_SIZE) { @@ -2256,7 +2241,7 @@ static uint32_t D3D11_PushComputeShaderUniforms( ); } - offset = d3d11CommandBuffer->computeUniformBuffer->offset; + d3d11CommandBuffer->computeUniformBuffer->drawOffset = d3d11CommandBuffer->computeUniformBuffer->offset; D3D11_INTERNAL_SetUniformBufferData( renderer, @@ -2268,8 +2253,6 @@ static uint32_t D3D11_PushComputeShaderUniforms( d3d11CommandBuffer->computeUniformBuffer->offset += (uint32_t) computePipeline->computeUniformBlockSize; /* API FIXME: Is this cast safe? */ - - return offset; } /* Samplers */ -- 2.25.1 From 16699e7ee322d8c11b2f6decd001213cb887ee81 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sun, 3 Mar 2024 10:58:44 -0800 Subject: [PATCH 72/98] implement D3D11 upload functions --- src/Refresh_Driver_D3D11.c | 179 +++++++++++++++++++++---------------- 1 file changed, 100 insertions(+), 79 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index d7d6019..fa3c171 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -442,6 +442,26 @@ typedef struct D3D11Buffer uint32_t size; } D3D11Buffer; +typedef struct D3D11TransferBuffer +{ + uint8_t *data; + uint32_t size; +} D3D11TransferBuffer; + +typedef struct D3D11TransferBufferContainer +{ + D3D11TransferBuffer *activeBuffer; + + /* These are all the buffers that have been used by this container. + * If the resource is bound and then updated with SafeDiscard, a new resource + * will be added to this list. + * These can be reused after they are submitted and command processing is complete. + */ + uint32_t bufferCapacity; + uint32_t bufferCount; + D3D11TransferBuffer **buffers; +} D3D11TransferBufferContainer; + typedef struct D3D11UniformBuffer { D3D11Buffer *d3d11Buffer; @@ -1706,7 +1726,7 @@ static Refresh_Texture* D3D11_CreateTexture( return (Refresh_Texture*) d3d11Texture; } -static Refresh_Buffer* D3D11_CreateBuffer( +static Refresh_GpuBuffer* D3D11_CreateGpuBuffer( Refresh_Renderer *driverData, Refresh_BufferUsageFlags usageFlags, uint32_t sizeInBytes @@ -1783,24 +1803,55 @@ static Refresh_Buffer* D3D11_CreateBuffer( d3d11Buffer->size = sizeInBytes; d3d11Buffer->uav = uav; - return (Refresh_Buffer*) d3d11Buffer; + return (Refresh_GpuBuffer*) d3d11Buffer; } -/* Texture Data */ - -static void D3D11_SetTextureData( +static Refresh_TransferBuffer* VULKAN_CreateTransferBuffer( Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, - void *data, - uint32_t dataLengthInBytes + uint32_t sizeInBytes ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - D3D11Texture *d3d11Texture = (D3D11Texture*) textureSlice->texture; + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) (sizeof(D3D11TransferBufferContainer)); + D3D11TransferBuffer *transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); - int32_t w = textureSlice->rectangle.w; - int32_t h = textureSlice->rectangle.h; + transferBuffer->data = SDL_malloc(sizeInBytes); + transferBuffer->size = sizeInBytes; + + container->activeBuffer = transferBuffer; + container->bufferCapacity = 1; + container->bufferCount = 1; + container->buffers = SDL_malloc( + container->bufferCapacity * sizeof(D3D11TransferBuffer) + ); + container->buffers[0] = transferBuffer; + + return (Refresh_TransferBuffer*) container; +} + +/* Copy Pass */ + +static void D3D11_BeginCopyPass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + /* no-op */ +} + +static void D3D11_UploadToTexture( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TransferBuffer *transferBuffer, + Refresh_TextureRegion *textureRegion, + Refresh_BufferImageCopy *copyParams, + Refresh_WriteOptions writeOption +) { + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; + D3D11Texture *d3d11Texture = (D3D11Texture*) textureRegion->textureSlice.texture; + + int32_t w = textureRegion->w; + int32_t h = textureRegion->h; int32_t blockSize = Texture_GetBlockSize(d3d11Texture->format); if (blockSize > 1) @@ -1810,89 +1861,52 @@ static void D3D11_SetTextureData( } 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; + dstBox.left = textureRegion->x; + dstBox.top = textureRegion->y; + dstBox.front = textureRegion->d; + dstBox.right = textureRegion->x + w; + dstBox.bottom = textureRegion->y + h; + dstBox.back = textureRegion->d + 1; ID3D11DeviceContext1_UpdateSubresource1( d3d11CommandBuffer->context, d3d11Texture->handle, D3D11_INTERNAL_CalcSubresource( - textureSlice->level, - textureSlice->layer, - d3d11Texture->levelCount + textureRegion->textureSlice.mipLevel, + textureRegion->textureSlice.layer, + 1 ), &dstBox, - data, - BytesPerRow(w, d3d11Texture->format), - BytesPerImage(w, h, d3d11Texture->format), - 0 /* FIXME: Could DISCARD here if we know we're overwriting the whole image... */ + d3d11TransferBuffer->data + copyParams->bufferOffset, + copyParams->bufferStride, + copyParams->bufferStride * copyParams->bufferImageHeight, + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 ); } -static void D3D11_SetTextureDataYUV( +static void D3D11_UploadToBuffer( 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 + Refresh_CommandBuffer *commandBuffer, + Refresh_TransferBuffer *transferBuffer, + Refresh_GpuBuffer *gpuBuffer, + Refresh_BufferCopy *copyParams, + Refresh_WriteOptions writeOption ) { - 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 }; + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; + D3D11_BOX dstBox = { copyParams->dstOffset, 0, 0, copyParams->dstOffset + copyParams->size, 1, 1 }; - /* Y */ ID3D11DeviceContext1_UpdateSubresource1( d3d11CommandBuffer->context, - yTex->handle, + (ID3D11Resource*) d3d11Buffer->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 + &dstBox, + d3d11TransferBuffer->data + copyParams->dstOffset, + copyParams->size, + 1, + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 ); } @@ -1915,6 +1929,13 @@ static void D3D11_CopyTextureToBuffer( NOT_IMPLEMENTED } +static void D3D11_EndCopyPass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + /* no-op */ +} + /* Buffer Data */ static void D3D11_SetBufferData( -- 2.25.1 From e01cab47ec6377ee52760cbc145faf679badaa13 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sun, 3 Mar 2024 11:27:48 -0800 Subject: [PATCH 73/98] D3D11 transfer buffer refcount and discard --- src/Refresh_Driver_D3D11.c | 169 ++++++++++++++++++++++++++++++++----- 1 file changed, 149 insertions(+), 20 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index fa3c171..d0f0a6b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -72,21 +72,14 @@ 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) \ - ); \ +#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \ + if (newCount >= capacity) \ + { \ + capacity = newCapacity; \ + arr = (elementType*) SDL_realloc( \ + arr, \ + sizeof(elementType) * capacity \ + ); \ } /* D3DCompile signature */ @@ -446,6 +439,7 @@ typedef struct D3D11TransferBuffer { uint8_t *data; uint32_t size; + SDL_atomic_t referenceCount; } D3D11TransferBuffer; typedef struct D3D11TransferBufferContainer @@ -511,6 +505,11 @@ typedef struct D3D11CommandBuffer D3D11UniformBuffer **boundUniformBuffers; uint32_t boundUniformBufferCount; uint32_t boundUniformBufferCapacity; + + /* Reference Counting */ + D3D11TransferBuffer **usedTransferBuffers; + uint32_t usedTransferBufferCount; + uint32_t usedTransferBufferCapacity; } D3D11CommandBuffer; typedef struct D3D11Sampler @@ -699,6 +698,7 @@ static void D3D11_DestroyDevice( D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i]; ID3D11DeviceContext_Release(commandBuffer->context); SDL_free(commandBuffer->boundUniformBuffers); + SDL_free(commandBuffer->usedTransferBuffers); SDL_free(commandBuffer); } SDL_free(renderer->availableCommandBuffers); @@ -1806,16 +1806,46 @@ static Refresh_GpuBuffer* D3D11_CreateGpuBuffer( return (Refresh_GpuBuffer*) d3d11Buffer; } -static Refresh_TransferBuffer* VULKAN_CreateTransferBuffer( +static void D3D11_INTERNAL_TrackTransferBuffer( + D3D11CommandBuffer *commandBuffer, + D3D11TransferBuffer *buffer +) { + EXPAND_ARRAY_IF_NEEDED( + commandBuffer->usedTransferBuffers, + D3D11TransferBuffer*, + commandBuffer->usedTransferBufferCount + 1, + commandBuffer->usedTransferBufferCapacity, + commandBuffer->boundUniformBufferCapacity * 2 + ); + + SDL_AtomicIncRef(&buffer->referenceCount); + + commandBuffer->usedTransferBuffers[ + commandBuffer->usedTransferBufferCount + ] = buffer; + commandBuffer->usedTransferBufferCount += 1; +} + +static D3D11TransferBuffer* D3D11_INTERNAL_CreateTransferBuffer( + uint32_t sizeInBytes +) { + D3D11TransferBuffer *transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); + + transferBuffer->data = SDL_malloc(sizeInBytes); + transferBuffer->size = sizeInBytes; + SDL_AtomicSet(&transferBuffer->referenceCount, 0); + + return transferBuffer; +} + +/* This actually returns a container handle so we can rotate buffers on Discard. */ +static Refresh_TransferBuffer* D3D11_CreateTransferBuffer( Refresh_Renderer *driverData, uint32_t sizeInBytes ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) (sizeof(D3D11TransferBufferContainer)); - D3D11TransferBuffer *transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); - - transferBuffer->data = SDL_malloc(sizeInBytes); - transferBuffer->size = sizeInBytes; + D3D11TransferBuffer *transferBuffer = D3D11_INTERNAL_CreateTransferBuffer(sizeInBytes); container->activeBuffer = transferBuffer; container->bufferCapacity = 1; @@ -1828,6 +1858,86 @@ static Refresh_TransferBuffer* VULKAN_CreateTransferBuffer( return (Refresh_TransferBuffer*) container; } +/* TransferBuffer Data */ + +static void D3D11_INTERNAL_DiscardActiveTransferBuffer( + D3D11TransferBufferContainer *container +) { + for (uint32_t i = 0; i < container->bufferCount; i += 1) + { + if (SDL_AtomicGet(&container->buffers[i]->referenceCount) == 0) + { + container->activeBuffer = container->buffers[i]; + return; + } + } + + container->activeBuffer = D3D11_INTERNAL_CreateTransferBuffer( + container->activeBuffer->size + ); + + EXPAND_ARRAY_IF_NEEDED( + container->buffers, + D3D11TransferBuffer*, + container->bufferCount + 1, + container->bufferCapacity, + container->bufferCapacity * 2 + ); + + container->buffers[ + container->bufferCapacity + ] = container->activeBuffer; + container->bufferCount += 1; +} + +static void D3D11_SetTransferData( + Refresh_Renderer *driverData, + void* data, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions transferOption +) { + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + D3D11TransferBuffer *buffer = container->activeBuffer; + + if ( + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0 + ) { + D3D11_INTERNAL_DiscardActiveTransferBuffer( + container + ); + } + + uint8_t *bufferPointer = + buffer->data + copyParams->dstOffset; + + SDL_memcpy( + bufferPointer, + ((uint8_t*) data) + copyParams->srcOffset, + copyParams->size + ); +} + +static void D3D11_GetTransferData( + Refresh_Renderer *driverData, + Refresh_TransferBuffer *transferBuffer, + void* data, + Refresh_BufferCopy *copyParams +) { + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + D3D11TransferBuffer *buffer = container->activeBuffer; + + uint8_t *bufferPointer = + buffer->data + copyParams->srcOffset; + + SDL_memcpy( + ((uint8_t*) data) + copyParams->dstOffset, + bufferPointer, + copyParams->size + ); +} + /* Copy Pass */ static void D3D11_BeginCopyPass( @@ -1882,6 +1992,8 @@ static void D3D11_UploadToTexture( copyParams->bufferStride * copyParams->bufferImageHeight, writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 ); + + D3D11_INTERNAL_TrackTransferBuffer(commandBuffer, d3d11TransferBuffer); } static void D3D11_UploadToBuffer( @@ -1908,6 +2020,8 @@ static void D3D11_UploadToBuffer( 1, writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 ); + + D3D11_INTERNAL_TrackTransferBuffer(commandBuffer, d3d11TransferBuffer); } static void D3D11_CopyTextureToTexture( @@ -2489,6 +2603,13 @@ static void D3D11_INTERNAL_AllocateCommandBuffers( commandBuffer->boundUniformBufferCapacity * sizeof(D3D11UniformBuffer*) ); + /* Reference Counting */ + commandBuffer->usedTransferBufferCapacity = 4; + commandBuffer->usedTransferBufferCount = 0; + commandBuffer->usedTransferBuffers = SDL_malloc( + commandBuffer->usedTransferBufferCapacity * sizeof(D3D11TransferBuffer*) + ); + renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; renderer->availableCommandBufferCount += 1; } @@ -3617,6 +3738,14 @@ static void D3D11_INTERNAL_CleanCommandBuffer( commandBuffer->boundUniformBufferCount = 0; + /* Reference Counting */ + + for (uint32_t i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) + { + SDL_AtomicDecRef(&commandBuffer->usedTransferBuffers[i]->referenceCount); + } + commandBuffer->usedTransferBufferCount = 0; + /* The fence is now available (unless SubmitAndAcquireFence was called) */ if (commandBuffer->autoReleaseFence) { -- 2.25.1 From 52ac3e1980605aaa8270fb27dc62b19f756ea171 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Mon, 4 Mar 2024 11:29:23 -0800 Subject: [PATCH 74/98] implementing some transfer structure --- src/Refresh_Driver_D3D11.c | 276 +++++++++++++++++++++++++++++++------ 1 file changed, 237 insertions(+), 39 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index d0f0a6b..8aecb82 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -437,8 +437,7 @@ typedef struct D3D11Buffer typedef struct D3D11TransferBuffer { - uint8_t *data; - uint32_t size; + D3D11Buffer buffer; SDL_atomic_t referenceCount; } D3D11TransferBuffer; @@ -1827,12 +1826,34 @@ static void D3D11_INTERNAL_TrackTransferBuffer( } static D3D11TransferBuffer* D3D11_INTERNAL_CreateTransferBuffer( + D3D11Renderer *renderer, uint32_t sizeInBytes ) { - D3D11TransferBuffer *transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); + D3D11TransferBuffer *transferBuffer; + D3D11_BUFFER_DESC bufferDesc; + ID3D11Buffer *bufferHandle; + HRESULT res; + + bufferDesc.ByteWidth = sizeInBytes; + bufferDesc.Usage = D3D11_USAGE_STAGING; + bufferDesc.BindFlags = 0; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + res = ID3D11Device_CreateBuffer( + renderer->device, + &bufferDesc, + NULL, + &bufferHandle + ); + ERROR_CHECK_RETURN("Could not create buffer", NULL); + + transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); + transferBuffer->buffer.handle = bufferHandle; + transferBuffer->buffer.size = sizeInBytes; + transferBuffer->buffer.uav = NULL; - transferBuffer->data = SDL_malloc(sizeInBytes); - transferBuffer->size = sizeInBytes; SDL_AtomicSet(&transferBuffer->referenceCount, 0); return transferBuffer; @@ -1845,7 +1866,7 @@ static Refresh_TransferBuffer* D3D11_CreateTransferBuffer( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) (sizeof(D3D11TransferBufferContainer)); - D3D11TransferBuffer *transferBuffer = D3D11_INTERNAL_CreateTransferBuffer(sizeInBytes); + D3D11TransferBuffer *transferBuffer = D3D11_INTERNAL_CreateTransferBuffer(renderer, sizeInBytes); container->activeBuffer = transferBuffer; container->bufferCapacity = 1; @@ -1861,6 +1882,7 @@ static Refresh_TransferBuffer* D3D11_CreateTransferBuffer( /* TransferBuffer Data */ static void D3D11_INTERNAL_DiscardActiveTransferBuffer( + D3D11Renderer *renderer, D3D11TransferBufferContainer *container ) { for (uint32_t i = 0; i < container->bufferCount; i += 1) @@ -1873,7 +1895,8 @@ static void D3D11_INTERNAL_DiscardActiveTransferBuffer( } container->activeBuffer = D3D11_INTERNAL_CreateTransferBuffer( - container->activeBuffer->size + renderer, + container->activeBuffer->buffer.size ); EXPAND_ARRAY_IF_NEEDED( @@ -1897,26 +1920,56 @@ static void D3D11_SetTransferData( Refresh_BufferCopy *copyParams, Refresh_TransferOptions transferOption ) { + D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *buffer = container->activeBuffer; + D3D11_MAPPED_SUBRESOURCE mappedSubresource; + HRESULT res; + /* Rotate the transfer buffer if necessary */ if ( transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0 ) { D3D11_INTERNAL_DiscardActiveTransferBuffer( + renderer, container ); + buffer = container->activeBuffer; + } + + res = ID3D11DeviceContext_Map( + renderer->immediateContext, + buffer->buffer.handle, + 0, + D3D11_MAP_WRITE, + D3D11_MAP_FLAG_DO_NOT_WAIT, + &mappedSubresource + ); + if (FAILED(res)) + { + D3D11_INTERNAL_LogError( + renderer->device, + "Failed to map transfer buffer for write!", + res + ); + return; } uint8_t *bufferPointer = - buffer->data + copyParams->dstOffset; + (uint8_t*) mappedSubresource.pData + copyParams->dstOffset; SDL_memcpy( bufferPointer, ((uint8_t*) data) + copyParams->srcOffset, copyParams->size ); + + ID3D11DeviceContext_Unmap( + renderer->immediateContext, + buffer->buffer.handle, + 0 + ); } static void D3D11_GetTransferData( @@ -1925,17 +1978,44 @@ static void D3D11_GetTransferData( void* data, Refresh_BufferCopy *copyParams ) { + D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *buffer = container->activeBuffer; + D3D11_MAPPED_SUBRESOURCE mappedSubresource; + HRESULT res; + + res = ID3D11DeviceContext_Map( + renderer->immediateContext, + buffer->buffer.handle, + 0, + D3D11_MAP_READ, + 0, + &mappedSubresource + ); + if (FAILED(res)) + { + D3D11_INTERNAL_LogError( + renderer->device, + "Failed to map transfer buffer for read!", + res + ); + return; + } uint8_t *bufferPointer = - buffer->data + copyParams->srcOffset; + (uint8_t*) mappedSubresource.pData + copyParams->srcOffset; SDL_memcpy( ((uint8_t*) data) + copyParams->dstOffset, bufferPointer, copyParams->size ); + + ID3D11DeviceContext_Unmap( + renderer->immediateContext, + buffer->buffer.handle, + 0 + ); } /* Copy Pass */ @@ -1955,10 +2035,13 @@ static void D3D11_UploadToTexture( Refresh_BufferImageCopy *copyParams, Refresh_WriteOptions writeOption ) { + D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Texture *d3d11Texture = (D3D11Texture*) textureRegion->textureSlice.texture; + D3D11_MAPPED_SUBRESOURCE mappedSubresource; + HRESULT res; int32_t w = textureRegion->w; int32_t h = textureRegion->h; @@ -1970,30 +2053,87 @@ static void D3D11_UploadToTexture( h = (h + blockSize - 1) & ~(blockSize - 1); } - D3D11_BOX dstBox; - dstBox.left = textureRegion->x; - dstBox.top = textureRegion->y; - dstBox.front = textureRegion->d; - dstBox.right = textureRegion->x + w; - dstBox.bottom = textureRegion->y + h; - dstBox.back = textureRegion->d + 1; + if ( + (copyParams->bufferStride == 0 || copyParams->bufferStride == BytesPerRow(w, d3d11Texture->format)) && + (copyParams->bufferImageHeight == 0 || copyParams->bufferImageHeight == h ) + ) { + /* Fast path */ + D3D11_BOX srcBox; + srcBox.left = copyParams->bufferOffset; + srcBox.top = 0; + srcBox.front = 0; + srcBox.right = copyParams->bufferOffset + BytesPerImage(w, h, d3d11Texture->format); + srcBox.bottom = 1; + srcBox.back = 1; - ID3D11DeviceContext1_UpdateSubresource1( - d3d11CommandBuffer->context, - d3d11Texture->handle, - D3D11_INTERNAL_CalcSubresource( - textureRegion->textureSlice.mipLevel, - textureRegion->textureSlice.layer, - 1 - ), - &dstBox, - d3d11TransferBuffer->data + copyParams->bufferOffset, - copyParams->bufferStride, - copyParams->bufferStride * copyParams->bufferImageHeight, - writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 - ); + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, + d3d11Texture->handle, + D3D11_INTERNAL_CalcSubresource( + textureRegion->textureSlice.mipLevel, + textureRegion->textureSlice.layer, + 1 + ), + textureRegion->x, + textureRegion->y, + textureRegion->z, + d3d11TransferBuffer->buffer.handle, + 0, + &srcBox, + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 + ); + } + else + { + D3D11_BOX dstBox; + dstBox.left = textureRegion->x; + dstBox.top = textureRegion->y; + dstBox.front = textureRegion->d; + dstBox.right = textureRegion->x + w; + dstBox.bottom = textureRegion->y + h; + dstBox.back = textureRegion->d + 1; - D3D11_INTERNAL_TrackTransferBuffer(commandBuffer, d3d11TransferBuffer); + res = ID3D11DeviceContext1_Map( + d3d11CommandBuffer->context, + d3d11TransferBuffer->buffer.handle, + 0, + D3D11_MAP_READ, + D3D11_MAP_FLAG_DO_NOT_WAIT, + &mappedSubresource + ); + if (FAILED(res)) + { + D3D11_INTERNAL_LogError( + renderer->device, + "Failed to map transfer buffer for read!", + res + ); + return; + } + + ID3D11DeviceContext1_UpdateSubresource1( + d3d11CommandBuffer->context, + d3d11Texture->handle, + D3D11_INTERNAL_CalcSubresource( + textureRegion->textureSlice.mipLevel, + textureRegion->textureSlice.layer, + 1 + ), + &dstBox, + (uint8_t*) mappedSubresource.pData + copyParams->bufferOffset, + copyParams->bufferStride, + copyParams->bufferStride * copyParams->bufferImageHeight, + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 + ); + + ID3D11DeviceContext1_Unmap( + renderer->immediateContext, + d3d11TransferBuffer->buffer.handle, + 0 + ); + } + + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); } static void D3D11_UploadToBuffer( @@ -2008,20 +2148,78 @@ static void D3D11_UploadToBuffer( D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; - D3D11_BOX dstBox = { copyParams->dstOffset, 0, 0, copyParams->dstOffset + copyParams->size, 1, 1 }; + D3D11_BOX srcBox = { copyParams->srcOffset, 0, 0, copyParams->srcOffset + copyParams->size, 1, 1 }; - ID3D11DeviceContext1_UpdateSubresource1( + ID3D11DeviceContext1_CopySubresourceRegion1( d3d11CommandBuffer->context, - (ID3D11Resource*) d3d11Buffer->handle, + d3d11Buffer->handle, 0, - &dstBox, - d3d11TransferBuffer->data + copyParams->dstOffset, - copyParams->size, - 1, + copyParams->dstOffset, + 0, + 0, + d3d11TransferBuffer->buffer.handle, + 0, + &srcBox, writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 ); - D3D11_INTERNAL_TrackTransferBuffer(commandBuffer, d3d11TransferBuffer); + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); +} + +static void D3D11_DownloadFromTexture( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TextureRegion *textureRegion, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions transferOption +) { + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + +} + +static void D3D11_DownloadFromBuffer( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_GpuBuffer *gpuBuffer, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions transferOption +) { + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; + D3D11_BOX srcBox = { copyParams->srcOffset, 0, 0, copyParams->srcOffset + copyParams->size, 1, 1 }; + + /* Rotate the transfer buffer if necessary */ + if ( + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0 + ) { + D3D11_INTERNAL_DiscardActiveTransferBuffer( + renderer, + container + ); + d3d11TransferBuffer = container->activeBuffer; + } + + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, + d3d11TransferBuffer->buffer.handle, + 0, + copyParams->dstOffset, + 0, + 0, + d3d11Buffer->handle, + 0, + &srcBox, + D3D11_COPY_NO_OVERWRITE + ); + + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); } static void D3D11_CopyTextureToTexture( -- 2.25.1 From 128bd1f5f0790fe9d8e9bf140170e3bf86c15924 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Mon, 4 Mar 2024 18:01:37 -0800 Subject: [PATCH 75/98] d3d11 copy pass implementation + filling in more APIs --- src/Refresh_Driver_D3D11.c | 514 +++++++++++++++++-------------------- 1 file changed, 241 insertions(+), 273 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 8aecb82..357a8df 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -437,7 +437,8 @@ typedef struct D3D11Buffer typedef struct D3D11TransferBuffer { - D3D11Buffer buffer; + uint8_t *data; + uint32_t size; SDL_atomic_t referenceCount; } D3D11TransferBuffer; @@ -1850,10 +1851,8 @@ static D3D11TransferBuffer* D3D11_INTERNAL_CreateTransferBuffer( ERROR_CHECK_RETURN("Could not create buffer", NULL); transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); - transferBuffer->buffer.handle = bufferHandle; - transferBuffer->buffer.size = sizeInBytes; - transferBuffer->buffer.uav = NULL; - + transferBuffer->data = (uint8_t*) SDL_malloc(sizeInBytes); + transferBuffer->size = sizeInBytes; SDL_AtomicSet(&transferBuffer->referenceCount, 0); return transferBuffer; @@ -1896,7 +1895,7 @@ static void D3D11_INTERNAL_DiscardActiveTransferBuffer( container->activeBuffer = D3D11_INTERNAL_CreateTransferBuffer( renderer, - container->activeBuffer->buffer.size + container->activeBuffer->size ); EXPAND_ARRAY_IF_NEEDED( @@ -1923,8 +1922,6 @@ static void D3D11_SetTransferData( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *buffer = container->activeBuffer; - D3D11_MAPPED_SUBRESOURCE mappedSubresource; - HRESULT res; /* Rotate the transfer buffer if necessary */ if ( @@ -1938,38 +1935,11 @@ static void D3D11_SetTransferData( buffer = container->activeBuffer; } - res = ID3D11DeviceContext_Map( - renderer->immediateContext, - buffer->buffer.handle, - 0, - D3D11_MAP_WRITE, - D3D11_MAP_FLAG_DO_NOT_WAIT, - &mappedSubresource - ); - if (FAILED(res)) - { - D3D11_INTERNAL_LogError( - renderer->device, - "Failed to map transfer buffer for write!", - res - ); - return; - } - - uint8_t *bufferPointer = - (uint8_t*) mappedSubresource.pData + copyParams->dstOffset; - SDL_memcpy( - bufferPointer, + (uint8_t*) buffer->data + copyParams->dstOffset, ((uint8_t*) data) + copyParams->srcOffset, copyParams->size ); - - ID3D11DeviceContext_Unmap( - renderer->immediateContext, - buffer->buffer.handle, - 0 - ); } static void D3D11_GetTransferData( @@ -1981,41 +1951,12 @@ static void D3D11_GetTransferData( D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *buffer = container->activeBuffer; - D3D11_MAPPED_SUBRESOURCE mappedSubresource; - HRESULT res; - - res = ID3D11DeviceContext_Map( - renderer->immediateContext, - buffer->buffer.handle, - 0, - D3D11_MAP_READ, - 0, - &mappedSubresource - ); - if (FAILED(res)) - { - D3D11_INTERNAL_LogError( - renderer->device, - "Failed to map transfer buffer for read!", - res - ); - return; - } - - uint8_t *bufferPointer = - (uint8_t*) mappedSubresource.pData + copyParams->srcOffset; SDL_memcpy( ((uint8_t*) data) + copyParams->dstOffset, - bufferPointer, + (uint8_t*) buffer->data + copyParams->srcOffset, copyParams->size ); - - ID3D11DeviceContext_Unmap( - renderer->immediateContext, - buffer->buffer.handle, - 0 - ); } /* Copy Pass */ @@ -2040,8 +1981,6 @@ static void D3D11_UploadToTexture( D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Texture *d3d11Texture = (D3D11Texture*) textureRegion->textureSlice.texture; - D3D11_MAPPED_SUBRESOURCE mappedSubresource; - HRESULT res; int32_t w = textureRegion->w; int32_t h = textureRegion->h; @@ -2053,85 +1992,28 @@ static void D3D11_UploadToTexture( h = (h + blockSize - 1) & ~(blockSize - 1); } - if ( - (copyParams->bufferStride == 0 || copyParams->bufferStride == BytesPerRow(w, d3d11Texture->format)) && - (copyParams->bufferImageHeight == 0 || copyParams->bufferImageHeight == h ) - ) { - /* Fast path */ - D3D11_BOX srcBox; - srcBox.left = copyParams->bufferOffset; - srcBox.top = 0; - srcBox.front = 0; - srcBox.right = copyParams->bufferOffset + BytesPerImage(w, h, d3d11Texture->format); - srcBox.bottom = 1; - srcBox.back = 1; + D3D11_BOX dstBox; + dstBox.left = textureRegion->x; + dstBox.top = textureRegion->y; + dstBox.front = textureRegion->d; + dstBox.right = textureRegion->x + w; + dstBox.bottom = textureRegion->y + h; + dstBox.back = textureRegion->d + 1; - ID3D11DeviceContext1_CopySubresourceRegion1( - d3d11CommandBuffer->context, - d3d11Texture->handle, - D3D11_INTERNAL_CalcSubresource( - textureRegion->textureSlice.mipLevel, - textureRegion->textureSlice.layer, - 1 - ), - textureRegion->x, - textureRegion->y, - textureRegion->z, - d3d11TransferBuffer->buffer.handle, - 0, - &srcBox, - writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 - ); - } - else - { - D3D11_BOX dstBox; - dstBox.left = textureRegion->x; - dstBox.top = textureRegion->y; - dstBox.front = textureRegion->d; - dstBox.right = textureRegion->x + w; - dstBox.bottom = textureRegion->y + h; - dstBox.back = textureRegion->d + 1; - - res = ID3D11DeviceContext1_Map( - d3d11CommandBuffer->context, - d3d11TransferBuffer->buffer.handle, - 0, - D3D11_MAP_READ, - D3D11_MAP_FLAG_DO_NOT_WAIT, - &mappedSubresource - ); - if (FAILED(res)) - { - D3D11_INTERNAL_LogError( - renderer->device, - "Failed to map transfer buffer for read!", - res - ); - return; - } - - ID3D11DeviceContext1_UpdateSubresource1( - d3d11CommandBuffer->context, - d3d11Texture->handle, - D3D11_INTERNAL_CalcSubresource( - textureRegion->textureSlice.mipLevel, - textureRegion->textureSlice.layer, - 1 - ), - &dstBox, - (uint8_t*) mappedSubresource.pData + copyParams->bufferOffset, - copyParams->bufferStride, - copyParams->bufferStride * copyParams->bufferImageHeight, - writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 - ); - - ID3D11DeviceContext1_Unmap( - renderer->immediateContext, - d3d11TransferBuffer->buffer.handle, - 0 - ); - } + ID3D11DeviceContext1_UpdateSubresource1( + d3d11CommandBuffer->context, + d3d11Texture->handle, + D3D11_INTERNAL_CalcSubresource( + textureRegion->textureSlice.mipLevel, + textureRegion->textureSlice.layer, + 1 + ), + &dstBox, + (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset, + copyParams->bufferStride, + copyParams->bufferStride * copyParams->bufferImageHeight, + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 + ); D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); } @@ -2157,7 +2039,7 @@ static void D3D11_UploadToBuffer( copyParams->dstOffset, 0, 0, - d3d11TransferBuffer->buffer.handle, + d3d11TransferBuffer->data, 0, &srcBox, writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 @@ -2176,7 +2058,94 @@ static void D3D11_DownloadFromTexture( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; + D3D11Texture *d3d11Texture = (D3D11Texture*) textureRegion->textureSlice.texture; + D3D11_TEXTURE2D_DESC stagingDesc; + ID3D11Resource *stagingTexture; + uint32_t subresourceIndex = D3D11_INTERNAL_CalcSubresource( + textureRegion->textureSlice.mipLevel, + textureRegion->textureSlice.layer, + d3d11Texture->levelCount + ); + int32_t formatSize = Texture_GetFormatSize(d3d11Texture->format); + D3D11_BOX srcBox = {textureRegion->x, textureRegion->y, textureRegion->z, textureRegion->x + textureRegion->w, textureRegion->y + textureRegion->h, 1}; + D3D11_MAPPED_SUBRESOURCE subresource; + HRESULT res; + /* Rotate the transfer buffer if necessary */ + if ( + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0 + ) { + D3D11_INTERNAL_DiscardActiveTransferBuffer( + renderer, + container + ); + d3d11TransferBuffer = container->activeBuffer; + } + + stagingDesc.Width = textureRegion->w; + stagingDesc.Height = textureRegion->h; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = RefreshToD3D11_TextureFormat[d3d11Texture->format]; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + res = ID3D11Device_CreateTexture2D( + renderer->device, + &stagingDesc, + NULL, + (ID3D11Texture2D**) &stagingTexture + ); + ERROR_CHECK_RETURN("Staging texture creation failed",) + + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, + stagingTexture, + 0, + 0, + 0, + 0, + d3d11Texture->handle, + subresourceIndex, + &srcBox, + D3D11_COPY_NO_OVERWRITE + ); + + /* Read from the staging texture */ + res = ID3D11DeviceContext1_Map( + d3d11CommandBuffer->context, + stagingTexture, + subresourceIndex, + D3D11_MAP_READ, + 0, + &subresource + ); + ERROR_CHECK_RETURN("Could not map texture for reading",) + + uint8_t* dataPtr = (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset; + for (int32_t row = textureRegion->y; row < copyParams->bufferImageHeight; row += 1) + { + SDL_memcpy( + dataPtr, + (uint8_t*) subresource.pData + (row * copyParams->bufferStride) + (textureRegion->x * formatSize), + textureRegion->w * formatSize + ); + } + + ID3D11DeviceContext1_Unmap( + d3d11CommandBuffer->context, + stagingTexture, + 0 + ); + + ID3D11Texture2D_Release(stagingTexture); } static void D3D11_DownloadFromBuffer( @@ -2192,7 +2161,11 @@ static void D3D11_DownloadFromBuffer( D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; - D3D11_BOX srcBox = { copyParams->srcOffset, 0, 0, copyParams->srcOffset + copyParams->size, 1, 1 }; + D3D11_BOX srcBox = { copyParams->srcOffset, 0, 0, copyParams->size, 1, 1 }; + ID3D11Resource *stagingBuffer; + D3D11_MAPPED_SUBRESOURCE mappedSubresource; + D3D11_BUFFER_DESC stagingBufferDesc; + HRESULT res; /* Rotate the transfer buffer if necessary */ if ( @@ -2206,90 +2179,8 @@ static void D3D11_DownloadFromBuffer( d3d11TransferBuffer = container->activeBuffer; } - ID3D11DeviceContext1_CopySubresourceRegion1( - d3d11CommandBuffer->context, - d3d11TransferBuffer->buffer.handle, - 0, - copyParams->dstOffset, - 0, - 0, - d3d11Buffer->handle, - 0, - &srcBox, - D3D11_COPY_NO_OVERWRITE - ); - - D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); -} - -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_EndCopyPass( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer -) { - /* no-op */ -} - -/* Buffer Data */ - -static void D3D11_SetBufferData( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer *buffer, - uint32_t offsetInBytes, - void* data, - uint32_t dataLength -) { - 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, - 1, - dataLength == d3d11Buffer->size ? D3D11_COPY_DISCARD : 0 - ); -} - -static void D3D11_GetBufferData( - Refresh_Renderer *driverData, - Refresh_Buffer *buffer, - void* data, - uint32_t dataLengthInBytes -) { - 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.ByteWidth = copyParams->size; stagingBufferDesc.Usage = D3D11_USAGE_STAGING; stagingBufferDesc.BindFlags = 0; stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; @@ -2304,23 +2195,22 @@ 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, + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, stagingBuffer, 0, 0, 0, 0, - (ID3D11Resource*) d3d11Buffer->handle, + d3d11Buffer->handle, 0, - &srcBox + &srcBox, + D3D11_COPY_NO_OVERWRITE ); /* Read from the staging buffer */ - res = ID3D11DeviceContext_Map( - renderer->immediateContext, + res = ID3D11DeviceContext1_Map( + d3d11CommandBuffer->context, stagingBuffer, 0, D3D11_MAP_READ, @@ -2335,21 +2225,95 @@ static void D3D11_GetBufferData( res ); ID3D11Buffer_Release(stagingBuffer); - SDL_UnlockMutex(renderer->contextLock); return; } - SDL_memcpy(data, mappedSubresource.pData, dataLengthInBytes); + SDL_memcpy( + d3d11TransferBuffer->data + copyParams->dstOffset, + mappedSubresource.pData, + copyParams->size + ); - ID3D11DeviceContext_Unmap( - renderer->immediateContext, + ID3D11DeviceContext1_Unmap( + d3d11CommandBuffer->context, stagingBuffer, 0 ); - SDL_UnlockMutex(renderer->contextLock); + + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); /* Clean up the staging buffer */ - ID3D11Resource_Release(stagingBuffer); + ID3D11Buffer_Release(stagingBuffer); +} + +static void D3D11_CopyTextureToTexture( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TextureRegion *source, + Refresh_TextureRegion *destination, + Refresh_WriteOptions writeOption +) { + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Texture *srcTexture = source->textureSlice.texture; + uint32_t srcSubresourceIndex = D3D11_INTERNAL_CalcSubresource( + source->textureSlice.mipLevel, + source->textureSlice.layer, + srcTexture->levelCount + ); + D3D11Texture *dstTexture = destination->textureSlice.texture; + uint32_t dstSubresourceIndex = D3D11_INTERNAL_CalcSubresource( + destination->textureSlice.mipLevel, + destination->textureSlice.layer, + dstTexture->levelCount + ); + D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + source->w, source->y + source->w, 1 }; + + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, + dstTexture->handle, + dstSubresourceIndex, + destination->x, + destination->y, + destination->z, + srcTexture->handle, + srcSubresourceIndex, + &srcBox, + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 + ); +} + +static void D3D11_CopyBufferToBuffer( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_GpuBuffer *source, + Refresh_GpuBuffer *destination, + Refresh_BufferCopy *copyParams, + Refresh_WriteOptions writeOption +) { + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Buffer *srcBuffer = (D3D11Buffer*) source; + D3D11Buffer *dstBuffer = (D3D11Buffer*) destination; + D3D11_BOX srcBox = { copyParams->srcOffset, 0, 0, copyParams->srcOffset + copyParams->size, 1, 1 }; + + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, + dstBuffer->handle, + 0, + copyParams->dstOffset, + 0, + 0, + srcBuffer->handle, + 0, + &srcBox, + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 + ); +} + +static void D3D11_EndCopyPass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + /* no-op */ } /* Uniforms */ @@ -2701,11 +2665,11 @@ static void D3D11_QueueDestroySampler( SDL_free(d3d11Sampler); } -static void D3D11_QueueDestroyBuffer( +static void D3D11_QueueDestroyGpuBuffer( Refresh_Renderer *driverData, - Refresh_Buffer *buffer + Refresh_GpuBuffer *gpuBuffer ) { - D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; if (d3d11Buffer->uav) { @@ -2932,22 +2896,23 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( D3D11Renderer *renderer, Refresh_ColorAttachmentInfo *info ) { - D3D11Texture *texture = (D3D11Texture*) info->texture; + D3D11Texture *texture = (D3D11Texture*) info->textureSlice.texture; D3D11TargetView *targetView; uint8_t isMultisample = texture->msaaHandle != NULL; D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; ID3D11RenderTargetView *rtv; HRESULT res; + /* FIXME: what about 3D textures */ /* 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 ) - { + if ( + targetView->layer == info->textureSlice.layer && + targetView->level == info->textureSlice.mipLevel + ) { return (ID3D11RenderTargetView*) targetView->view; } } @@ -2957,16 +2922,16 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( if (texture->isCube && !isMultisample) { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.FirstArraySlice = info->layer; + rtvDesc.Texture2DArray.FirstArraySlice = info->textureSlice.layer; rtvDesc.Texture2DArray.ArraySize = 1; - rtvDesc.Texture2DArray.MipSlice = info->level; + rtvDesc.Texture2DArray.MipSlice = info->textureSlice.mipLevel; } 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; + rtvDesc.Texture3D.MipSlice = info->textureSlice.mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = texture->depth; } else { @@ -2977,7 +2942,7 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( else { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = info->level; + rtvDesc.Texture2D.MipSlice = info->textureSlice.mipLevel; } } @@ -3001,8 +2966,8 @@ static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( targetView = &texture->targetViews[texture->targetViewCount]; targetView->depth = info->depth; - targetView->layer = info->layer; - targetView->level = info->level; + targetView->layer = info->textureSlice.layer; + targetView->level = info->textureSlice.mipLevel; targetView->view = (ID3D11View*) rtv; texture->targetViewCount += 1; @@ -3401,16 +3366,17 @@ static void D3D11_BindVertexBuffers( Refresh_CommandBuffer *commandBuffer, uint32_t firstBinding, uint32_t bindingCount, - Refresh_Buffer **pBuffers, - uint64_t *pOffsets + Refresh_BufferBinding *pBindings ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; ID3D11Buffer *bufferHandles[MAX_BUFFER_BINDINGS]; + UINT bufferOffsets[MAX_BUFFER_BINDINGS]; for (uint32_t i = 0; i < bindingCount; i += 1) { - bufferHandles[i] = ((D3D11Buffer*) pBuffers[i])->handle; + bufferHandles[i] = ((D3D11Buffer*) pBindings[i].gpuBuffer)->handle; + bufferOffsets[i] = pBindings[i].offset; } ID3D11DeviceContext_IASetVertexBuffers( @@ -3419,26 +3385,25 @@ static void D3D11_BindVertexBuffers( bindingCount, bufferHandles, &d3d11CommandBuffer->graphicsPipeline->vertexStrides[firstBinding], - (UINT*) pOffsets + bufferOffsets ); } static void D3D11_BindIndexBuffer( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer *buffer, - uint64_t offset, + Refresh_BufferBinding *pBinding, Refresh_IndexElementSize indexElementSize ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - D3D11Buffer *d3d11Buffer = (D3D11Buffer*) buffer; + D3D11Buffer *d3d11Buffer = (D3D11Buffer*) pBinding->gpuBuffer; ID3D11DeviceContext_IASetIndexBuffer( d3d11CommandBuffer->context, d3d11Buffer->handle, RefreshToD3D11_IndexType[indexElementSize], - (UINT) offset + (UINT) pBinding->offset ); } @@ -3477,10 +3442,11 @@ static void D3D11_BindComputePipeline( ); } +/* D3D11 can't discard when setting a UAV, so just ignore writeOption */ static void D3D11_BindComputeBuffers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer **pBuffers + Refresh_ComputeBufferBinding *pBindings ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; @@ -3490,7 +3456,7 @@ static void D3D11_BindComputeBuffers( for (int32_t i = 0; i < numBuffers; i += 1) { - uavs[i] = ((D3D11Buffer*) pBuffers[i])->uav; + uavs[i] = ((D3D11Buffer*) pBindings[i].gpuBuffer)->uav; } ID3D11DeviceContext_CSSetUnorderedAccessViews( @@ -3502,10 +3468,12 @@ static void D3D11_BindComputeBuffers( ); } +/* FIXME: need to pre-generate UAVs per subresource */ +/* D3D11 can't discard when setting a UAV, so just ignore writeOption */ static void D3D11_BindComputeTextures( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures + Refresh_ComputeTextureBinding *pBindings ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; @@ -3515,7 +3483,7 @@ static void D3D11_BindComputeTextures( for (int32_t i = 0; i < numTextures; i += 1) { - uavs[i] = ((D3D11Texture*) pTextures[i])->unorderedAccessView; + uavs[i] = ((D3D11Texture*) pBindings[i].textureSlice.texture)->unorderedAccessView; } ID3D11DeviceContext_CSSetUnorderedAccessViews( -- 2.25.1 From 5c84debb50a8cacef9ff33ff227fe31c009843ce Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 12:27:38 -0800 Subject: [PATCH 76/98] implement d3d11 subresource tracking --- src/Refresh_Driver_D3D11.c | 545 +++++++++++++++---------------------- 1 file changed, 227 insertions(+), 318 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 357a8df..ba83d8e 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -348,25 +348,22 @@ static D3D11_FILTER RefreshToD3D11_Filter(Refresh_SamplerStateCreateInfo *create /* Structs */ -typedef struct D3D11TargetView +typedef struct D3D11TextureSubresource { - ID3D11View *view; /* ID3D11RenderTargetView* or ID3D11DepthStencilView* */ + ID3D11View *targetView; /* can be NULL if not a target */ + ID3D11UnorderedAccessView *uav; /* can be NULL if not used in compute */ + ID3D11Resource *msaaHandle; /* can be NULL if not using MSAA */ uint32_t level; - uint32_t depth; uint32_t layer; -} D3D11TargetView; +} D3D11TextureSubresource; typedef struct D3D11Texture { /* D3D Handles */ ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ ID3D11ShaderResourceView *shaderView; - ID3D11Resource *msaaHandle; - ID3D11UnorderedAccessView *unorderedAccessView; /* API FIXME: This needs to be a dynamic array! */ - D3D11TargetView *targetViews; - uint32_t targetViewCount; - uint32_t targetViewCapacity; + D3D11TextureSubresource *subresources; /* count is layerCount * levelCount */ /* Basic Info */ Refresh_TextureFormat format; @@ -374,6 +371,7 @@ typedef struct D3D11Texture uint32_t height; uint32_t depth; uint32_t levelCount; + uint32_t layerCount; uint8_t isCube; uint8_t isRenderTarget; } D3D11Texture; @@ -469,14 +467,6 @@ typedef struct D3D11Fence ID3D11Query *handle; } D3D11Fence; -typedef struct D3D11TargetBinding -{ - D3D11Texture *texture; - uint32_t layer; -} D3D11TargetBinding; - -static const D3D11TargetBinding NullTargetBinding = { NULL, 0 }; - typedef struct D3D11CommandBuffer { /* Deferred Context */ @@ -486,10 +476,13 @@ typedef struct D3D11CommandBuffer D3D11WindowData *windowData; /* Render Pass */ - D3D11TargetBinding colorTargets[MAX_COLOR_TARGET_BINDINGS]; - D3D11TargetBinding depthStencilTarget; D3D11GraphicsPipeline *graphicsPipeline; + /* Render Pass MSAA resolve */ + D3D11Texture *colorTargetResolveTexture[MAX_COLOR_TARGET_BINDINGS]; + uint32_t colorTargetResolveSubresourceIndex[MAX_COLOR_TARGET_BINDINGS]; + ID3D11Resource *colorTargetMsaaHandle[MAX_COLOR_TARGET_BINDINGS]; + /* Compute Pass */ D3D11ComputePipeline *computePipeline; @@ -506,7 +499,7 @@ typedef struct D3D11CommandBuffer uint32_t boundUniformBufferCount; uint32_t boundUniformBufferCapacity; - /* Reference Counting */ + /* Transfer Reference Counting */ D3D11TransferBuffer **usedTransferBuffers; uint32_t usedTransferBufferCount; uint32_t usedTransferBufferCapacity; @@ -1460,7 +1453,6 @@ static Refresh_Texture* D3D11_CreateTexture( ID3D11Resource *textureHandle; ID3D11Resource *msaaHandle = NULL; ID3D11ShaderResourceView *srv = NULL; - ID3D11UnorderedAccessView *uav = NULL; D3D11Texture *d3d11Texture; HRESULT res; @@ -1500,7 +1492,7 @@ static Refresh_Texture* D3D11_CreateTexture( desc2D.Width = textureCreateInfo->width; desc2D.Height = textureCreateInfo->height; - desc2D.ArraySize = textureCreateInfo->isCube ? 6 : 1; + desc2D.ArraySize = textureCreateInfo->isCube ? 6 : textureCreateInfo->layerCount; desc2D.CPUAccessFlags = 0; desc2D.Format = format; desc2D.MipLevels = textureCreateInfo->levelCount; @@ -1549,64 +1541,6 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } - - /* 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; - - 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; - } - } - - /* 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 { @@ -1648,7 +1582,7 @@ static Refresh_Texture* D3D11_CreateTexture( { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = format; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE3D; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; srvDesc.Texture3D.MipLevels = desc3D.MipLevels; srvDesc.Texture3D.MostDetailedMip = 0; @@ -1665,62 +1599,163 @@ static Refresh_Texture* D3D11_CreateTexture( return NULL; } } - - /* 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; - uavDesc.Texture3D.FirstWSlice = 0; - uavDesc.Texture3D.WSize = -1; - - 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; - } - } } d3d11Texture = (D3D11Texture*) SDL_malloc(sizeof(D3D11Texture)); d3d11Texture->handle = textureHandle; - d3d11Texture->msaaHandle = msaaHandle; d3d11Texture->format = textureCreateInfo->format; d3d11Texture->width = textureCreateInfo->width; d3d11Texture->height = textureCreateInfo->height; d3d11Texture->depth = textureCreateInfo->depth; d3d11Texture->levelCount = textureCreateInfo->levelCount; + d3d11Texture->layerCount = textureCreateInfo->layerCount; d3d11Texture->isCube = textureCreateInfo->isCube; d3d11Texture->isRenderTarget = isColorTarget | isDepthStencil; d3d11Texture->shaderView = srv; - d3d11Texture->unorderedAccessView = uav; - d3d11Texture->targetViewCount = 0; - if (d3d11Texture->isRenderTarget) + d3d11Texture->subresources = SDL_malloc( + d3d11Texture->levelCount * d3d11Texture->layerCount * sizeof(D3D11TextureSubresource) + ); + + for (uint32_t layerIndex = 0; layerIndex < d3d11Texture->layerCount; layerIndex += 1) { - d3d11Texture->targetViewCapacity = d3d11Texture->isCube ? 6 : 1; - d3d11Texture->targetViews = SDL_malloc( - sizeof(D3D11TargetView) * d3d11Texture->targetViewCapacity - ); - } - else - { - d3d11Texture->targetViewCapacity = 0; - d3d11Texture->targetViews = NULL; + for (uint32_t levelIndex = 0; levelIndex < d3d11Texture->levelCount; levelIndex += 1) + { + uint32_t subresourceIndex = D3D11_INTERNAL_CalcSubresource( + levelIndex, + layerIndex, + d3d11Texture->levelCount + ); + + d3d11Texture->subresources[subresourceIndex].layer = layerIndex; + d3d11Texture->subresources[subresourceIndex].level = levelIndex; + + if (isMultisample) + { + D3D11_TEXTURE2D_DESC desc2D; + + 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**) &d3d11Texture->subresources[subresourceIndex].msaaHandle + ); + ERROR_CHECK_RETURN("Could not create MSAA texture!", NULL); + } + else + { + d3d11Texture->subresources[subresourceIndex].msaaHandle = NULL; + } + + if (d3d11Texture->isRenderTarget) + { + if (isDepthStencil) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + + dsvDesc.Format = format; + dsvDesc.Flags = 0; + + if (isMultisample) + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = levelIndex; + } + + res = ID3D11Device_CreateDepthStencilView( + renderer->device, + isMultisample ? d3d11Texture->subresources[subresourceIndex].msaaHandle : d3d11Texture->handle, + &dsvDesc, + &d3d11Texture->subresources[subresourceIndex].targetView + ); + ERROR_CHECK_RETURN("Could not create DSV!", NULL); + } + else + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + + if (d3d11Texture->layerCount > 1) + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = levelIndex; + rtvDesc.Texture2DArray.FirstArraySlice = layerIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + } + else if (d3d11Texture->depth > 1) + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = levelIndex; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = d3d11Texture->depth; + } + else + { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = levelIndex; + } + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + d3d11Texture->handle, + &rtvDesc, + &d3d11Texture->subresources[subresourceIndex].targetView + ); + ERROR_CHECK_RETURN("Could not create RTV!", NULL); + } + } + else + { + d3d11Texture->subresources[subresourceIndex].targetView = NULL; + } + + if (isCompute) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.Format = format; + + if (d3d11Texture->layerCount > 1) + { + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; + uavDesc.Texture2DArray.MipSlice = levelIndex; + uavDesc.Texture2DArray.FirstArraySlice = layerIndex; + uavDesc.Texture2DArray.ArraySize = 1; + } + else if (d3d11Texture->depth > 1) + { + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; + uavDesc.Texture3D.MipSlice = levelIndex; + uavDesc.Texture3D.FirstWSlice = 0; + uavDesc.Texture3D.WSize = d3d11Texture->layerCount; + } + else + { + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = levelIndex; + } + + res = ID3D11Device_CreateUnorderedAccessView( + renderer->device, + d3d11Texture->handle, + &uavDesc, + &d3d11Texture->subresources[subresourceIndex].uav + ); + ERROR_CHECK_RETURN("Could not create UAV!", NULL); + } + else + { + d3d11Texture->subresources[subresourceIndex].uav = NULL; + } + } } return (Refresh_Texture*) d3d11Texture; @@ -2634,22 +2669,34 @@ static void D3D11_QueueDestroyTexture( { ID3D11ShaderResourceView_Release(d3d11Texture->shaderView); } - if (d3d11Texture->unorderedAccessView) + + for (uint32_t layerIndex = 0; layerIndex < d3d11Texture->layerCount; layerIndex += 1) { - ID3D11UnorderedAccessView_Release(d3d11Texture->unorderedAccessView); - } - if (d3d11Texture->targetViewCount > 0) - { - for (uint32_t i = 0; i < d3d11Texture->targetViewCount; i += 1) + for (uint32_t levelIndex = 0; levelIndex < d3d11Texture->levelCount; levelIndex += 1) { - ID3D11View_Release(d3d11Texture->targetViews[i].view); + uint32_t subresourceIndex = D3D11_INTERNAL_CalcSubresource( + levelIndex, + layerIndex, + d3d11Texture->levelCount + ); + + if (d3d11Texture->subresources[subresourceIndex].msaaHandle != NULL) + { + ID3D11Resource_Release(d3d11Texture->subresources[subresourceIndex].msaaHandle); + } + + if (d3d11Texture->subresources[subresourceIndex].targetView != NULL) + { + ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].targetView); + } + + if (d3d11Texture->subresources[subresourceIndex].uav != NULL) + { + ID3D11UnorderedAccessView_Release(d3d11Texture->subresources[subresourceIndex].uav); + } } - SDL_free(d3d11Texture->targetViews); - } - if (d3d11Texture->msaaHandle) - { - ID3D11Resource_Release(d3d11Texture->msaaHandle); } + SDL_free(d3d11Texture->subresources); ID3D11Resource_Release(d3d11Texture->handle); @@ -2880,9 +2927,10 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( commandBuffer->computeUniformBuffer = NULL; for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { - commandBuffer->colorTargets[i] = NullTargetBinding; + commandBuffer->colorTargetResolveTexture[i] = NULL; + commandBuffer->colorTargetResolveSubresourceIndex[i] = 0; + commandBuffer->colorTargetMsaaHandle[i] = NULL; } - commandBuffer->depthStencilTarget = NullTargetBinding; D3D11_INTERNAL_AcquireFence(renderer, commandBuffer); commandBuffer->autoReleaseFence = 1; @@ -2892,155 +2940,6 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( return (Refresh_CommandBuffer*) commandBuffer; } -static ID3D11RenderTargetView* D3D11_INTERNAL_FetchRTV( - D3D11Renderer *renderer, - Refresh_ColorAttachmentInfo *info -) { - D3D11Texture *texture = (D3D11Texture*) info->textureSlice.texture; - D3D11TargetView *targetView; - uint8_t isMultisample = texture->msaaHandle != NULL; - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - ID3D11RenderTargetView *rtv; - HRESULT res; - - /* FIXME: what about 3D textures */ - /* Does this target already exist? */ - for (uint32_t i = 0; i < texture->targetViewCount; i += 1) - { - targetView = &texture->targetViews[i]; - - if ( - targetView->layer == info->textureSlice.layer && - targetView->level == info->textureSlice.mipLevel - ) { - return (ID3D11RenderTargetView*) targetView->view; - } - } - - /* Let's create a new RTV! */ - rtvDesc.Format = RefreshToD3D11_TextureFormat[texture->format]; - if (texture->isCube && !isMultisample) - { - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.FirstArraySlice = info->textureSlice.layer; - rtvDesc.Texture2DArray.ArraySize = 1; - rtvDesc.Texture2DArray.MipSlice = info->textureSlice.mipLevel; - } - else if (texture->depth > 1) - { - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = info->textureSlice.mipLevel; - rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = texture->depth; - } - else - { - if (isMultisample) - { - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; - } - else - { - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = info->textureSlice.mipLevel; - } - } - - res = ID3D11Device_CreateRenderTargetView( - renderer->device, - isMultisample ? texture->msaaHandle : 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->textureSlice.layer; - targetView->level = info->textureSlice.mipLevel; - targetView->view = (ID3D11View*) rtv; - - texture->targetViewCount += 1; - - return rtv; -} - -static ID3D11DepthStencilView* D3D11_INTERNAL_FetchDSV( - D3D11Renderer* renderer, - Refresh_DepthStencilAttachmentInfo* info -) { - D3D11Texture *texture = (D3D11Texture*) info->texture; - D3D11TargetView *targetView; - uint8_t isMultisample = texture->msaaHandle != NULL; - 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 (isMultisample) - { - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; - } - else - { - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = info->level; - } - - res = ID3D11Device_CreateDepthStencilView( - renderer->device, - isMultisample ? texture->msaaHandle : 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, @@ -3060,32 +2959,43 @@ static void D3D11_BeginRenderPass( /* Clear the bound targets for the current command buffer */ for (uint32_t i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { - d3d11CommandBuffer->colorTargets[i] = NullTargetBinding; + d3d11CommandBuffer->colorTargetResolveTexture[i] = NULL; + d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = 0; + d3d11CommandBuffer->colorTargetMsaaHandle[i] = NULL; } - d3d11CommandBuffer->depthStencilTarget = NullTargetBinding; /* Set up the new color target bindings */ for (uint32_t i = 0; i < colorAttachmentCount; i += 1) { - d3d11CommandBuffer->colorTargets[i].texture = (D3D11Texture*) colorAttachmentInfos[i].texture; - d3d11CommandBuffer->colorTargets[i].layer = colorAttachmentInfos[i].layer; + D3D11Texture *texture = (D3D11Texture*) colorAttachmentInfos[i].textureSlice.texture; - rtvs[i] = D3D11_INTERNAL_FetchRTV( - renderer, - &colorAttachmentInfos[i] + uint32_t subresourceIndex = D3D11_INTERNAL_CalcSubresource( + colorAttachmentInfos[i].textureSlice.mipLevel, + colorAttachmentInfos[i].textureSlice.layer, + texture->levelCount ); + rtvs[i] = texture->subresources[subresourceIndex].targetView; + + if (texture->subresources[subresourceIndex].msaaHandle != NULL) + { + d3d11CommandBuffer->colorTargetResolveTexture[i] = texture; + d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = subresourceIndex; + d3d11CommandBuffer->colorTargetMsaaHandle[i] = texture->subresources[subresourceIndex].msaaHandle; + } } /* Get the DSV for the depth stencil attachment, if applicable */ if (depthStencilAttachmentInfo != NULL) { - d3d11CommandBuffer->depthStencilTarget.texture = (D3D11Texture*) depthStencilAttachmentInfo->texture; - d3d11CommandBuffer->depthStencilTarget.layer = depthStencilAttachmentInfo->layer; + D3D11Texture *texture = (D3D11Texture*) depthStencilAttachmentInfo->textureSlice.texture; - dsv = D3D11_INTERNAL_FetchDSV( - renderer, - depthStencilAttachmentInfo + uint32_t subresourceIndex = D3D11_INTERNAL_CalcSubresource( + depthStencilAttachmentInfo->textureSlice.mipLevel, + depthStencilAttachmentInfo->textureSlice.layer, + texture->levelCount ); + + dsv = texture->subresources[subresourceIndex].targetView; } /* Actually set the RTs */ @@ -3143,9 +3053,9 @@ 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; + D3D11Texture *texture = (D3D11Texture*) colorAttachmentInfos[i].textureSlice.texture; + uint32_t w = texture->width >> colorAttachmentInfos[i].textureSlice.mipLevel; + uint32_t h = texture->height >> colorAttachmentInfos[i].textureSlice.mipLevel; if (w < vpWidth) { @@ -3160,9 +3070,9 @@ static void D3D11_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - D3D11Texture *texture = (D3D11Texture*) depthStencilAttachmentInfo->texture; - uint32_t w = texture->width >> depthStencilAttachmentInfo->level; - uint32_t h = texture->height >> depthStencilAttachmentInfo->level; + D3D11Texture *texture = (D3D11Texture*) depthStencilAttachmentInfo->textureSlice.texture; + uint32_t w = texture->width >> depthStencilAttachmentInfo->textureSlice.mipLevel; + uint32_t h = texture->height >> depthStencilAttachmentInfo->textureSlice.mipLevel; if (w < vpWidth) { @@ -3214,22 +3124,15 @@ static void D3D11_EndRenderPass( /* 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) + if (d3d11CommandBuffer->colorTargetMsaaHandle[i] != NULL) { - uint32_t subresource = D3D11_INTERNAL_CalcSubresource( - 0, /* FIXME: This should probably the color target's mip level */ - d3d11CommandBuffer->colorTargets[i].layer, - texture->levelCount - ); - ID3D11DeviceContext_ResolveSubresource( d3d11CommandBuffer->context, - texture->handle, - subresource, - texture->msaaHandle, + d3d11CommandBuffer->colorTargetResolveTexture[i]->handle, + d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i], + d3d11CommandBuffer->colorTargetMsaaHandle[i], 0, - RefreshToD3D11_TextureFormat[texture->format] + RefreshToD3D11_TextureFormat[d3d11CommandBuffer->colorTargetResolveTexture[i]->format] ); } } @@ -3468,7 +3371,6 @@ static void D3D11_BindComputeBuffers( ); } -/* FIXME: need to pre-generate UAVs per subresource */ /* D3D11 can't discard when setting a UAV, so just ignore writeOption */ static void D3D11_BindComputeTextures( Refresh_Renderer *driverData, @@ -3483,7 +3385,14 @@ static void D3D11_BindComputeTextures( for (int32_t i = 0; i < numTextures; i += 1) { - uavs[i] = ((D3D11Texture*) pBindings[i].textureSlice.texture)->unorderedAccessView; + D3D11Texture *texture = ((D3D11Texture*) pBindings[i].textureSlice.texture); + uint32_t subresourceIndex = D3D11_INTERNAL_CalcSubresource( + pBindings[i].textureSlice.mipLevel, + pBindings[i].textureSlice.layer, + texture->levelCount + ); + + uavs[i] = texture->subresources[subresourceIndex].uav; } ID3D11DeviceContext_CSSetUnorderedAccessViews( -- 2.25.1 From 5ed41a7de226fa7b7d689d339904d6157a0ba3b7 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 14:55:53 -0800 Subject: [PATCH 77/98] fill in a bit more d3d11 behavior --- include/Refresh.h | 20 ------- src/Refresh.c | 38 ------------- src/Refresh_Driver.h | 20 ------- src/Refresh_Driver_D3D11.c | 111 ++++++++++++++++++++++++++----------- 4 files changed, 78 insertions(+), 111 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index feb22d8..4e3b722 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -1260,26 +1260,6 @@ REFRESHAPI void Refresh_CopyTextureToTexture( Refresh_WriteOptions writeOption ); -/* Copies image data from a texture slice into a buffer. */ -REFRESHAPI void Refresh_CopyTextureToBuffer( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParams, - Refresh_WriteOptions writeOption -); - -/* Copies data from a buffer to a texture slice. */ -REFRESHAPI void Refresh_CopyBufferToTexture( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_BufferImageCopy *copyParams, - Refresh_WriteOptions writeOption -); - /* Copies data from a buffer to a buffer. */ REFRESHAPI void Refresh_CopyBufferToBuffer( Refresh_Device *device, diff --git a/src/Refresh.c b/src/Refresh.c index c3b0fbe..267f47d 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -879,44 +879,6 @@ void Refresh_CopyTextureToTexture( ); } -void Refresh_CopyTextureToBuffer( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParameters, - Refresh_WriteOptions writeOption -) { - NULL_RETURN(device); - device->CopyTextureToBuffer( - device->driverData, - commandBuffer, - textureRegion, - gpuBuffer, - copyParameters, - writeOption - ); -} - -void Refresh_CopyBufferToTexture( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_BufferImageCopy *copyParams, - Refresh_WriteOptions writeOption -) { - NULL_RETURN(device); - device->CopyBufferToTexture( - device->driverData, - commandBuffer, - gpuBuffer, - textureRegion, - copyParams, - writeOption - ); -} - void Refresh_CopyBufferToBuffer( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index f1cf090..18d0785 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -532,24 +532,6 @@ struct Refresh_Device Refresh_WriteOptions writeOption ); - void (*CopyTextureToBuffer)( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureSlice, - Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParams, - Refresh_WriteOptions writeOption - ); - - void (*CopyBufferToTexture)( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureRegion *textureSlice, - Refresh_BufferImageCopy *copyParams, - Refresh_WriteOptions writeOption - ); - void (*CopyBufferToBuffer)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -689,8 +671,6 @@ struct Refresh_Device ASSIGN_DRIVER_FUNC(DownloadFromTexture, name) \ ASSIGN_DRIVER_FUNC(DownloadFromBuffer, name) \ ASSIGN_DRIVER_FUNC(CopyTextureToTexture, name) \ - ASSIGN_DRIVER_FUNC(CopyTextureToBuffer, name) \ - ASSIGN_DRIVER_FUNC(CopyBufferToTexture, name) \ ASSIGN_DRIVER_FUNC(CopyBufferToBuffer, name) \ ASSIGN_DRIVER_FUNC(GenerateMipmaps, name) \ ASSIGN_DRIVER_FUNC(EndCopyPass, name) \ diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ba83d8e..06a5368 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1,4 +1,4 @@ -/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities +/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities * * Copyright (c) 2020 Evan Hemsley * @@ -1865,27 +1865,8 @@ static D3D11TransferBuffer* D3D11_INTERNAL_CreateTransferBuffer( D3D11Renderer *renderer, uint32_t sizeInBytes ) { - D3D11TransferBuffer *transferBuffer; - D3D11_BUFFER_DESC bufferDesc; - ID3D11Buffer *bufferHandle; - HRESULT res; + D3D11TransferBuffer *transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); - bufferDesc.ByteWidth = sizeInBytes; - bufferDesc.Usage = D3D11_USAGE_STAGING; - bufferDesc.BindFlags = 0; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - res = ID3D11Device_CreateBuffer( - renderer->device, - &bufferDesc, - NULL, - &bufferHandle - ); - ERROR_CHECK_RETURN("Could not create buffer", NULL); - - transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); transferBuffer->data = (uint8_t*) SDL_malloc(sizeInBytes); transferBuffer->size = sizeInBytes; SDL_AtomicSet(&transferBuffer->referenceCount, 0); @@ -2289,13 +2270,13 @@ static void D3D11_CopyTextureToTexture( Refresh_WriteOptions writeOption ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - D3D11Texture *srcTexture = source->textureSlice.texture; + D3D11Texture *srcTexture = (D3D11Texture*) source->textureSlice.texture; uint32_t srcSubresourceIndex = D3D11_INTERNAL_CalcSubresource( source->textureSlice.mipLevel, source->textureSlice.layer, srcTexture->levelCount ); - D3D11Texture *dstTexture = destination->textureSlice.texture; + D3D11Texture *dstTexture = (D3D11Texture*) destination->textureSlice.texture; uint32_t dstSubresourceIndex = D3D11_INTERNAL_CalcSubresource( destination->textureSlice.mipLevel, destination->textureSlice.layer, @@ -2344,6 +2325,21 @@ static void D3D11_CopyBufferToBuffer( ); } +static void D3D11_GenerateMipmaps( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_Texture *texture +) { + D3D11Renderer *renderer = (D3D11Renderer*) driverData; + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; + D3D11Texture *d3d11Texture = (D3D11Texture*) texture; + + ID3D11DeviceContext1_GenerateMips( + d3d11CommandBuffer->context, + d3d11Texture->shaderView + ); +} + static void D3D11_EndCopyPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer @@ -2728,6 +2724,19 @@ static void D3D11_QueueDestroyGpuBuffer( SDL_free(d3d11Buffer); } +static void D3D11_QueueDestroyTransferBuffer( + Refresh_Renderer *driverData, + Refresh_TransferBuffer *transferBuffer +) { + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + + for (uint32_t i = 0; i < container->bufferCount; i += 1) + { + SDL_free(container->buffers[i]); + } + SDL_free(container->buffers); +} + static void D3D11_QueueDestroyShaderModule( Refresh_Renderer *driverData, Refresh_ShaderModule *shaderModule @@ -3312,6 +3321,13 @@ static void D3D11_BindIndexBuffer( /* Compute State */ +static void D3D11_BeginComputePass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + /* no-op */ +} + static void D3D11_BindComputePipeline( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -3404,6 +3420,13 @@ static void D3D11_BindComputeTextures( ); } +static void D3D11_EndComputePass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + /* no-op */ +} + /* Window and Swapchain Management */ static D3D11WindowData* D3D11_INTERNAL_FetchWindowData( @@ -3419,8 +3442,10 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( ) { ID3D11Texture2D *swapchainTexture; D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; D3D11_TEXTURE2D_DESC textureDesc; ID3D11RenderTargetView *rtv; + ID3D11UnorderedAccessView *uav; HRESULT res; /* Clear all the texture data */ @@ -3453,14 +3478,32 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( return 0; } + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = 0; + + res = ID3D11Device_CreateUnorderedAccessView( + renderer->device, + (ID3D11Resource *)swapchainTexture, + &uavDesc, + &uav + ); + if (FAILED(res)) + { + ID3D11RenderTargetView_Release(rtv); + ID3D11Texture2D_Release(swapchainTexture); + D3D11_INTERNAL_LogError(renderer->device, "Swapchain UAV creation failed", res); + return 0; + } + /* 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->unorderedAccessView = NULL; - pTexture->targetViewCapacity = 1; - pTexture->targetViewCount = 1; - pTexture->targetViews = SDL_calloc(1, sizeof(D3D11TargetView)); - pTexture->targetViews[0].view = (ID3D11View*) rtv; + pTexture->subresources = SDL_malloc(sizeof(D3D11TextureSubresource)); + pTexture->subresources[0].targetView = rtv; + pTexture->subresources[0].uav = uav; + pTexture->subresources[0].msaaHandle = NULL; + pTexture->subresources[0].layer = 0; + pTexture->subresources[0].level = 0; ID3D11Texture2D_GetDesc(swapchainTexture, &textureDesc); pTexture->levelCount = textureDesc.MipLevels; @@ -3600,9 +3643,10 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( int32_t width, int32_t height ) { - /* Release the old RTV */ - ID3D11RenderTargetView_Release(windowData->texture.targetViews[0].view); - SDL_free(windowData->texture.targetViews); + /* Release the old views */ + ID3D11RenderTargetView_Release(windowData->texture.subresources[0].targetView); + ID3D11UnorderedAccessView_Release(windowData->texture.subresources[0].uav); + SDL_free(windowData->texture.subresources); /* Resize the swapchain */ HRESULT res = IDXGISwapChain_ResizeBuffers( @@ -3685,8 +3729,9 @@ static void D3D11_UnclaimWindow( D3D11_Wait(driverData); - ID3D11RenderTargetView_Release(windowData->texture.targetViews[0].view); - SDL_free(windowData->texture.targetViews); + ID3D11RenderTargetView_Release(windowData->texture.subresources[0].targetView); + ID3D11UnorderedAccessView_Release(windowData->texture.subresources[0].uav); + SDL_free(windowData->texture.subresources); IDXGISwapChain_Release(windowData->swapchain); SDL_LockMutex(renderer->windowLock); -- 2.25.1 From 3c74ddf8faf8d6277570dc6e4f3d139027cf9157 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 15:45:41 -0800 Subject: [PATCH 78/98] misc d3d11 fixes --- src/Refresh_Driver_D3D11.c | 111 ++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 57 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 06a5368..0ddc777 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -350,9 +350,10 @@ static D3D11_FILTER RefreshToD3D11_Filter(Refresh_SamplerStateCreateInfo *create typedef struct D3D11TextureSubresource { - ID3D11View *targetView; /* can be NULL if not a target */ - ID3D11UnorderedAccessView *uav; /* can be NULL if not used in compute */ - ID3D11Resource *msaaHandle; /* can be NULL if not using MSAA */ + ID3D11RenderTargetView *colorTargetView; /* NULL if not a color target */ + ID3D11DepthStencilView *depthStencilTargetView; /* NULL if not a depth stencil target */ + ID3D11UnorderedAccessView *uav; /* NULL if not used in compute */ + ID3D11Resource *msaaHandle; /* NULL if not using MSAA */ uint32_t level; uint32_t layer; } D3D11TextureSubresource; @@ -421,7 +422,7 @@ typedef struct D3D11GraphicsPipeline typedef struct D3D11ComputePipeline { ID3D11ComputeShader *computeShader; - uint64_t computeUniformBlockSize; + uint32_t computeUniformBlockSize; uint32_t numTextures; uint32_t numBuffers; } D3D11ComputePipeline; @@ -770,8 +771,8 @@ static void D3D11_DrawInstancedPrimitives( uint32_t instanceCount ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16; - uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16; + uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer != NULL ? d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16 : 0; + uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer != NULL ? d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16 : 0; uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; @@ -833,8 +834,8 @@ static void D3D11_DrawPrimitives( uint32_t primitiveCount ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16; - uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16; + uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer != NULL ? d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16 : 0; + uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer != NULL ? d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16 : 0; uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; @@ -879,8 +880,8 @@ static void D3D11_DrawPrimitivesIndirect( ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; - uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16; - uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16; + uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer != NULL ? d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16 : 0; + uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer != NULL ? d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16 : 0; uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; @@ -1189,7 +1190,7 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline( pipeline->numBuffers = computeShaderInfo->bufferBindingCount; pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; pipeline->computeUniformBlockSize = D3D11_INTERNAL_NextHighestAlignment( - (uint32_t) computeShaderInfo->uniformBufferSize, + computeShaderInfo->uniformBufferSize, 256 ); @@ -1627,6 +1628,10 @@ static Refresh_Texture* D3D11_CreateTexture( d3d11Texture->levelCount ); + d3d11Texture->subresources[subresourceIndex].colorTargetView = NULL; + d3d11Texture->subresources[subresourceIndex].depthStencilTargetView = NULL; + d3d11Texture->subresources[subresourceIndex].uav = NULL; + d3d11Texture->subresources[subresourceIndex].msaaHandle = NULL; d3d11Texture->subresources[subresourceIndex].layer = layerIndex; d3d11Texture->subresources[subresourceIndex].level = levelIndex; @@ -1648,10 +1653,6 @@ static Refresh_Texture* D3D11_CreateTexture( ); ERROR_CHECK_RETURN("Could not create MSAA texture!", NULL); } - else - { - d3d11Texture->subresources[subresourceIndex].msaaHandle = NULL; - } if (d3d11Texture->isRenderTarget) { @@ -1659,7 +1660,7 @@ static Refresh_Texture* D3D11_CreateTexture( { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = format; + dsvDesc.Format = RefreshToD3D11_TextureFormat[d3d11Texture->format]; dsvDesc.Flags = 0; if (isMultisample) @@ -1676,7 +1677,7 @@ static Refresh_Texture* D3D11_CreateTexture( renderer->device, isMultisample ? d3d11Texture->subresources[subresourceIndex].msaaHandle : d3d11Texture->handle, &dsvDesc, - &d3d11Texture->subresources[subresourceIndex].targetView + &d3d11Texture->subresources[subresourceIndex].depthStencilTargetView ); ERROR_CHECK_RETURN("Could not create DSV!", NULL); } @@ -1708,15 +1709,11 @@ static Refresh_Texture* D3D11_CreateTexture( renderer->device, d3d11Texture->handle, &rtvDesc, - &d3d11Texture->subresources[subresourceIndex].targetView + &d3d11Texture->subresources[subresourceIndex].colorTargetView ); ERROR_CHECK_RETURN("Could not create RTV!", NULL); } } - else - { - d3d11Texture->subresources[subresourceIndex].targetView = NULL; - } if (isCompute) { @@ -1751,10 +1748,6 @@ static Refresh_Texture* D3D11_CreateTexture( ); ERROR_CHECK_RETURN("Could not create UAV!", NULL); } - else - { - d3d11Texture->subresources[subresourceIndex].uav = NULL; - } } } @@ -1880,7 +1873,7 @@ static Refresh_TransferBuffer* D3D11_CreateTransferBuffer( uint32_t sizeInBytes ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) (sizeof(D3D11TransferBufferContainer)); + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) SDL_malloc(sizeof(D3D11TransferBufferContainer)); D3D11TransferBuffer *transferBuffer = D3D11_INTERNAL_CreateTransferBuffer(renderer, sizeInBytes); container->activeBuffer = transferBuffer; @@ -2046,18 +2039,16 @@ static void D3D11_UploadToBuffer( D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; - D3D11_BOX srcBox = { copyParams->srcOffset, 0, 0, copyParams->srcOffset + copyParams->size, 1, 1 }; + D3D11_BOX dstBox = { copyParams->dstOffset, 0, 0, copyParams->dstOffset + copyParams->size, 1, 1 }; - ID3D11DeviceContext1_CopySubresourceRegion1( + ID3D11DeviceContext1_UpdateSubresource1( d3d11CommandBuffer->context, - d3d11Buffer->handle, + (ID3D11Resource*) d3d11Buffer->handle, 0, - copyParams->dstOffset, + &dstBox, + d3d11TransferBuffer->data + copyParams->srcOffset, 0, 0, - d3d11TransferBuffer->data, - 0, - &srcBox, writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 ); @@ -2146,7 +2137,7 @@ static void D3D11_DownloadFromTexture( ERROR_CHECK_RETURN("Could not map texture for reading",) uint8_t* dataPtr = (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset; - for (int32_t row = textureRegion->y; row < copyParams->bufferImageHeight; row += 1) + for (uint32_t row = textureRegion->y; row < copyParams->bufferImageHeight; row += 1) { SDL_memcpy( dataPtr, @@ -2213,12 +2204,12 @@ static void D3D11_DownloadFromBuffer( ID3D11DeviceContext1_CopySubresourceRegion1( d3d11CommandBuffer->context, - stagingBuffer, + (ID3D11Resource*) stagingBuffer, 0, 0, 0, 0, - d3d11Buffer->handle, + (ID3D11Resource*) d3d11Buffer->handle, 0, &srcBox, D3D11_COPY_NO_OVERWRITE @@ -2313,12 +2304,12 @@ static void D3D11_CopyBufferToBuffer( ID3D11DeviceContext1_CopySubresourceRegion1( d3d11CommandBuffer->context, - dstBuffer->handle, + (ID3D11Resource*) dstBuffer->handle, 0, copyParams->dstOffset, 0, 0, - srcBuffer->handle, + (ID3D11Resource*) srcBuffer->handle, 0, &srcBox, writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 @@ -2548,7 +2539,7 @@ static void D3D11_PushFragmentShaderUniforms( d3d11CommandBuffer->fragmentUniformBuffer->offset += graphicsPipeline->fragmentUniformBlockSize; } -static uint32_t D3D11_PushComputeShaderUniforms( +static void D3D11_PushComputeShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, void *data, @@ -2580,7 +2571,7 @@ static uint32_t D3D11_PushComputeShaderUniforms( ); d3d11CommandBuffer->computeUniformBuffer->offset += - (uint32_t) computePipeline->computeUniformBlockSize; /* API FIXME: Is this cast safe? */ + (uint32_t) computePipeline->computeUniformBlockSize; } /* Samplers */ @@ -2588,8 +2579,7 @@ static uint32_t D3D11_PushComputeShaderUniforms( static void D3D11_BindVertexSamplers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; @@ -2600,8 +2590,8 @@ static void D3D11_BindVertexSamplers( for (int32_t i = 0; i < numVertexSamplers; i += 1) { - srvs[i] = ((D3D11Texture*) pTextures[i])->shaderView; - d3d11Samplers[i] = ((D3D11Sampler*) pSamplers[i])->handle; + srvs[i] = ((D3D11Texture*) pBindings[i].texture)->shaderView; + d3d11Samplers[i] = ((D3D11Sampler*) pBindings[i].sampler)->handle; } ID3D11DeviceContext_VSSetShaderResources( @@ -2622,8 +2612,7 @@ static void D3D11_BindVertexSamplers( static void D3D11_BindFragmentSamplers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; @@ -2634,8 +2623,8 @@ static void D3D11_BindFragmentSamplers( for (int32_t i = 0; i < numFragmentSamplers; i += 1) { - srvs[i] = ((D3D11Texture*) pTextures[i])->shaderView; - d3d11Samplers[i] = ((D3D11Sampler*) pSamplers[i])->handle; + srvs[i] = ((D3D11Texture*) pBindings[i].texture)->shaderView; + d3d11Samplers[i] = ((D3D11Sampler*) pBindings[i].sampler)->handle; } ID3D11DeviceContext_PSSetShaderResources( @@ -2681,9 +2670,14 @@ static void D3D11_QueueDestroyTexture( ID3D11Resource_Release(d3d11Texture->subresources[subresourceIndex].msaaHandle); } - if (d3d11Texture->subresources[subresourceIndex].targetView != NULL) + if (d3d11Texture->subresources[subresourceIndex].colorTargetView != NULL) { - ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].targetView); + ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].colorTargetView); + } + + if (d3d11Texture->subresources[subresourceIndex].depthStencilTargetView != NULL) + { + ID3D11DepthStencilView_Release(d3d11Texture->subresources[subresourceIndex].depthStencilTargetView); } if (d3d11Texture->subresources[subresourceIndex].uav != NULL) @@ -2983,7 +2977,7 @@ static void D3D11_BeginRenderPass( colorAttachmentInfos[i].textureSlice.layer, texture->levelCount ); - rtvs[i] = texture->subresources[subresourceIndex].targetView; + rtvs[i] = texture->subresources[subresourceIndex].colorTargetView; if (texture->subresources[subresourceIndex].msaaHandle != NULL) { @@ -3004,7 +2998,7 @@ static void D3D11_BeginRenderPass( texture->levelCount ); - dsv = texture->subresources[subresourceIndex].targetView; + dsv = texture->subresources[subresourceIndex].depthStencilTargetView; } /* Actually set the RTs */ @@ -3478,6 +3472,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( return 0; } + uavDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; uavDesc.Texture2D.MipSlice = 0; @@ -3499,8 +3494,9 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( pTexture->handle = NULL; /* The texture does not "own" the swapchain texture, and it can change dynamically. */ pTexture->shaderView = NULL; pTexture->subresources = SDL_malloc(sizeof(D3D11TextureSubresource)); - pTexture->subresources[0].targetView = rtv; + pTexture->subresources[0].colorTargetView = rtv; pTexture->subresources[0].uav = uav; + pTexture->subresources[0].depthStencilTargetView = NULL; pTexture->subresources[0].msaaHandle = NULL; pTexture->subresources[0].layer = 0; pTexture->subresources[0].level = 0; @@ -3545,6 +3541,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( swapchainDesc.BufferDesc.Height = 0; swapchainDesc.BufferDesc.RefreshRate.Numerator = 0; swapchainDesc.BufferDesc.RefreshRate.Denominator = 0; + /* TODO: support different swapchain formats? */ swapchainDesc.BufferDesc.Format = RefreshToD3D11_TextureFormat[REFRESH_TEXTUREFORMAT_R8G8B8A8]; swapchainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapchainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; @@ -3552,7 +3549,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( /* Initialize the rest of the swapchain descriptor */ swapchainDesc.SampleDesc.Count = 1; swapchainDesc.SampleDesc.Quality = 0; - swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_UNORDERED_ACCESS; swapchainDesc.BufferCount = 2; swapchainDesc.OutputWindow = dxgiHandle; swapchainDesc.Windowed = 1; @@ -3644,7 +3641,7 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( int32_t height ) { /* Release the old views */ - ID3D11RenderTargetView_Release(windowData->texture.subresources[0].targetView); + ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetView); ID3D11UnorderedAccessView_Release(windowData->texture.subresources[0].uav); SDL_free(windowData->texture.subresources); @@ -3729,7 +3726,7 @@ static void D3D11_UnclaimWindow( D3D11_Wait(driverData); - ID3D11RenderTargetView_Release(windowData->texture.subresources[0].targetView); + ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetView); ID3D11UnorderedAccessView_Release(windowData->texture.subresources[0].uav); SDL_free(windowData->texture.subresources); IDXGISwapChain_Release(windowData->swapchain); -- 2.25.1 From 6c2eef669e161e45f9ea65e1daf65f9faf99bdff Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 16:06:39 -0800 Subject: [PATCH 79/98] add correct defaults for buffer stride and buffer image height --- src/Refresh_Driver_D3D11.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 0ddc777..3e3c9ab 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1990,7 +1990,8 @@ static void D3D11_UploadToTexture( D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Texture *d3d11Texture = (D3D11Texture*) textureRegion->textureSlice.texture; - + uint32_t bufferStride = copyParams->bufferStride; + uint32_t bufferImageHeight = copyParams->bufferImageHeight; int32_t w = textureRegion->w; int32_t h = textureRegion->h; @@ -2001,6 +2002,15 @@ static void D3D11_UploadToTexture( h = (h + blockSize - 1) & ~(blockSize - 1); } + if (bufferStride == 0) + { + bufferStride = BytesPerRow(w, d3d11Texture->format); + } + if (bufferImageHeight == 0) + { + bufferImageHeight = h; + } + D3D11_BOX dstBox; dstBox.left = textureRegion->x; dstBox.top = textureRegion->y; @@ -2019,8 +2029,8 @@ static void D3D11_UploadToTexture( ), &dstBox, (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset, - copyParams->bufferStride, - copyParams->bufferStride * copyParams->bufferImageHeight, + bufferStride, + bufferStride * bufferImageHeight, writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD ? D3D11_COPY_DISCARD : 0 ); @@ -2076,6 +2086,8 @@ static void D3D11_DownloadFromTexture( d3d11Texture->levelCount ); int32_t formatSize = Texture_GetFormatSize(d3d11Texture->format); + uint32_t bufferStride = copyParams->bufferStride; + uint32_t bufferImageHeight = copyParams->bufferImageHeight; D3D11_BOX srcBox = {textureRegion->x, textureRegion->y, textureRegion->z, textureRegion->x + textureRegion->w, textureRegion->y + textureRegion->h, 1}; D3D11_MAPPED_SUBRESOURCE subresource; HRESULT res; @@ -2136,12 +2148,21 @@ static void D3D11_DownloadFromTexture( ); ERROR_CHECK_RETURN("Could not map texture for reading",) + if (bufferStride == 0) + { + bufferStride = BytesPerRow(textureRegion->w, d3d11Texture->format); + } + if (bufferImageHeight == 0) + { + bufferImageHeight = textureRegion->h; + } + uint8_t* dataPtr = (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset; for (uint32_t row = textureRegion->y; row < copyParams->bufferImageHeight; row += 1) { SDL_memcpy( dataPtr, - (uint8_t*) subresource.pData + (row * copyParams->bufferStride) + (textureRegion->x * formatSize), + (uint8_t*) subresource.pData + (row * bufferStride) + (textureRegion->x * formatSize), textureRegion->w * formatSize ); } -- 2.25.1 From 01e805c800e78ed82ed47445be1936c9eca52eb1 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 16:18:31 -0800 Subject: [PATCH 80/98] fix render target view creation --- src/Refresh_Driver_D3D11.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 3e3c9ab..1ebf457 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1685,6 +1685,8 @@ static Refresh_Texture* D3D11_CreateTexture( { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = RefreshToD3D11_TextureFormat[d3d11Texture->format]; + if (d3d11Texture->layerCount > 1) { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; -- 2.25.1 From 6ebfabcecf6aad15ecf82ea884f23c8f4671ab9f Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 16:31:41 -0800 Subject: [PATCH 81/98] fix compute uniform access --- 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 1ebf457..b9477f9 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -930,7 +930,7 @@ static void D3D11_DispatchCompute( uint32_t groupCountZ ) { D3D11CommandBuffer* d3d11CommandBuffer = (D3D11CommandBuffer*)commandBuffer; - uint32_t computeOffsetInConstants = d3d11CommandBuffer->computeUniformBuffer->drawOffset / 16; + uint32_t computeOffsetInConstants = d3d11CommandBuffer->computeUniformBuffer != NULL ? d3d11CommandBuffer->computeUniformBuffer->drawOffset / 16 : 0; uint32_t computeBlockSizeInConstants = (uint32_t) (d3d11CommandBuffer->computePipeline->computeUniformBlockSize / 16); if (d3d11CommandBuffer->computeUniformBuffer != NULL) -- 2.25.1 From 52d4c934f3961512a0528dcda5db386df8bac16b Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 17:30:20 -0800 Subject: [PATCH 82/98] modify readback API --- include/Refresh.h | 83 ++++---- src/Refresh.c | 72 ++++--- src/Refresh_Driver.h | 34 ++-- src/Refresh_Driver_D3D11.c | 39 ++-- src/Refresh_Driver_Vulkan.c | 396 ++++++++++++------------------------ 5 files changed, 243 insertions(+), 381 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index 4e3b722..c4be92d 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -1193,46 +1193,6 @@ REFRESHAPI void Refresh_UploadToBuffer( Refresh_WriteOptions writeOption ); -/* GPU-to-CPU copies occur on the GPU timeline. - * - * You may NOT assume that the data in the TransferBuffer is fully copied - * until the command buffer has finished execution. - */ - -/* - * transferOption: - * SAFEDISCARD: - * If this TransferBuffer has been used in commands that have not completed, - * the issued commands will still be valid at the cost of increased memory usage. - * You may NOT assume that any of the previous data is retained. - * If the TransferBuffer was not in use, this option is equivalent to OVERWRITE. - * It is not recommended to use this option with large TransferBuffers. - * - * OVERWRITE: - * Overwrites the data regardless of whether a command has been issued. - * Use this option with great care, as it can cause data races to occur! - */ - -/* Downloads data from a texture to a TransferBuffer. */ -REFRESHAPI void Refresh_DownloadFromTexture( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions transferOption -); - -/* Downloads data from a GpuBuffer object. */ -REFRESHAPI void Refresh_DownloadFromBuffer( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams, - Refresh_TransferOptions transferOption -); - /* GPU-to-GPU copies occur on the GPU timeline, * and you may assume the copy has finished in subsequent commands. */ @@ -1401,6 +1361,49 @@ REFRESHAPI void Refresh_ReleaseFence( Refresh_Fence *fence ); +/* Readback */ + +/* GPU-to-CPU copies occur immediately on the CPU timeline. + * + * If you modify data on the GPU and then call these functions without calling Wait or WaitForFences first, + * the data will be undefined! + * + * Readback forces a sync point and is generally a bad thing to do. + * Only use these functions if you have exhausted all other options. + */ + +/* + * transferOption: + * SAFEDISCARD: + * If this TransferBuffer has been used in commands that have not completed, + * the issued commands will still be valid at the cost of increased memory usage. + * You may NOT assume that any of the previous data is retained. + * If the TransferBuffer was not in use, this option is equivalent to OVERWRITE. + * It is not recommended to use this option with large TransferBuffers. + * + * OVERWRITE: + * Overwrites the data regardless of whether a command has been issued. + * Use this option with great care, as it can cause data races to occur! + */ + +/* Downloads data from a texture to a TransferBuffer. */ +REFRESHAPI void Refresh_DownloadFromTexture( + Refresh_Device *device, + Refresh_TextureRegion *textureRegion, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions transferOption +); + +/* Downloads data from a GpuBuffer object. */ +REFRESHAPI void Refresh_DownloadFromBuffer( + Refresh_Device *device, + Refresh_GpuBuffer *gpuBuffer, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions transferOption +); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/Refresh.c b/src/Refresh.c index 267f47d..e6ac313 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -824,44 +824,6 @@ void Refresh_UploadToBuffer( ); } -void Refresh_DownloadFromTexture( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions transferOption -) { - NULL_RETURN(device); - device->DownloadFromTexture( - device->driverData, - commandBuffer, - textureRegion, - transferBuffer, - copyParams, - transferOption - ); -} - -void Refresh_DownloadFromBuffer( - Refresh_Device *device, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams, - Refresh_TransferOptions transferOption -) { - NULL_RETURN(device); - device->DownloadFromBuffer( - device->driverData, - commandBuffer, - gpuBuffer, - transferBuffer, - copyParams, - transferOption - ); -} - void Refresh_CopyTextureToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, @@ -1067,4 +1029,38 @@ void Refresh_ReleaseFence( ); } +void Refresh_DownloadFromTexture( + Refresh_Device *device, + Refresh_TextureRegion *textureRegion, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions transferOption +) { + NULL_RETURN(device); + device->DownloadFromTexture( + device->driverData, + textureRegion, + transferBuffer, + copyParams, + transferOption + ); +} + +void Refresh_DownloadFromBuffer( + Refresh_Device *device, + Refresh_GpuBuffer *gpuBuffer, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions transferOption +) { + NULL_RETURN(device); + device->DownloadFromBuffer( + device->driverData, + gpuBuffer, + transferBuffer, + copyParams, + transferOption + ); +} + /* vim: set noexpandtab shiftwidth=8 tabstop=8: */ diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index 18d0785..bb6d60f 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -506,24 +506,6 @@ struct Refresh_Device Refresh_WriteOptions writeOption ); - void (*DownloadFromTexture)( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureSlice, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions transferOption - ); - - void (*DownloadFromBuffer)( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams, - Refresh_TransferOptions transferOption - ); - void (*CopyTextureToTexture)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -619,6 +601,22 @@ struct Refresh_Device Refresh_Fence *fence ); + void (*DownloadFromTexture)( + Refresh_Renderer *driverData, + Refresh_TextureRegion *textureSlice, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions transferOption + ); + + void (*DownloadFromBuffer)( + Refresh_Renderer *driverData, + Refresh_GpuBuffer *gpuBuffer, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions transferOption + ); + /* Opaque pointer for the Driver */ Refresh_Renderer *driverData; }; diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b9477f9..ae15513 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2069,14 +2069,12 @@ static void D3D11_UploadToBuffer( static void D3D11_DownloadFromTexture( Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, Refresh_TextureRegion *textureRegion, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, Refresh_TransferOptions transferOption ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Texture *d3d11Texture = (D3D11Texture*) textureRegion->textureSlice.texture; @@ -2126,8 +2124,10 @@ static void D3D11_DownloadFromTexture( ); ERROR_CHECK_RETURN("Staging texture creation failed",) - ID3D11DeviceContext1_CopySubresourceRegion1( - d3d11CommandBuffer->context, + /* Readback is only possible on CPU timeline in D3D11 */ + SDL_LockMutex(renderer->contextLock); + ID3D11DeviceContext_CopySubresourceRegion( + renderer->immediateContext, stagingTexture, 0, 0, @@ -2135,13 +2135,12 @@ static void D3D11_DownloadFromTexture( 0, d3d11Texture->handle, subresourceIndex, - &srcBox, - D3D11_COPY_NO_OVERWRITE + &srcBox ); /* Read from the staging texture */ - res = ID3D11DeviceContext1_Map( - d3d11CommandBuffer->context, + res = ID3D11DeviceContext_Map( + renderer->immediateContext, stagingTexture, subresourceIndex, D3D11_MAP_READ, @@ -2170,24 +2169,24 @@ static void D3D11_DownloadFromTexture( } ID3D11DeviceContext1_Unmap( - d3d11CommandBuffer->context, + renderer->immediateContext, stagingTexture, 0 ); + SDL_UnlockMutex(renderer->contextLock); + /* Clean up the staging texture */ ID3D11Texture2D_Release(stagingTexture); } static void D3D11_DownloadFromBuffer( Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, Refresh_TransferOptions transferOption ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; - D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer; D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; @@ -2225,8 +2224,10 @@ static void D3D11_DownloadFromBuffer( ); ERROR_CHECK_RETURN("Could not create staging buffer for readback", ); - ID3D11DeviceContext1_CopySubresourceRegion1( - d3d11CommandBuffer->context, + /* Readback is only possible on CPU timeline in D3D11 */ + SDL_LockMutex(renderer->contextLock); + ID3D11DeviceContext_CopySubresourceRegion( + renderer->immediateContext, (ID3D11Resource*) stagingBuffer, 0, 0, @@ -2234,13 +2235,12 @@ static void D3D11_DownloadFromBuffer( 0, (ID3D11Resource*) d3d11Buffer->handle, 0, - &srcBox, - D3D11_COPY_NO_OVERWRITE + &srcBox ); /* Read from the staging buffer */ - res = ID3D11DeviceContext1_Map( - d3d11CommandBuffer->context, + res = ID3D11DeviceContext_Map( + renderer->immediateContext, stagingBuffer, 0, D3D11_MAP_READ, @@ -2265,12 +2265,11 @@ static void D3D11_DownloadFromBuffer( ); ID3D11DeviceContext1_Unmap( - d3d11CommandBuffer->context, + renderer->immediateContext, stagingBuffer, 0 ); - - D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); + SDL_UnlockMutex(renderer->contextLock); /* Clean up the staging buffer */ ID3D11Buffer_Release(stagingBuffer); diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 890644a..feb9fa6 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -8550,130 +8550,6 @@ static void VULKAN_UploadToBuffer( VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); } -static void VULKAN_DownloadFromTexture( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions transferOption -) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTextureSlice *vulkanTextureSlice; - VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; - VkBufferImageCopy imageCopy; - - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); - - if ( - transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && - SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 - ) { - VULKAN_INTERNAL_DiscardActiveBuffer( - renderer, - transferBufferContainer - ); - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); - } - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - transferBufferContainer->activeBufferHandle->vulkanBuffer - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - vulkanTextureSlice - ); - - imageCopy.imageExtent.width = textureRegion->w; - imageCopy.imageExtent.height = textureRegion->h; - imageCopy.imageExtent.depth = textureRegion->d; - imageCopy.imageOffset.x = textureRegion->x; - imageCopy.imageOffset.y = textureRegion->y; - imageCopy.imageOffset.z = textureRegion->z; - imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; - imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; - imageCopy.bufferOffset = copyParams->bufferOffset; - imageCopy.bufferRowLength = copyParams->bufferStride; - imageCopy.bufferImageHeight = copyParams->bufferImageHeight; - - renderer->vkCmdCopyImageToBuffer( - vulkanCommandBuffer->commandBuffer, - vulkanTextureSlice->parent->image, - AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, - transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, - 1, - &imageCopy - ); - - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); - VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); -} - -static void VULKAN_DownloadFromBuffer( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams, - Refresh_TransferOptions transferOption -) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBufferContainer *gpuBufferContainer = (VulkanBufferContainer*) gpuBuffer; - VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; - VkBufferCopy bufferCopy; - - if ( - transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && - SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 - ) { - VULKAN_INTERNAL_DiscardActiveBuffer( - renderer, - transferBufferContainer - ); - } - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - transferBufferContainer->activeBufferHandle->vulkanBuffer - ); - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - gpuBufferContainer->activeBufferHandle->vulkanBuffer - ); - - bufferCopy.srcOffset = copyParams->srcOffset; - bufferCopy.dstOffset = copyParams->dstOffset; - bufferCopy.size = copyParams->size; - - renderer->vkCmdCopyBuffer( - vulkanCommandBuffer->commandBuffer, - gpuBufferContainer->activeBufferHandle->vulkanBuffer->buffer, - transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, - 1, - &bufferCopy - ); - - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); -} - static void VULKAN_CopyTextureToTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -8751,147 +8627,6 @@ static void VULKAN_CopyTextureToTexture( VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, dstSlice); } -static void VULKAN_CopyTextureToBuffer( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParams, - Refresh_WriteOptions writeOption -) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTextureSlice *vulkanTextureSlice; - VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; - VkBufferImageCopy imageCopy; - - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); - - if ( - writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && - SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 - ) { - VULKAN_INTERNAL_DiscardActiveBuffer( - renderer, - bufferContainer - ); - } - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - vulkanTextureSlice - ); - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - bufferContainer->activeBufferHandle->vulkanBuffer - ); - - imageCopy.imageExtent.width = textureRegion->w; - imageCopy.imageExtent.height = textureRegion->h; - imageCopy.imageExtent.depth = textureRegion->d; - imageCopy.imageOffset.x = textureRegion->x; - imageCopy.imageOffset.y = textureRegion->y; - imageCopy.imageOffset.z = textureRegion->z; - imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; - imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; - imageCopy.bufferOffset = copyParams->bufferOffset; - imageCopy.bufferRowLength = copyParams->bufferStride; - imageCopy.bufferImageHeight = copyParams->bufferImageHeight; - - renderer->vkCmdCopyImageToBuffer( - vulkanCommandBuffer->commandBuffer, - vulkanTextureSlice->parent->image, - AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, - bufferContainer->activeBufferHandle->vulkanBuffer->buffer, - 1, - &imageCopy - ); - - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); -} - -static void VULKAN_CopyBufferToTexture( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureRegion *textureRegion, - Refresh_BufferImageCopy *copyParams, - Refresh_WriteOptions writeOption -) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; - VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureRegion->textureSlice.texture; - VulkanTextureSlice *vulkanTextureSlice; - VkBufferImageCopy imageCopy; - - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); - - if ( - writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && - textureContainer->canBeDiscarded && - SDL_AtomicGet(&vulkanTextureSlice->referenceCount) > 0 - ) { - VULKAN_INTERNAL_DiscardActiveTexture( - renderer, - textureContainer - ); - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); - } - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - bufferContainer->activeBufferHandle->vulkanBuffer - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanTextureSlice - ); - - imageCopy.imageExtent.width = textureRegion->w; - imageCopy.imageExtent.height = textureRegion->h; - imageCopy.imageExtent.depth = textureRegion->d; - imageCopy.imageOffset.x = textureRegion->x; - imageCopy.imageOffset.y = textureRegion->y; - imageCopy.imageOffset.z = textureRegion->z; - imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; - imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; - imageCopy.bufferOffset = copyParams->bufferOffset; - imageCopy.bufferRowLength = copyParams->bufferStride; - imageCopy.bufferImageHeight = copyParams->bufferImageHeight; - - renderer->vkCmdCopyBufferToImage( - vulkanCommandBuffer->commandBuffer, - bufferContainer->activeBufferHandle->vulkanBuffer->buffer, - vulkanTextureSlice->parent->image, - AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, - 1, - &imageCopy - ); - - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); -} - static void VULKAN_CopyBufferToBuffer( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -10461,6 +10196,137 @@ static void VULKAN_ReleaseFence( VULKAN_INTERNAL_ReturnFenceToPool((VulkanRenderer*) driverData, (VkFence) fence); } +/* Readback */ + +static void VULKAN_DownloadFromTexture( + Refresh_Renderer *driverData, + Refresh_TextureRegion *textureRegion, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions transferOption +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanTextureSlice *vulkanTextureSlice; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; + VkBufferImageCopy imageCopy; + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); + Refresh_Fence *fence; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer(driverData); + + if ( + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + transferBufferContainer + ); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); + } + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + transferBufferContainer->activeBufferHandle->vulkanBuffer + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanTextureSlice + ); + + imageCopy.imageExtent.width = textureRegion->w; + imageCopy.imageExtent.height = textureRegion->h; + imageCopy.imageExtent.depth = textureRegion->d; + imageCopy.imageOffset.x = textureRegion->x; + imageCopy.imageOffset.y = textureRegion->y; + imageCopy.imageOffset.z = textureRegion->z; + imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; + imageCopy.imageSubresource.layerCount = 1; + imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; + imageCopy.bufferOffset = copyParams->bufferOffset; + imageCopy.bufferRowLength = copyParams->bufferStride; + imageCopy.bufferImageHeight = copyParams->bufferImageHeight; + + renderer->vkCmdCopyImageToBuffer( + vulkanCommandBuffer->commandBuffer, + vulkanTextureSlice->parent->image, + AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, + transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, + 1, + &imageCopy + ); + + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); + VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); + + fence = VULKAN_SubmitAndAcquireFence(driverData, (Refresh_CommandBuffer*) vulkanCommandBuffer); + VULKAN_WaitForFences(driverData, 1, 1, &fence); +} + +static void VULKAN_DownloadFromBuffer( + Refresh_Renderer *driverData, + Refresh_GpuBuffer *gpuBuffer, + Refresh_TransferBuffer *transferBuffer, + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions transferOption +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanBufferContainer *gpuBufferContainer = (VulkanBufferContainer*) gpuBuffer; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; + VkBufferCopy bufferCopy; + Refresh_Fence *fence; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer(driverData); + + if ( + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + transferBufferContainer + ); + } + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + transferBufferContainer->activeBufferHandle->vulkanBuffer + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + gpuBufferContainer->activeBufferHandle->vulkanBuffer + ); + + bufferCopy.srcOffset = copyParams->srcOffset; + bufferCopy.dstOffset = copyParams->dstOffset; + bufferCopy.size = copyParams->size; + + renderer->vkCmdCopyBuffer( + vulkanCommandBuffer->commandBuffer, + gpuBufferContainer->activeBufferHandle->vulkanBuffer->buffer, + transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, + 1, + &bufferCopy + ); + + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); + + fence = VULKAN_SubmitAndAcquireFence(driverData, (Refresh_CommandBuffer*) vulkanCommandBuffer); + VULKAN_WaitForFences(driverData, 1, 1, &fence); +} + /* Device instantiation */ static inline uint8_t CheckDeviceExtensions( -- 2.25.1 From 838b5df27b8a943dbd0f4998a4f74eb9a0e11a2d Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 17:54:50 -0800 Subject: [PATCH 83/98] fix texture upload depth --- src/Refresh_Driver_D3D11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ae15513..b0c60ae 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2016,10 +2016,10 @@ static void D3D11_UploadToTexture( D3D11_BOX dstBox; dstBox.left = textureRegion->x; dstBox.top = textureRegion->y; - dstBox.front = textureRegion->d; + dstBox.front = textureRegion->z; dstBox.right = textureRegion->x + w; dstBox.bottom = textureRegion->y + h; - dstBox.back = textureRegion->d + 1; + dstBox.back = textureRegion->z + 1; ID3D11DeviceContext1_UpdateSubresource1( d3d11CommandBuffer->context, -- 2.25.1 From 65c30350a7f40f5e9a150c378f9ae976da47f44c Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 20:58:02 -0800 Subject: [PATCH 84/98] fix Vulkan fence leak on download --- src/Refresh_Driver_Vulkan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index feb9fa6..7c24e25 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -10267,6 +10267,7 @@ static void VULKAN_DownloadFromTexture( fence = VULKAN_SubmitAndAcquireFence(driverData, (Refresh_CommandBuffer*) vulkanCommandBuffer); VULKAN_WaitForFences(driverData, 1, 1, &fence); + VULKAN_ReleaseFence(driverData, fence); } static void VULKAN_DownloadFromBuffer( @@ -10325,6 +10326,7 @@ static void VULKAN_DownloadFromBuffer( fence = VULKAN_SubmitAndAcquireFence(driverData, (Refresh_CommandBuffer*) vulkanCommandBuffer); VULKAN_WaitForFences(driverData, 1, 1, &fence); + VULKAN_ReleaseFence(driverData, fence); } /* Device instantiation */ -- 2.25.1 From 953be4225c739713f6428a8863452fae85ed7cb3 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 20:58:34 -0800 Subject: [PATCH 85/98] d3d11 swapchain texture handle + misc fixes --- src/Refresh_Driver_D3D11.c | 66 ++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b0c60ae..39ebe58 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1,4 +1,4 @@ -/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities +/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities * * Copyright (c) 2020 Evan Hemsley * @@ -2130,7 +2130,7 @@ static void D3D11_DownloadFromTexture( renderer->immediateContext, stagingTexture, 0, - 0, + copyParams->bufferOffset, 0, 0, d3d11Texture->handle, @@ -2159,14 +2159,27 @@ static void D3D11_DownloadFromTexture( } uint8_t* dataPtr = (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset; - for (uint32_t row = textureRegion->y; row < copyParams->bufferImageHeight; row += 1) + + if (bufferStride == 0 && bufferImageHeight == 0) // assume tightly packed { SDL_memcpy( dataPtr, - (uint8_t*) subresource.pData + (row * bufferStride) + (textureRegion->x * formatSize), - textureRegion->w * formatSize + (uint8_t *)subresource.pData, + BytesPerImage(textureRegion->w, textureRegion->h, d3d11Texture->format) ); } + else + { + for (uint32_t row = textureRegion->y; row < bufferImageHeight; row += 1) + { + SDL_memcpy( + dataPtr, + (uint8_t*) subresource.pData + (row * bufferStride) + (textureRegion->x * formatSize), + textureRegion->w * formatSize + ); + dataPtr += textureRegion->w * formatSize; + } + } ID3D11DeviceContext1_Unmap( renderer->immediateContext, @@ -2295,7 +2308,7 @@ static void D3D11_CopyTextureToTexture( destination->textureSlice.layer, dstTexture->levelCount ); - D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + source->w, source->y + source->w, 1 }; + D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + source->w, source->y + source->h, 1 }; ID3D11DeviceContext1_CopySubresourceRegion1( d3d11CommandBuffer->context, @@ -3457,9 +3470,11 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( D3D11Texture *pTexture ) { ID3D11Texture2D *swapchainTexture; + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; D3D11_TEXTURE2D_DESC textureDesc; + ID3D11ShaderResourceView *srv; ID3D11RenderTargetView *rtv; ID3D11UnorderedAccessView *uav; HRESULT res; @@ -3476,6 +3491,25 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( ); ERROR_CHECK_RETURN("Could not get buffer from swapchain!", 0); + /* Create the SRV for the swapchain */ + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MostDetailedMip = 0; + + res = ID3D11Device_CreateShaderResourceView( + renderer->device, + (ID3D11Resource *)swapchainTexture, + &srvDesc, + &srv + ); + if (FAILED(res)) + { + ID3D11Texture2D_Release(swapchainTexture); + D3D11_INTERNAL_LogError(renderer->device, "Swapchain SRV creation failed", res); + return 0; + } + /* Create the RTV for the swapchain */ rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; @@ -3489,6 +3523,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( ); if (FAILED(res)) { + ID3D11ShaderResourceView_Release(srv); ID3D11Texture2D_Release(swapchainTexture); D3D11_INTERNAL_LogError(renderer->device, "Swapchain RTV creation failed", res); return 0; @@ -3506,6 +3541,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( ); if (FAILED(res)) { + ID3D11ShaderResourceView_Release(srv); ID3D11RenderTargetView_Release(rtv); ID3D11Texture2D_Release(swapchainTexture); D3D11_INTERNAL_LogError(renderer->device, "Swapchain UAV creation failed", res); @@ -3513,8 +3549,8 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( } /* 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->handle = NULL; /* This will be set in AcquireSwapchainTexture. */ + pTexture->shaderView = srv; pTexture->subresources = SDL_malloc(sizeof(D3D11TextureSubresource)); pTexture->subresources[0].colorTargetView = rtv; pTexture->subresources[0].uav = uav; @@ -3571,7 +3607,7 @@ static uint8_t D3D11_INTERNAL_CreateSwapchain( /* Initialize the rest of the swapchain descriptor */ swapchainDesc.SampleDesc.Count = 1; swapchainDesc.SampleDesc.Quality = 0; - swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_UNORDERED_ACCESS; + swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_UNORDERED_ACCESS | DXGI_USAGE_SHADER_INPUT; swapchainDesc.BufferCount = 2; swapchainDesc.OutputWindow = dxgiHandle; swapchainDesc.Windowed = 1; @@ -3748,6 +3784,7 @@ static void D3D11_UnclaimWindow( D3D11_Wait(driverData); + ID3D11ShaderResourceView_Release(windowData->texture.shaderView); ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetView); ID3D11UnorderedAccessView_Release(windowData->texture.subresources[0].uav); SDL_free(windowData->texture.subresources); @@ -3804,6 +3841,15 @@ static Refresh_Texture* D3D11_AcquireSwapchainTexture( ERROR_CHECK_RETURN("Could not resize swapchain", NULL); } + /* Set the handle on the windowData texture data. */ + res = IDXGISwapChain_GetBuffer( + windowData->swapchain, + 0, + &D3D_IID_ID3D11Texture2D, + (void**) &windowData->texture.handle + ); + ERROR_CHECK_RETURN("Could not acquire swapchain!", NULL); + /* Let the command buffer know it's associated with this swapchain. */ d3d11CommandBuffer->windowData = windowData; @@ -4011,6 +4057,8 @@ static void D3D11_Submit( syncInterval, presentFlags ); + + ID3D11Texture2D_Release(d3d11CommandBuffer->windowData->texture.handle); } /* Check if we can perform any cleanups */ -- 2.25.1 From 23aed89ad9b31aea20c94e694710a90504a5dde7 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 22:24:33 -0800 Subject: [PATCH 86/98] more download fixes --- src/Refresh_Driver_D3D11.c | 36 ++++++++---------------------------- src/Refresh_Driver_Vulkan.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 39ebe58..ce98c52 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2086,8 +2086,8 @@ static void D3D11_DownloadFromTexture( d3d11Texture->levelCount ); int32_t formatSize = Texture_GetFormatSize(d3d11Texture->format); - uint32_t bufferStride = copyParams->bufferStride; - uint32_t bufferImageHeight = copyParams->bufferImageHeight; + uint32_t bufferStride = copyParams->bufferStride == 0 ? (textureRegion->w * formatSize) : copyParams->bufferStride; + uint32_t bufferImageHeight = copyParams->bufferImageHeight == 0 ? (textureRegion->h * formatSize) : copyParams->bufferImageHeight; D3D11_BOX srcBox = {textureRegion->x, textureRegion->y, textureRegion->z, textureRegion->x + textureRegion->w, textureRegion->y + textureRegion->h, 1}; D3D11_MAPPED_SUBRESOURCE subresource; HRESULT res; @@ -2130,7 +2130,7 @@ static void D3D11_DownloadFromTexture( renderer->immediateContext, stagingTexture, 0, - copyParams->bufferOffset, + 0, 0, 0, d3d11Texture->handle, @@ -2142,43 +2142,23 @@ static void D3D11_DownloadFromTexture( res = ID3D11DeviceContext_Map( renderer->immediateContext, stagingTexture, - subresourceIndex, + 0, D3D11_MAP_READ, 0, &subresource ); ERROR_CHECK_RETURN("Could not map texture for reading",) - if (bufferStride == 0) - { - bufferStride = BytesPerRow(textureRegion->w, d3d11Texture->format); - } - if (bufferImageHeight == 0) - { - bufferImageHeight = textureRegion->h; - } - uint8_t* dataPtr = (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset; - if (bufferStride == 0 && bufferImageHeight == 0) // assume tightly packed + for (uint32_t row = textureRegion->y; row < textureRegion->h; row += 1) { SDL_memcpy( dataPtr, - (uint8_t *)subresource.pData, - BytesPerImage(textureRegion->w, textureRegion->h, d3d11Texture->format) + (uint8_t*) subresource.pData + (row * subresource.RowPitch) + (textureRegion->x * formatSize), + bufferStride ); - } - else - { - for (uint32_t row = textureRegion->y; row < bufferImageHeight; row += 1) - { - SDL_memcpy( - dataPtr, - (uint8_t*) subresource.pData + (row * bufferStride) + (textureRegion->x * formatSize), - textureRegion->w * formatSize - ); - dataPtr += textureRegion->w * formatSize; - } + dataPtr += bufferStride; } ID3D11DeviceContext1_Unmap( diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 7c24e25..743a4ee 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -10212,6 +10212,8 @@ static void VULKAN_DownloadFromTexture( vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); Refresh_Fence *fence; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer(driverData); + VulkanResourceAccessType originalTextureSliceAccessType; + VulkanResourceAccessType originalBufferAccessType; if ( transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && @@ -10224,6 +10226,9 @@ static void VULKAN_DownloadFromTexture( vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); } + originalTextureSliceAccessType = vulkanTextureSlice->resourceAccessType; + originalBufferAccessType = transferBufferContainer->activeBufferHandle->vulkanBuffer->resourceAccessType; + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, @@ -10261,6 +10266,19 @@ static void VULKAN_DownloadFromTexture( &imageCopy ); + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + originalTextureSliceAccessType, + vulkanTextureSlice + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + originalBufferAccessType, + transferBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); @@ -10283,6 +10301,8 @@ static void VULKAN_DownloadFromBuffer( VkBufferCopy bufferCopy; Refresh_Fence *fence; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer(driverData); + VulkanResourceAccessType originalTransferBufferAccessType; + VulkanResourceAccessType originalGpuBufferAccessType; if ( transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && @@ -10294,6 +10314,9 @@ static void VULKAN_DownloadFromBuffer( ); } + originalTransferBufferAccessType = transferBufferContainer->activeBufferHandle->vulkanBuffer->resourceAccessType; + originalGpuBufferAccessType = gpuBufferContainer->activeBufferHandle->vulkanBuffer->resourceAccessType; + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, @@ -10320,6 +10343,19 @@ static void VULKAN_DownloadFromBuffer( &bufferCopy ); + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + originalTransferBufferAccessType, + transferBufferContainer->activeBufferHandle->vulkanBuffer + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + originalGpuBufferAccessType, + gpuBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); -- 2.25.1 From 45e7dde067552bcb30e693335ac34c22f40a5d11 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 22:41:07 -0800 Subject: [PATCH 87/98] fix d3d11 transfer buffer allocation --- src/Refresh_Driver_D3D11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ce98c52..d421bf7 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1882,7 +1882,7 @@ static Refresh_TransferBuffer* D3D11_CreateTransferBuffer( container->bufferCapacity = 1; container->bufferCount = 1; container->buffers = SDL_malloc( - container->bufferCapacity * sizeof(D3D11TransferBuffer) + container->bufferCapacity * sizeof(D3D11TransferBuffer*) ); container->buffers[0] = transferBuffer; @@ -2741,6 +2741,7 @@ static void D3D11_QueueDestroyTransferBuffer( for (uint32_t i = 0; i < container->bufferCount; i += 1) { + SDL_free(container->buffers[i]->data); SDL_free(container->buffers[i]); } SDL_free(container->buffers); -- 2.25.1 From 548c468cc9d074fe742d4e9948841e2e0fe58bc1 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 22:45:47 -0800 Subject: [PATCH 88/98] release swapchain SRV on resize --- src/Refresh_Driver_D3D11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index d421bf7..ac7669d 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -3680,6 +3680,7 @@ static uint8_t D3D11_INTERNAL_ResizeSwapchain( int32_t height ) { /* Release the old views */ + ID3D11ShaderResourceView_Release(windowData->texture.shaderView); ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetView); ID3D11UnorderedAccessView_Release(windowData->texture.subresources[0].uav); SDL_free(windowData->texture.subresources); -- 2.25.1 From ded5dac60ae1424652b187b1114310384a85d301 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 22:48:04 -0800 Subject: [PATCH 89/98] 3d copy TODO --- src/Refresh_Driver_D3D11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ac7669d..27fce95 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -2151,6 +2151,7 @@ static void D3D11_DownloadFromTexture( uint8_t* dataPtr = (uint8_t*) d3d11TransferBuffer->data + copyParams->bufferOffset; + /* TODO: figure out 3D copy */ for (uint32_t row = textureRegion->y; row < textureRegion->h; row += 1) { SDL_memcpy( -- 2.25.1 From 75927137d623fffb6db7c313fe2dc6bc5d8c4c4e Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 5 Mar 2024 23:55:04 -0800 Subject: [PATCH 90/98] implement D3D11 MSAA targets --- src/Refresh_Driver_D3D11.c | 48 ++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 27fce95..060d6a9 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -354,6 +354,7 @@ typedef struct D3D11TextureSubresource ID3D11DepthStencilView *depthStencilTargetView; /* NULL if not a depth stencil target */ ID3D11UnorderedAccessView *uav; /* NULL if not used in compute */ ID3D11Resource *msaaHandle; /* NULL if not using MSAA */ + ID3D11RenderTargetView *msaaTargetView; /* NULL if not an MSAA color target */ uint32_t level; uint32_t layer; } D3D11TextureSubresource; @@ -1452,7 +1453,6 @@ static Refresh_Texture* D3D11_CreateTexture( uint8_t isColorTarget, isDepthStencil, isSampler, isCompute, isMultisample; DXGI_FORMAT format; ID3D11Resource *textureHandle; - ID3D11Resource *msaaHandle = NULL; ID3D11ShaderResourceView *srv = NULL; D3D11Texture *d3d11Texture; HRESULT res; @@ -1639,11 +1639,25 @@ static Refresh_Texture* D3D11_CreateTexture( { D3D11_TEXTURE2D_DESC desc2D; - desc2D.MiscFlags = 0; - desc2D.MipLevels = 1; + if (isColorTarget) + { + desc2D.BindFlags = D3D11_BIND_RENDER_TARGET; + } + else if (isDepthStencil) + { + desc2D.BindFlags = D3D11_BIND_DEPTH_STENCIL; + } + + desc2D.Width = textureCreateInfo->width; + desc2D.Height = textureCreateInfo->height; desc2D.ArraySize = 1; + desc2D.CPUAccessFlags = 0; + desc2D.Format = format; + desc2D.MipLevels = 1; + desc2D.MiscFlags = 0; desc2D.SampleDesc.Count = RefreshToD3D11_SampleCount[textureCreateInfo->sampleCount]; desc2D.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN; + desc2D.Usage = D3D11_USAGE_DEFAULT; res = ID3D11Device_CreateTexture2D( renderer->device, @@ -1652,6 +1666,22 @@ static Refresh_Texture* D3D11_CreateTexture( (ID3D11Texture2D**) &d3d11Texture->subresources[subresourceIndex].msaaHandle ); ERROR_CHECK_RETURN("Could not create MSAA texture!", NULL); + + if (!isDepthStencil) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + + rtvDesc.Format = format; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + d3d11Texture->subresources[subresourceIndex].msaaHandle, + &rtvDesc, + &d3d11Texture->subresources[subresourceIndex].msaaTargetView + ); + ERROR_CHECK_RETURN("Could not create MSAA RTV!", NULL); + } } if (d3d11Texture->isRenderTarget) @@ -2686,6 +2716,11 @@ static void D3D11_QueueDestroyTexture( ID3D11Resource_Release(d3d11Texture->subresources[subresourceIndex].msaaHandle); } + if (d3d11Texture->subresources[subresourceIndex].msaaTargetView != NULL) + { + ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].msaaTargetView); + } + if (d3d11Texture->subresources[subresourceIndex].colorTargetView != NULL) { ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].colorTargetView); @@ -2994,13 +3029,18 @@ static void D3D11_BeginRenderPass( colorAttachmentInfos[i].textureSlice.layer, texture->levelCount ); - rtvs[i] = texture->subresources[subresourceIndex].colorTargetView; if (texture->subresources[subresourceIndex].msaaHandle != NULL) { d3d11CommandBuffer->colorTargetResolveTexture[i] = texture; d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = subresourceIndex; d3d11CommandBuffer->colorTargetMsaaHandle[i] = texture->subresources[subresourceIndex].msaaHandle; + + rtvs[i] = texture->subresources[subresourceIndex].msaaTargetView; + } + else + { + rtvs[i] = texture->subresources[subresourceIndex].colorTargetView; } } -- 2.25.1 From 5db754719a7faef6b45696599f07131186047c58 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 6 Mar 2024 00:03:55 -0800 Subject: [PATCH 91/98] set msaaTargetView to NULL --- src/Refresh_Driver_D3D11.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 060d6a9..66b2713 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1632,6 +1632,7 @@ static Refresh_Texture* D3D11_CreateTexture( d3d11Texture->subresources[subresourceIndex].depthStencilTargetView = NULL; d3d11Texture->subresources[subresourceIndex].uav = NULL; d3d11Texture->subresources[subresourceIndex].msaaHandle = NULL; + d3d11Texture->subresources[subresourceIndex].msaaTargetView = NULL; d3d11Texture->subresources[subresourceIndex].layer = layerIndex; d3d11Texture->subresources[subresourceIndex].level = levelIndex; @@ -3578,6 +3579,7 @@ static uint8_t D3D11_INTERNAL_InitializeSwapchainTexture( pTexture->subresources[0].uav = uav; pTexture->subresources[0].depthStencilTargetView = NULL; pTexture->subresources[0].msaaHandle = NULL; + pTexture->subresources[0].msaaTargetView = NULL; pTexture->subresources[0].layer = 0; pTexture->subresources[0].level = 0; -- 2.25.1 From efd26f474afe22e961de02986dea3d6ab0ec5548 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 6 Mar 2024 11:32:23 -0800 Subject: [PATCH 92/98] D3D11 discard in BeginRenderPass --- src/Refresh_Driver_D3D11.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 66b2713..b1db104 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1611,7 +1611,7 @@ static Refresh_Texture* D3D11_CreateTexture( d3d11Texture->levelCount = textureCreateInfo->levelCount; d3d11Texture->layerCount = textureCreateInfo->layerCount; d3d11Texture->isCube = textureCreateInfo->isCube; - d3d11Texture->isRenderTarget = isColorTarget | isDepthStencil; + d3d11Texture->isRenderTarget = isColorTarget || isDepthStencil; d3d11Texture->shaderView = srv; d3d11Texture->subresources = SDL_malloc( @@ -3033,6 +3033,14 @@ static void D3D11_BeginRenderPass( if (texture->subresources[subresourceIndex].msaaHandle != NULL) { + if (colorAttachmentInfos[i].writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD) + { + ID3D11DeviceContext1_DiscardView( + d3d11CommandBuffer->context, + (ID3D11View*) texture->subresources[subresourceIndex].msaaTargetView + ); + } + d3d11CommandBuffer->colorTargetResolveTexture[i] = texture; d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = subresourceIndex; d3d11CommandBuffer->colorTargetMsaaHandle[i] = texture->subresources[subresourceIndex].msaaHandle; @@ -3041,6 +3049,14 @@ static void D3D11_BeginRenderPass( } else { + if (colorAttachmentInfos[i].writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD) + { + ID3D11DeviceContext1_DiscardView( + d3d11CommandBuffer->context, + (ID3D11View*) texture->subresources[subresourceIndex].colorTargetView + ); + } + rtvs[i] = texture->subresources[subresourceIndex].colorTargetView; } } @@ -3056,6 +3072,14 @@ static void D3D11_BeginRenderPass( texture->levelCount ); + if (depthStencilAttachmentInfo->writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD) + { + ID3D11DeviceContext1_DiscardView( + d3d11CommandBuffer->context, + (ID3D11View*) texture->subresources[subresourceIndex].depthStencilTargetView + ); + } + dsv = texture->subresources[subresourceIndex].depthStencilTargetView; } -- 2.25.1 From bb5752824216cc430265ea62210fb6d7189f2902 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 6 Mar 2024 14:17:43 -0800 Subject: [PATCH 93/98] reduce transfer buffer alloc count + fix use after free --- src/Refresh_Driver_D3D11.c | 122 +++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 32 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index b1db104..f2b2dc4 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1,4 +1,4 @@ -/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities +/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities * * Copyright (c) 2020 Evan Hemsley * @@ -453,7 +453,7 @@ typedef struct D3D11TransferBufferContainer */ uint32_t bufferCapacity; uint32_t bufferCount; - D3D11TransferBuffer **buffers; + D3D11TransferBuffer *buffers; } D3D11TransferBufferContainer; typedef struct D3D11UniformBuffer @@ -551,6 +551,10 @@ typedef struct D3D11Renderer uint32_t availableFenceCount; uint32_t availableFenceCapacity; + D3D11TransferBufferContainer **transferBufferContainersToDestroy; + uint32_t transferBufferContainersToDestroyCount; + uint32_t transferBufferContainersToDestroyCapacity; + SDL_mutex *contextLock; SDL_mutex *acquireCommandBufferLock; SDL_mutex *uniformBufferLock; @@ -1887,17 +1891,14 @@ static void D3D11_INTERNAL_TrackTransferBuffer( commandBuffer->usedTransferBufferCount += 1; } -static D3D11TransferBuffer* D3D11_INTERNAL_CreateTransferBuffer( +static void D3D11_INTERNAL_InitTransferBuffer( D3D11Renderer *renderer, - uint32_t sizeInBytes + uint32_t sizeInBytes, + D3D11TransferBuffer *pTransferBuffer ) { - D3D11TransferBuffer *transferBuffer = (D3D11TransferBuffer*) SDL_malloc(sizeof(D3D11TransferBuffer)); - - transferBuffer->data = (uint8_t*) SDL_malloc(sizeInBytes); - transferBuffer->size = sizeInBytes; - SDL_AtomicSet(&transferBuffer->referenceCount, 0); - - return transferBuffer; + pTransferBuffer->data = (uint8_t*) SDL_malloc(sizeInBytes); + pTransferBuffer->size = sizeInBytes; + SDL_AtomicSet(&pTransferBuffer->referenceCount, 0); } /* This actually returns a container handle so we can rotate buffers on Discard. */ @@ -1907,15 +1908,19 @@ static Refresh_TransferBuffer* D3D11_CreateTransferBuffer( ) { D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) SDL_malloc(sizeof(D3D11TransferBufferContainer)); - D3D11TransferBuffer *transferBuffer = D3D11_INTERNAL_CreateTransferBuffer(renderer, sizeInBytes); - container->activeBuffer = transferBuffer; container->bufferCapacity = 1; container->bufferCount = 1; container->buffers = SDL_malloc( - container->bufferCapacity * sizeof(D3D11TransferBuffer*) + container->bufferCapacity * sizeof(D3D11TransferBuffer) ); - container->buffers[0] = transferBuffer; + D3D11_INTERNAL_InitTransferBuffer( + renderer, + sizeInBytes, + &container->buffers[0] + ); + + container->activeBuffer = &container->buffers[0]; return (Refresh_TransferBuffer*) container; } @@ -1928,30 +1933,29 @@ static void D3D11_INTERNAL_DiscardActiveTransferBuffer( ) { for (uint32_t i = 0; i < container->bufferCount; i += 1) { - if (SDL_AtomicGet(&container->buffers[i]->referenceCount) == 0) + if (SDL_AtomicGet(&container->buffers[i].referenceCount) == 0) { - container->activeBuffer = container->buffers[i]; + container->activeBuffer = &container->buffers[i]; return; } } - container->activeBuffer = D3D11_INTERNAL_CreateTransferBuffer( - renderer, - container->activeBuffer->size - ); - EXPAND_ARRAY_IF_NEEDED( container->buffers, - D3D11TransferBuffer*, + D3D11TransferBuffer, container->bufferCount + 1, container->bufferCapacity, - container->bufferCapacity * 2 + container->bufferCapacity + 1 ); - container->buffers[ - container->bufferCapacity - ] = container->activeBuffer; + D3D11_INTERNAL_InitTransferBuffer( + renderer, + container->activeBuffer->size, + &container->buffers[container->bufferCount] + ); container->bufferCount += 1; + + container->activeBuffer = &container->buffers[container->bufferCount - 1]; } static void D3D11_SetTransferData( @@ -2774,14 +2778,34 @@ static void D3D11_QueueDestroyTransferBuffer( Refresh_Renderer *driverData, Refresh_TransferBuffer *transferBuffer ) { - D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer; + D3D11Renderer *renderer = (D3D11Renderer*) driverData; - for (uint32_t i = 0; i < container->bufferCount; i += 1) + SDL_LockMutex(renderer->contextLock); + + EXPAND_ARRAY_IF_NEEDED( + renderer->transferBufferContainersToDestroy, + D3D11TransferBufferContainer*, + renderer->transferBufferContainersToDestroyCount + 1, + renderer->transferBufferContainersToDestroyCapacity, + renderer->transferBufferContainersToDestroyCapacity + 1 + ); + + renderer->transferBufferContainersToDestroy[ + renderer->transferBufferContainersToDestroyCount + ] = (D3D11TransferBufferContainer*) transferBuffer; + renderer->transferBufferContainersToDestroyCount += 1; + + SDL_UnlockMutex(renderer->contextLock); +} + +static void D3D11_INTERNAL_DestroyTransferBufferContainer( + D3D11TransferBufferContainer *transferBufferContainer +) { + for (uint32_t i = 0; i < transferBufferContainer->bufferCount; i += 1) { - SDL_free(container->buffers[i]->data); - SDL_free(container->buffers[i]); + SDL_free(transferBufferContainer->buffers[i].data); } - SDL_free(container->buffers); + SDL_free(transferBufferContainer->buffers); } static void D3D11_QueueDestroyShaderModule( @@ -4035,6 +4059,29 @@ static void D3D11_INTERNAL_WaitForFence( SDL_UnlockMutex(renderer->contextLock); } +static void D3D11_INTERNAL_PerformPendingDestroys( + D3D11Renderer *renderer +) { + for (int32_t i = renderer->transferBufferContainersToDestroyCount - 1; i >= 0; i -= 1) + { + int32_t referenceCount = 0; + for (uint32_t j = 0; j < renderer->transferBufferContainersToDestroy[i]->bufferCount; j += 1) + { + referenceCount += SDL_AtomicGet(&renderer->transferBufferContainersToDestroy[i]->buffers[j].referenceCount); + } + + if (referenceCount == 0) + { + D3D11_INTERNAL_DestroyTransferBufferContainer( + renderer->transferBufferContainersToDestroy[i] + ); + + renderer->transferBufferContainersToDestroy[i] = renderer->transferBufferContainersToDestroy[renderer->transferBufferContainersToDestroyCount - 1]; + renderer->transferBufferContainersToDestroyCount -= 1; + } + } +} + static void D3D11_Submit( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer @@ -4130,6 +4177,8 @@ static void D3D11_Submit( } } + D3D11_INTERNAL_PerformPendingDestroys(renderer); + SDL_UnlockMutex(renderer->contextLock); } @@ -4172,6 +4221,8 @@ static void D3D11_Wait( D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer); } + D3D11_INTERNAL_PerformPendingDestroys(renderer); + SDL_UnlockMutex(renderer->contextLock); } @@ -4636,6 +4687,13 @@ tryCreateDevice: sizeof(D3D11Fence*) * renderer->availableFenceCapacity ); + /* Create deferred transfer array */ + renderer->transferBufferContainersToDestroyCapacity = 2; + renderer->transferBufferContainersToDestroyCount = 0; + renderer->transferBufferContainersToDestroy = SDL_malloc( + renderer->transferBufferContainersToDestroyCapacity * sizeof(D3D11TransferBufferContainer*) + ); + /* Create claimed window list */ renderer->claimedWindowCapacity = 1; renderer->claimedWindows = SDL_malloc( -- 2.25.1 From 1dcf29eed40c24bb38030d79081e1dfee1f23814 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 6 Mar 2024 14:17:55 -0800 Subject: [PATCH 94/98] fix texture 2d array SRV --- src/Refresh_Driver_D3D11.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index f2b2dc4..168394c 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1,4 +1,4 @@ -/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities +/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities * * Copyright (c) 2020 Evan Hemsley * @@ -1526,6 +1526,14 @@ static Refresh_Texture* D3D11_CreateTexture( srvDesc.TextureCube.MipLevels = desc2D.MipLevels; srvDesc.TextureCube.MostDetailedMip = 0; } + else if (textureCreateInfo->layerCount > 1) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MipLevels = desc2D.MipLevels; + srvDesc.Texture2DArray.MostDetailedMip = 0; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = textureCreateInfo->layerCount; + } else { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; -- 2.25.1 From d3d5a5a52560d25c9754fceaad6abe4300fc8f79 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 6 Mar 2024 14:29:53 -0800 Subject: [PATCH 95/98] don't re-track transfer buffers on same command buffer --- src/Refresh_Driver_D3D11.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 168394c..ab682cf 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -1883,6 +1883,14 @@ static void D3D11_INTERNAL_TrackTransferBuffer( D3D11CommandBuffer *commandBuffer, D3D11TransferBuffer *buffer ) { + for (uint32_t i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) + { + if (commandBuffer->usedTransferBuffers[i] == buffer) + { + return; + } + } + EXPAND_ARRAY_IF_NEEDED( commandBuffer->usedTransferBuffers, D3D11TransferBuffer*, -- 2.25.1 From 397e84fe4af1187abd30e0da5face74366be14ee Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 6 Mar 2024 22:42:01 -0800 Subject: [PATCH 96/98] workaround for broken d3d11 constant buffer updates --- src/Refresh_Driver_D3D11.c | 115 +++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index ab682cf..a8a5cb3 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -53,7 +53,7 @@ #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" #define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface" #define WINDOW_DATA "Refresh_D3D11WindowData" -#define UBO_BUFFER_SIZE 16000 /* 16KB */ +#define UBO_BUFFER_SIZE 1048576 /* 1 MiB */ #define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!"); @@ -458,10 +458,9 @@ typedef struct D3D11TransferBufferContainer typedef struct D3D11UniformBuffer { - D3D11Buffer *d3d11Buffer; + D3D11Buffer d3d11Buffer; uint32_t offset; /* number of bytes written */ uint32_t drawOffset; /* parameter for SetConstantBuffers */ - uint8_t hasDiscarded; } D3D11UniformBuffer; typedef struct D3D11Fence @@ -707,8 +706,7 @@ static void D3D11_DestroyDevice( for (uint32_t i = 0; i < renderer->availableUniformBufferCount; i += 1) { D3D11UniformBuffer *uniformBuffer = renderer->availableUniformBuffers[i]; - ID3D11Buffer_Release(uniformBuffer->d3d11Buffer->handle); - SDL_free(uniformBuffer->d3d11Buffer); + ID3D11Buffer_Release(uniformBuffer->d3d11Buffer.handle); SDL_free(uniformBuffer); } SDL_free(renderer->availableUniformBuffers); @@ -781,13 +779,25 @@ static void D3D11_DrawInstancedPrimitives( uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; + ID3D11Buffer *nullBuf = NULL; + if (d3d11CommandBuffer->vertexUniformBuffer != NULL) { + /* stupid workaround for god awful D3D11 drivers + * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation + */ + ID3D11DeviceContext1_VSSetConstantBuffers( + d3d11CommandBuffer->context, + 0, + 1, + &nullBuf + ); + ID3D11DeviceContext1_VSSetConstantBuffers1( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle, + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer.handle, &vertexOffsetInConstants, &vertexBlockSizeInConstants ); @@ -795,11 +805,19 @@ static void D3D11_DrawInstancedPrimitives( if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) { + /* another stupid workaround for god awful D3D11 drivers */ + ID3D11DeviceContext1_PSSetConstantBuffers( + d3d11CommandBuffer->context, + 0, + 1, + &nullBuf + ); + ID3D11DeviceContext1_PSSetConstantBuffers1( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle, + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer.handle, &fragmentOffsetInConstants, &fragmentBlockSizeInConstants ); @@ -850,7 +868,7 @@ static void D3D11_DrawPrimitives( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle, + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer.handle, &vertexOffsetInConstants, &vertexBlockSizeInConstants ); @@ -862,7 +880,7 @@ static void D3D11_DrawPrimitives( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle, + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer.handle, &fragmentOffsetInConstants, &fragmentBlockSizeInConstants ); @@ -896,7 +914,7 @@ static void D3D11_DrawPrimitivesIndirect( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer->handle, + &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer.handle, &vertexOffsetInConstants, &vertexBlockSizeInConstants ); @@ -908,7 +926,7 @@ static void D3D11_DrawPrimitivesIndirect( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer->handle, + &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer.handle, &fragmentOffsetInConstants, &fragmentBlockSizeInConstants ); @@ -938,13 +956,23 @@ static void D3D11_DispatchCompute( uint32_t computeOffsetInConstants = d3d11CommandBuffer->computeUniformBuffer != NULL ? d3d11CommandBuffer->computeUniformBuffer->drawOffset / 16 : 0; uint32_t computeBlockSizeInConstants = (uint32_t) (d3d11CommandBuffer->computePipeline->computeUniformBlockSize / 16); + ID3D11Buffer *nullBuf = NULL; + if (d3d11CommandBuffer->computeUniformBuffer != NULL) { + /* another stupid workaround for god awful D3D11 drivers */ + ID3D11DeviceContext1_CSSetConstantBuffers( + d3d11CommandBuffer->context, + 0, + 1, + &nullBuf + ); + ID3D11DeviceContext1_CSSetConstantBuffers1( d3d11CommandBuffer->context, 0, 1, - &d3d11CommandBuffer->computeUniformBuffer->d3d11Buffer->handle, + &d3d11CommandBuffer->computeUniformBuffer->d3d11Buffer.handle, &computeOffsetInConstants, &computeBlockSizeInConstants ); @@ -2417,10 +2445,10 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bufferDesc.ByteWidth = UBO_BUFFER_SIZE; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; res = ID3D11Device_CreateBuffer( renderer->device, @@ -2433,11 +2461,9 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer)); uniformBuffer->offset = 0; uniformBuffer->drawOffset = 0; - uniformBuffer->hasDiscarded = 0; - uniformBuffer->d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); - uniformBuffer->d3d11Buffer->handle = bufferHandle; - uniformBuffer->d3d11Buffer->size = UBO_BUFFER_SIZE; - uniformBuffer->d3d11Buffer->uav = NULL; + uniformBuffer->d3d11Buffer.handle = bufferHandle; + uniformBuffer->d3d11Buffer.size = UBO_BUFFER_SIZE; + uniformBuffer->d3d11Buffer.uav = NULL; /* Add it to the available pool */ if (renderer->availableUniformBufferCount >= renderer->availableUniformBufferCapacity) @@ -2483,7 +2509,6 @@ static uint8_t D3D11_INTERNAL_AcquireUniformBuffer( SDL_UnlockMutex(renderer->uniformBufferLock); /* Reset the uniform buffer */ - uniformBuffer->hasDiscarded = 0; uniformBuffer->offset = 0; uniformBuffer->drawOffset = 0; @@ -2511,31 +2536,18 @@ static void D3D11_INTERNAL_SetUniformBufferData( void* data, uint32_t dataLength ) { - D3D11_MAPPED_SUBRESOURCE subres; + D3D11_BOX dstBox = { uniformBuffer->offset, 0, 0, uniformBuffer->offset + dataLength, 1, 1 }; - HRESULT res = ID3D11DeviceContext_Map( + ID3D11DeviceContext1_UpdateSubresource1( commandBuffer->context, - (ID3D11Resource*) uniformBuffer->d3d11Buffer->handle, + (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, + &dstBox, data, - dataLength + 0, + 0, + uniformBuffer->offset == 0 ? D3D11_COPY_DISCARD : D3D11_COPY_NO_OVERWRITE ); - - ID3D11DeviceContext_Unmap( - commandBuffer->context, - (ID3D11Resource*) uniformBuffer->d3d11Buffer->handle, - 0 - ); - - uniformBuffer->hasDiscarded = 1; } static void D3D11_PushVertexShaderUniforms( @@ -3274,11 +3286,8 @@ static void D3D11_BindGraphicsPipeline( d3d11CommandBuffer->graphicsPipeline = pipeline; - if (pipeline->vertexUniformBlockSize == 0) - { - d3d11CommandBuffer->vertexUniformBuffer = NULL; - } - else + /* Get a vertex uniform buffer if we need one */ + if (d3d11CommandBuffer->vertexUniformBuffer == NULL && pipeline->vertexUniformBlockSize > 0) { D3D11_INTERNAL_AcquireUniformBuffer( renderer, @@ -3288,11 +3297,8 @@ static void D3D11_BindGraphicsPipeline( ); } - if (pipeline->fragmentUniformBlockSize == 0) - { - d3d11CommandBuffer->fragmentUniformBuffer = NULL; - } - else + /* Get a fragment uniform buffer if we need one */ + if (d3d11CommandBuffer->fragmentUniformBuffer == NULL && pipeline->fragmentUniformBlockSize > 0) { D3D11_INTERNAL_AcquireUniformBuffer( renderer, @@ -3455,11 +3461,8 @@ static void D3D11_BindComputePipeline( d3d11CommandBuffer->computePipeline = pipeline; - if (pipeline->computeUniformBlockSize == 0) - { - d3d11CommandBuffer->computeUniformBuffer = NULL; - } - else + /* Get a compute uniform buffer if we need one */ + if (d3d11CommandBuffer->computeUniformBuffer == NULL && pipeline->computeUniformBlockSize > 0) { D3D11_INTERNAL_AcquireUniformBuffer( renderer, @@ -4692,7 +4695,7 @@ tryCreateDevice: D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2); /* Create uniform buffer pool */ - renderer->availableUniformBufferCapacity = 2; + renderer->availableUniformBufferCapacity = 16; renderer->availableUniformBuffers = SDL_malloc( sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity ); -- 2.25.1 From a80f3f40dd77122b9244f9a10924907d553f6891 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 6 Mar 2024 23:55:37 -0800 Subject: [PATCH 97/98] more d3d11 constant buffer fixes --- src/Refresh_Driver_D3D11.c | 204 +++++++++++++++---------------------- 1 file changed, 81 insertions(+), 123 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index a8a5cb3..89b546a 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -765,6 +765,58 @@ static void D3D11_DestroyDevice( /* Drawing */ +static void D3D11_SetGraphicsConstantBuffers( + D3D11CommandBuffer *commandBuffer +) { + uint32_t vertexOffsetInConstants = commandBuffer->vertexUniformBuffer != NULL ? commandBuffer->vertexUniformBuffer->drawOffset / 16 : 0; + uint32_t fragmentOffsetInConstants = commandBuffer->fragmentUniformBuffer != NULL ? commandBuffer->fragmentUniformBuffer->drawOffset / 16 : 0; + uint32_t vertexBlockSizeInConstants = commandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; + uint32_t fragmentBlockSizeInConstants = commandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; + ID3D11Buffer *nullBuf = NULL; + + if (commandBuffer->vertexUniformBuffer != NULL) + { + /* stupid workaround for god awful D3D11 drivers + * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation + */ + ID3D11DeviceContext1_VSSetConstantBuffers( + commandBuffer->context, + 0, + 1, + &nullBuf + ); + + ID3D11DeviceContext1_VSSetConstantBuffers1( + commandBuffer->context, + 0, + 1, + &commandBuffer->vertexUniformBuffer->d3d11Buffer.handle, + &vertexOffsetInConstants, + &vertexBlockSizeInConstants + ); + } + + if (commandBuffer->fragmentUniformBuffer != NULL) + { + /* another stupid workaround for god awful D3D11 drivers */ + ID3D11DeviceContext1_PSSetConstantBuffers( + commandBuffer->context, + 0, + 1, + &nullBuf + ); + + ID3D11DeviceContext1_PSSetConstantBuffers1( + commandBuffer->context, + 0, + 1, + &commandBuffer->fragmentUniformBuffer->d3d11Buffer.handle, + &fragmentOffsetInConstants, + &fragmentBlockSizeInConstants + ); + } +} + static void D3D11_DrawInstancedPrimitives( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -774,54 +826,8 @@ static void D3D11_DrawInstancedPrimitives( uint32_t instanceCount ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer != NULL ? d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16 : 0; - uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer != NULL ? d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16 : 0; - uint32_t vertexBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->vertexUniformBlockSize / 16; - uint32_t fragmentBlockSizeInConstants = d3d11CommandBuffer->graphicsPipeline->fragmentUniformBlockSize / 16; - ID3D11Buffer *nullBuf = NULL; - - if (d3d11CommandBuffer->vertexUniformBuffer != NULL) - { - /* stupid workaround for god awful D3D11 drivers - * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation - */ - ID3D11DeviceContext1_VSSetConstantBuffers( - d3d11CommandBuffer->context, - 0, - 1, - &nullBuf - ); - - ID3D11DeviceContext1_VSSetConstantBuffers1( - d3d11CommandBuffer->context, - 0, - 1, - &d3d11CommandBuffer->vertexUniformBuffer->d3d11Buffer.handle, - &vertexOffsetInConstants, - &vertexBlockSizeInConstants - ); - } - - if (d3d11CommandBuffer->fragmentUniformBuffer != NULL) - { - /* another stupid workaround for god awful D3D11 drivers */ - ID3D11DeviceContext1_PSSetConstantBuffers( - d3d11CommandBuffer->context, - 0, - 1, - &nullBuf - ); - - ID3D11DeviceContext1_PSSetConstantBuffers1( - d3d11CommandBuffer->context, - 0, - 1, - &d3d11CommandBuffer->fragmentUniformBuffer->d3d11Buffer.handle, - &fragmentOffsetInConstants, - &fragmentBlockSizeInConstants - ); - } + D3D11_SetGraphicsConstantBuffers(d3d11CommandBuffer); ID3D11DeviceContext_DrawIndexedInstanced( d3d11CommandBuffer->context, @@ -857,34 +863,8 @@ static void D3D11_DrawPrimitives( uint32_t primitiveCount ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; - uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer != NULL ? d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16 : 0; - uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer != NULL ? d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16 : 0; - 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_SetGraphicsConstantBuffers(d3d11CommandBuffer); ID3D11DeviceContext_Draw( d3d11CommandBuffer->context, @@ -903,34 +883,8 @@ static void D3D11_DrawPrimitivesIndirect( ) { D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer; D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer; - uint32_t vertexOffsetInConstants = d3d11CommandBuffer->vertexUniformBuffer != NULL ? d3d11CommandBuffer->vertexUniformBuffer->drawOffset / 16 : 0; - uint32_t fragmentOffsetInConstants = d3d11CommandBuffer->fragmentUniformBuffer != NULL ? d3d11CommandBuffer->fragmentUniformBuffer->drawOffset / 16 : 0; - 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_SetGraphicsConstantBuffers(d3d11CommandBuffer); /* D3D11: "We have multi-draw at home!" * Multi-draw at home: @@ -2445,10 +2399,10 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bufferDesc.ByteWidth = UBO_BUFFER_SIZE; - bufferDesc.CPUAccessFlags = 0; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; - bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; res = ID3D11Device_CreateBuffer( renderer->device, @@ -2485,8 +2439,7 @@ static uint8_t D3D11_INTERNAL_CreateUniformBuffer( static uint8_t D3D11_INTERNAL_AcquireUniformBuffer( D3D11Renderer *renderer, D3D11CommandBuffer *commandBuffer, - D3D11UniformBuffer **uniformBufferToBind, - uint64_t blockSize + D3D11UniformBuffer **uniformBufferToBind ) { D3D11UniformBuffer *uniformBuffer; @@ -2536,17 +2489,28 @@ static void D3D11_INTERNAL_SetUniformBufferData( void* data, uint32_t dataLength ) { - D3D11_BOX dstBox = { uniformBuffer->offset, 0, 0, uniformBuffer->offset + dataLength, 1, 1 }; + D3D11_MAPPED_SUBRESOURCE subres; - ID3D11DeviceContext1_UpdateSubresource1( + HRESULT res = ID3D11DeviceContext_Map( commandBuffer->context, (ID3D11Resource*) uniformBuffer->d3d11Buffer.handle, 0, - &dstBox, + uniformBuffer->offset == 0 ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE, + 0, + &subres + ); + ERROR_CHECK_RETURN("Could not map buffer for writing!", ); + + SDL_memcpy( + (uint8_t*) subres.pData + uniformBuffer->offset, data, - 0, - 0, - uniformBuffer->offset == 0 ? D3D11_COPY_DISCARD : D3D11_COPY_NO_OVERWRITE + dataLength + ); + + ID3D11DeviceContext_Unmap( + commandBuffer->context, + (ID3D11Resource*) uniformBuffer->d3d11Buffer.handle, + 0 ); } @@ -2566,8 +2530,7 @@ static void D3D11_PushVertexShaderUniforms( D3D11_INTERNAL_AcquireUniformBuffer( renderer, d3d11CommandBuffer, - &d3d11CommandBuffer->vertexUniformBuffer, - graphicsPipeline->vertexUniformBlockSize + &d3d11CommandBuffer->vertexUniformBuffer ); } @@ -2600,8 +2563,7 @@ static void D3D11_PushFragmentShaderUniforms( D3D11_INTERNAL_AcquireUniformBuffer( renderer, d3d11CommandBuffer, - &d3d11CommandBuffer->fragmentUniformBuffer, - graphicsPipeline->fragmentUniformBlockSize + &d3d11CommandBuffer->fragmentUniformBuffer ); } @@ -2634,8 +2596,7 @@ static void D3D11_PushComputeShaderUniforms( D3D11_INTERNAL_AcquireUniformBuffer( renderer, d3d11CommandBuffer, - &d3d11CommandBuffer->computeUniformBuffer, - computePipeline->computeUniformBlockSize + &d3d11CommandBuffer->computeUniformBuffer ); } @@ -3292,8 +3253,7 @@ static void D3D11_BindGraphicsPipeline( D3D11_INTERNAL_AcquireUniformBuffer( renderer, d3d11CommandBuffer, - &d3d11CommandBuffer->vertexUniformBuffer, - pipeline->vertexUniformBlockSize + &d3d11CommandBuffer->vertexUniformBuffer ); } @@ -3303,8 +3263,7 @@ static void D3D11_BindGraphicsPipeline( D3D11_INTERNAL_AcquireUniformBuffer( renderer, d3d11CommandBuffer, - &d3d11CommandBuffer->fragmentUniformBuffer, - pipeline->fragmentUniformBlockSize + &d3d11CommandBuffer->fragmentUniformBuffer ); } @@ -3467,8 +3426,7 @@ static void D3D11_BindComputePipeline( D3D11_INTERNAL_AcquireUniformBuffer( renderer, d3d11CommandBuffer, - &d3d11CommandBuffer->computeUniformBuffer, - pipeline->computeUniformBlockSize + &d3d11CommandBuffer->computeUniformBuffer ); } -- 2.25.1 From 856a7004aecd9718626f64db32f370784925a42b Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 7 Mar 2024 00:16:11 -0800 Subject: [PATCH 98/98] DiscardView is broken on cubemap faces so whatever --- src/Refresh_Driver_D3D11.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/Refresh_Driver_D3D11.c b/src/Refresh_Driver_D3D11.c index 89b546a..a11621b 100644 --- a/src/Refresh_Driver_D3D11.c +++ b/src/Refresh_Driver_D3D11.c @@ -3046,14 +3046,6 @@ static void D3D11_BeginRenderPass( if (texture->subresources[subresourceIndex].msaaHandle != NULL) { - if (colorAttachmentInfos[i].writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD) - { - ID3D11DeviceContext1_DiscardView( - d3d11CommandBuffer->context, - (ID3D11View*) texture->subresources[subresourceIndex].msaaTargetView - ); - } - d3d11CommandBuffer->colorTargetResolveTexture[i] = texture; d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = subresourceIndex; d3d11CommandBuffer->colorTargetMsaaHandle[i] = texture->subresources[subresourceIndex].msaaHandle; @@ -3062,14 +3054,6 @@ static void D3D11_BeginRenderPass( } else { - if (colorAttachmentInfos[i].writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD) - { - ID3D11DeviceContext1_DiscardView( - d3d11CommandBuffer->context, - (ID3D11View*) texture->subresources[subresourceIndex].colorTargetView - ); - } - rtvs[i] = texture->subresources[subresourceIndex].colorTargetView; } } -- 2.25.1