diff --git a/.gitmodules b/.gitmodules index 347b3728..42caa0fb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,6 +2,3 @@ path = MojoShader url = https://github.com/icculus/mojoshader branch = main -[submodule "Vulkan-Headers"] - path = Vulkan-Headers - url = https://github.com/KhronosGroup/Vulkan-Headers diff --git a/CMakeLists.txt b/CMakeLists.txt index b05354f2..935f623e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ endif() # Defines add_definitions( - -DFNA3D_DRIVER_VULKAN -DFNA3D_DRIVER_OPENGL ) if(BUILD_SDL3) @@ -88,9 +87,6 @@ else() endif() if(EMSCRIPTEN) - remove_definitions( - -DFNA3D_DRIVER_VULKAN - ) add_definitions( -DSUPPORT_PROFILE_GLSPIRV=0 -DSUPPORT_PROFILE_SPIRV=0 @@ -112,19 +108,13 @@ add_library(FNA3D src/FNA3D_Driver.h src/FNA3D_Driver_OpenGL.h src/FNA3D_Driver_OpenGL_glfuncs.h - src/FNA3D_Driver_Vulkan_vkfuncs.h - src/FNA3D_CommandBuffer.h - src/FNA3D_Memory.h src/FNA3D_PipelineCache.h # Source Files src/FNA3D.c src/FNA3D_Driver_D3D11.c src/FNA3D_Driver_OpenGL.c src/FNA3D_Driver_SDL.c - src/FNA3D_Driver_Vulkan.c src/FNA3D_Image.c - src/FNA3D_CommandBuffer.c - src/FNA3D_Memory.c src/FNA3D_PipelineCache.c src/FNA3D_Tracing.c ) @@ -134,7 +124,6 @@ add_library(mojoshader STATIC MojoShader/mojoshader_common.c MojoShader/mojoshader_d3d11.c MojoShader/mojoshader_opengl.c - MojoShader/mojoshader_vulkan.c MojoShader/mojoshader_sdlgpu.c MojoShader/profiles/mojoshader_profile_common.c MojoShader/profiles/mojoshader_profile_glsl.c @@ -162,7 +151,6 @@ endif() target_include_directories(FNA3D PUBLIC $ $ - $ ) if(BUILD_DXVK_NATIVE) add_definitions(-DFNA3D_DXVK_NATIVE) @@ -171,7 +159,6 @@ if(BUILD_DXVK_NATIVE) endif() target_include_directories(mojoshader PUBLIC $ - $ ) # MinGW builds should statically link libgcc diff --git a/README b/README index db096fdd..3cfd5d77 100644 --- a/README +++ b/README @@ -10,8 +10,8 @@ About FNA3D ----------- FNA3D was written to be used for FNA's Graphics namespace. It carries the same API design as XNA 4.0, with various implementations available at runtime -(including Vulkan, OpenGL, Metal via MoltenVK, and Direct3D). For shaders, -we support Direct3D 9 Effect Framework binaries via MojoShader. +(including SDL_GPU, OpenGL, and Direct3D). For shaders, we support Direct3D 9 +Effect Framework binaries via MojoShader. Note that while FNA is the main consumer of FNA3D, we do NOT provide separate C# bindings. If you want to use FNA3D in C#, simply use FNA instead; it's the same diff --git a/Vulkan-Headers b/Vulkan-Headers deleted file mode 160000 index 85470b32..00000000 --- a/Vulkan-Headers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 85470b32ad5d0d7d67fdf411b6e7b502c09c9c52 diff --git a/Xcode/FNA3D.xcodeproj/project.pbxproj b/Xcode/FNA3D.xcodeproj/project.pbxproj index 23bea2df..3ecc8fc8 100644 --- a/Xcode/FNA3D.xcodeproj/project.pbxproj +++ b/Xcode/FNA3D.xcodeproj/project.pbxproj @@ -7,10 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 021FF3972A4A764500A63B55 /* FNA3D_Memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 021FF3962A4A764500A63B55 /* FNA3D_Memory.c */; }; - 021FF3982A4A764500A63B55 /* FNA3D_Memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 021FF3962A4A764500A63B55 /* FNA3D_Memory.c */; }; - 02FD608F2A7B227300E1D7A5 /* FNA3D_CommandBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 02FD608E2A7B227300E1D7A5 /* FNA3D_CommandBuffer.c */; }; - 02FD60902A7B227300E1D7A5 /* FNA3D_CommandBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 02FD608E2A7B227300E1D7A5 /* FNA3D_CommandBuffer.c */; }; 7B8B6CBE24452690001C08D6 /* mojoshader_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B8B6CB824452690001C08D6 /* mojoshader_common.c */; }; 7B8B6CBF24452690001C08D6 /* mojoshader_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B8B6CB824452690001C08D6 /* mojoshader_common.c */; }; 7B8B6CC224452690001C08D6 /* mojoshader.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B8B6CBA24452690001C08D6 /* mojoshader.c */; }; @@ -25,15 +21,11 @@ 7BC01C072B4348F300941563 /* mojoshader_profile_spirv.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B9F275C046100050413 /* mojoshader_profile_spirv.c */; }; 7BC01C082B4348F300941563 /* mojoshader.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B8B6CBA24452690001C08D6 /* mojoshader.c */; }; 7BC01C092B4348F300941563 /* mojoshader_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B8B6CB824452690001C08D6 /* mojoshader_common.c */; }; - 7BC01C0A2B4348F300941563 /* mojoshader_vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B9C275C044E00050413 /* mojoshader_vulkan.c */; }; 7BC01C0B2B4348F300941563 /* mojoshader_profile_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B8B6CC6244526A7001C08D6 /* mojoshader_profile_common.c */; }; 7BC01C0C2B4348F300941563 /* mojoshader_effects.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B8B6CBB24452690001C08D6 /* mojoshader_effects.c */; }; - 7BC01C0D2B4348F700941563 /* FNA3D_Driver_Vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B99275C042200050413 /* FNA3D_Driver_Vulkan.c */; }; - 7BC01C0E2B4348F700941563 /* FNA3D_CommandBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 02FD608E2A7B227300E1D7A5 /* FNA3D_CommandBuffer.c */; }; 7BC01C0F2B4348F700941563 /* FNA3D_Image.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF8206C2445254300736AB0 /* FNA3D_Image.c */; }; 7BC01C102B4348F700941563 /* FNA3D_PipelineCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF8206E2445254300736AB0 /* FNA3D_PipelineCache.c */; }; 7BC01C112B4348F700941563 /* FNA3D.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF820682445254300736AB0 /* FNA3D.c */; }; - 7BC01C122B4348F700941563 /* FNA3D_Memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 021FF3962A4A764500A63B55 /* FNA3D_Memory.c */; }; 7BC01C142B43490100941563 /* FNA3D_Driver_OpenGL.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BC01C132B43490100941563 /* FNA3D_Driver_OpenGL.c */; }; 7BF820702445254300736AB0 /* FNA3D.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF820682445254300736AB0 /* FNA3D.c */; }; 7BF820712445254300736AB0 /* FNA3D.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF820682445254300736AB0 /* FNA3D.c */; }; @@ -41,10 +33,6 @@ 7BF820792445254300736AB0 /* FNA3D_Image.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF8206C2445254300736AB0 /* FNA3D_Image.c */; }; 7BF8207C2445254300736AB0 /* FNA3D_PipelineCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF8206E2445254300736AB0 /* FNA3D_PipelineCache.c */; }; 7BF8207D2445254300736AB0 /* FNA3D_PipelineCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF8206E2445254300736AB0 /* FNA3D_PipelineCache.c */; }; - 7BF94B9A275C042200050413 /* FNA3D_Driver_Vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B99275C042200050413 /* FNA3D_Driver_Vulkan.c */; }; - 7BF94B9B275C042200050413 /* FNA3D_Driver_Vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B99275C042200050413 /* FNA3D_Driver_Vulkan.c */; }; - 7BF94B9D275C044E00050413 /* mojoshader_vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B9C275C044E00050413 /* mojoshader_vulkan.c */; }; - 7BF94B9E275C044E00050413 /* mojoshader_vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B9C275C044E00050413 /* mojoshader_vulkan.c */; }; 7BF94BA0275C046100050413 /* mojoshader_profile_spirv.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B9F275C046100050413 /* mojoshader_profile_spirv.c */; }; 7BF94BA1275C046100050413 /* mojoshader_profile_spirv.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF94B9F275C046100050413 /* mojoshader_profile_spirv.c */; }; /* End PBXBuildFile section */ @@ -151,9 +139,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 021FF3962A4A764500A63B55 /* FNA3D_Memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FNA3D_Memory.c; path = ../src/FNA3D_Memory.c; sourceTree = ""; }; - 02FD608D2A7B226300E1D7A5 /* FNA3D_CommandBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FNA3D_CommandBuffer.h; path = ../src/FNA3D_CommandBuffer.h; sourceTree = ""; }; - 02FD608E2A7B227300E1D7A5 /* FNA3D_CommandBuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FNA3D_CommandBuffer.c; path = ../src/FNA3D_CommandBuffer.c; sourceTree = ""; }; 7B1CDD452190C0A200175C7B /* libFNA3D.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFNA3D.a; sourceTree = BUILT_PRODUCTS_DIR; }; 7B7E140D2190E0CB00616654 /* libFNA3D.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFNA3D.a; sourceTree = BUILT_PRODUCTS_DIR; }; 7B81CE172B434A04007EC76D /* SDL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL.xcodeproj; path = ../../SDL2/Xcode/SDL/SDL.xcodeproj; sourceTree = ""; }; @@ -171,8 +156,6 @@ 7BF820682445254300736AB0 /* FNA3D.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FNA3D.c; path = ../src/FNA3D.c; sourceTree = ""; }; 7BF8206C2445254300736AB0 /* FNA3D_Image.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FNA3D_Image.c; path = ../src/FNA3D_Image.c; sourceTree = ""; }; 7BF8206E2445254300736AB0 /* FNA3D_PipelineCache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FNA3D_PipelineCache.c; path = ../src/FNA3D_PipelineCache.c; sourceTree = ""; }; - 7BF94B99275C042200050413 /* FNA3D_Driver_Vulkan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FNA3D_Driver_Vulkan.c; path = ../src/FNA3D_Driver_Vulkan.c; sourceTree = ""; }; - 7BF94B9C275C044E00050413 /* mojoshader_vulkan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mojoshader_vulkan.c; path = ../MojoShader/mojoshader_vulkan.c; sourceTree = ""; }; 7BF94B9F275C046100050413 /* mojoshader_profile_spirv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mojoshader_profile_spirv.c; path = ../MojoShader/profiles/mojoshader_profile_spirv.c; sourceTree = ""; }; /* End PBXFileReference section */ @@ -227,9 +210,6 @@ 7B1CDDA62190C50300175C7B /* Library Source */ = { isa = PBXGroup; children = ( - 02FD608E2A7B227300E1D7A5 /* FNA3D_CommandBuffer.c */, - 021FF3962A4A764500A63B55 /* FNA3D_Memory.c */, - 7BF94B99275C042200050413 /* FNA3D_Driver_Vulkan.c */, 7BC01C132B43490100941563 /* FNA3D_Driver_OpenGL.c */, 7BF8206C2445254300736AB0 /* FNA3D_Image.c */, 7BF8206E2445254300736AB0 /* FNA3D_PipelineCache.c */, @@ -241,7 +221,6 @@ 7B1CDDA72190C52900175C7B /* Public Headers */ = { isa = PBXGroup; children = ( - 02FD608D2A7B226300E1D7A5 /* FNA3D_CommandBuffer.h */, 7BF820652445251D00736AB0 /* FNA3D_SysRenderer.h */, 7BF820662445251D00736AB0 /* FNA3D_Image.h */, 7BF820672445251D00736AB0 /* FNA3D.h */, @@ -273,7 +252,6 @@ 7BC01C052B4348EC00941563 /* mojoshader_profile_glsl.c */, 7BC01C032B4348CD00941563 /* mojoshader_opengl.c */, 7BF94B9F275C046100050413 /* mojoshader_profile_spirv.c */, - 7BF94B9C275C044E00050413 /* mojoshader_vulkan.c */, 7B8B6CC6244526A7001C08D6 /* mojoshader_profile_common.c */, 7B8B6CB824452690001C08D6 /* mojoshader_common.c */, 7B8B6CBB24452690001C08D6 /* mojoshader_effects.c */, @@ -483,14 +461,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 021FF3972A4A764500A63B55 /* FNA3D_Memory.c in Sources */, 7BF94BA0275C046100050413 /* mojoshader_profile_spirv.c in Sources */, 7B8B6CC9244526A7001C08D6 /* mojoshader_profile_common.c in Sources */, - 7BF94B9A275C042200050413 /* FNA3D_Driver_Vulkan.c in Sources */, 7B8B6CC224452690001C08D6 /* mojoshader.c in Sources */, 7B8B6CC424452690001C08D6 /* mojoshader_effects.c in Sources */, - 02FD608F2A7B227300E1D7A5 /* FNA3D_CommandBuffer.c in Sources */, - 7BF94B9D275C044E00050413 /* mojoshader_vulkan.c in Sources */, 7BF820702445254300736AB0 /* FNA3D.c in Sources */, 7B8B6CBE24452690001C08D6 /* mojoshader_common.c in Sources */, 7BF8207C2445254300736AB0 /* FNA3D_PipelineCache.c in Sources */, @@ -502,14 +476,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 021FF3982A4A764500A63B55 /* FNA3D_Memory.c in Sources */, 7BF94BA1275C046100050413 /* mojoshader_profile_spirv.c in Sources */, 7B8B6CCA244526A7001C08D6 /* mojoshader_profile_common.c in Sources */, - 7BF94B9B275C042200050413 /* FNA3D_Driver_Vulkan.c in Sources */, 7B8B6CC324452690001C08D6 /* mojoshader.c in Sources */, 7B8B6CC524452690001C08D6 /* mojoshader_effects.c in Sources */, - 02FD60902A7B227300E1D7A5 /* FNA3D_CommandBuffer.c in Sources */, - 7BF94B9E275C044E00050413 /* mojoshader_vulkan.c in Sources */, 7BF820712445254300736AB0 /* FNA3D.c in Sources */, 7B8B6CBF24452690001C08D6 /* mojoshader_common.c in Sources */, 7BF8207D2445254300736AB0 /* FNA3D_PipelineCache.c in Sources */, @@ -523,18 +493,14 @@ files = ( 7BC01C0C2B4348F300941563 /* mojoshader_effects.c in Sources */, 7BC01C0B2B4348F300941563 /* mojoshader_profile_common.c in Sources */, - 7BC01C0E2B4348F700941563 /* FNA3D_CommandBuffer.c in Sources */, 7BC01C112B4348F700941563 /* FNA3D.c in Sources */, 7BC01C0F2B4348F700941563 /* FNA3D_Image.c in Sources */, - 7BC01C122B4348F700941563 /* FNA3D_Memory.c in Sources */, 7BC01C042B4348CD00941563 /* mojoshader_opengl.c in Sources */, 7BC01C082B4348F300941563 /* mojoshader.c in Sources */, - 7BC01C0D2B4348F700941563 /* FNA3D_Driver_Vulkan.c in Sources */, 7BC01C142B43490100941563 /* FNA3D_Driver_OpenGL.c in Sources */, 7BC01C102B4348F700941563 /* FNA3D_PipelineCache.c in Sources */, 7BC01C062B4348ED00941563 /* mojoshader_profile_glsl.c in Sources */, 7BC01C072B4348F300941563 /* mojoshader_profile_spirv.c in Sources */, - 7BC01C0A2B4348F300941563 /* mojoshader_vulkan.c in Sources */, 7BC01C092B4348F300941563 /* mojoshader_common.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -584,7 +550,6 @@ GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - FNA3D_DRIVER_VULKAN, MOJOSHADER_NO_VERSION_INCLUDE, MOJOSHADER_USE_SDL_STDLIB, MOJOSHADER_EFFECT_SUPPORT, @@ -610,7 +575,6 @@ HEADER_SEARCH_PATHS = ( ../../SDL2/include, ../mojoshader/, - "../Vulkan-Headers/include", ); IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACOSX_DEPLOYMENT_TARGET = 10.9; @@ -661,7 +625,6 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( - FNA3D_DRIVER_VULKAN, MOJOSHADER_NO_VERSION_INCLUDE, MOJOSHADER_USE_SDL_STDLIB, MOJOSHADER_EFFECT_SUPPORT, @@ -687,7 +650,6 @@ HEADER_SEARCH_PATHS = ( ../../SDL2/include, ../mojoshader/, - "../Vulkan-Headers/include", ); IPHONEOS_DEPLOYMENT_TARGET = 11.0; MACOSX_DEPLOYMENT_TARGET = 10.9; diff --git a/include/FNA3D_SysRenderer.h b/include/FNA3D_SysRenderer.h index cd5c6ec1..33566ef2 100644 --- a/include/FNA3D_SysRenderer.h +++ b/include/FNA3D_SysRenderer.h @@ -44,7 +44,7 @@ extern "C" { typedef enum FNA3D_SysRendererTypeEXT { FNA3D_RENDERER_TYPE_OPENGL_EXT, - FNA3D_RENDERER_TYPE_VULKAN_EXT, + FNA3D_RENDERER_TYPE_VULKAN_EXT, /* REMOVED, DO NOT USE */ FNA3D_RENDERER_TYPE_D3D11_EXT, FNA3D_RENDERER_TYPE_METAL_EXT, /* REMOVED, DO NOT USE */ FNA3D_RENDERER_TYPE_SDL_GPU_EXT, diff --git a/src/FNA3D_CommandBuffer.c b/src/FNA3D_CommandBuffer.c deleted file mode 100644 index 9bd35586..00000000 --- a/src/FNA3D_CommandBuffer.c +++ /dev/null @@ -1,879 +0,0 @@ -/* FNA3D - 3D Graphics Library for FNA - * - * Copyright (c) 2020-2024 Ethan Lee - * - * 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. - * - * Ethan "flibitijibibo" Lee - * - */ - -#include "FNA3D_CommandBuffer.h" - -#ifdef USE_SDL3 -#include -#else -#include -#define SDL_Mutex SDL_mutex -#endif - -#define STARTING_TRANSFER_BUFFER_SIZE 8000000 /* 8MB */ -#define FAST_TRANSFER_SIZE 64000000 /* 64MB */ - -typedef struct FNA3D_TransferBufferPool -{ - FNA3D_TransferBuffer *fastTransferBuffer; - uint8_t fastTransferBufferAvailable; - - FNA3D_TransferBuffer **availableSlowTransferBuffers; - uint32_t availableSlowTransferBufferCount; - uint32_t availableSlowTransferBufferCapacity; -} FNA3D_TransferBufferPool; - -/* Command buffers have various resources associated with them - * that can be freed after the command buffer is fully processed. - */ -typedef struct FNA3D_CommandBufferContainer -{ - FNA3D_CommandBuffer *handle; - - FNA3D_TransferBuffer **transferBuffers; - uint32_t transferBufferCount; - uint32_t transferBufferCapacity; - - FNA3D_BufferHandle **boundBuffers; - uint32_t boundBufferCount; - uint32_t boundBufferCapacity; - - FNA3D_Renderbuffer **renderbuffersToDestroy; - uint32_t renderbuffersToDestroyCount; - uint32_t renderbuffersToDestroyCapacity; - - FNA3D_BufferHandle **buffersToDestroy; - uint32_t buffersToDestroyCount; - uint32_t buffersToDestroyCapacity; - - FNA3D_Effect **effectsToDestroy; - uint32_t effectsToDestroyCount; - uint32_t effectsToDestroyCapacity; - - FNA3D_Texture **texturesToDestroy; - uint32_t texturesToDestroyCount; - uint32_t texturesToDestroyCapacity; -} FNA3D_CommandBufferContainer; - -struct FNA3D_CommandBufferManager -{ - FNA3D_CommandBufferDriver driver; - - FNA3D_CommandBufferContainer **inactiveCommandBufferContainers; - uint32_t inactiveCommandBufferContainerCount; - uint32_t inactiveCommandBufferContainerCapacity; - - FNA3D_CommandBufferContainer **submittedCommandBufferContainers; - uint32_t submittedCommandBufferContainerCount; - uint32_t submittedCommandBufferContainerCapacity; - - uint32_t currentCommandCount; - FNA3D_CommandBufferContainer *currentCommandBufferContainer; - - /* Special command buffer for performing defrag copies */ - FNA3D_CommandBufferContainer *defragCommandBufferContainer; - - FNA3D_TransferBufferPool transferBufferPool; - - SDL_Mutex *commandLock; - SDL_Mutex *transferLock; -}; - -static FNA3D_CommandBufferContainer* FNA3D_INTERNAL_CreateCommandBufferContainer( - FNA3D_CommandBufferManager *manager, - uint8_t fenceSignaled -) { - FNA3D_CommandBufferContainer *result = (FNA3D_CommandBufferContainer*) SDL_malloc( - sizeof(FNA3D_CommandBufferContainer) - ); - - result->handle = manager->driver.AllocCommandBuffer( - manager->driver.driverData, - fenceSignaled - ); - - /* Transfer buffer tracking */ - - result->transferBufferCapacity = 0; - result->transferBufferCount = 0; - result->transferBuffers = NULL; - - /* Bound buffer tracking */ - - result->boundBufferCapacity = 4; - result->boundBufferCount = 0; - result->boundBuffers = (FNA3D_BufferHandle**) SDL_malloc( - result->boundBufferCapacity * sizeof(FNA3D_BufferHandle*) - ); - - /* Destroyed resources tracking */ - - result->renderbuffersToDestroyCapacity = 16; - result->renderbuffersToDestroyCount = 0; - - result->renderbuffersToDestroy = (FNA3D_Renderbuffer**) SDL_malloc( - sizeof(FNA3D_Renderbuffer*) * - result->renderbuffersToDestroyCapacity - ); - - result->buffersToDestroyCapacity = 16; - result->buffersToDestroyCount = 0; - - result->buffersToDestroy = (FNA3D_BufferHandle**) SDL_malloc( - sizeof(FNA3D_BufferHandle*) * - result->buffersToDestroyCapacity - ); - - result->effectsToDestroyCapacity = 16; - result->effectsToDestroyCount = 0; - - result->effectsToDestroy = (FNA3D_Effect**) SDL_malloc( - sizeof(FNA3D_Effect*) * - result->effectsToDestroyCapacity - ); - - result->texturesToDestroyCapacity = 16; - result->texturesToDestroyCount = 0; - - result->texturesToDestroy = (FNA3D_Texture**) SDL_malloc( - sizeof(FNA3D_Texture*) * - result->texturesToDestroyCapacity - ); - - return result; -} - -static void FNA3D_CommandBuffer_CleanContainer( - FNA3D_CommandBufferManager *manager, - FNA3D_CommandBufferContainer *container -) { - FNA3D_TransferBuffer* transferBuffer; - uint32_t i; - - /* Reset bound buffers */ - for (i = 0; i < container->boundBufferCount; i += 1) - { - if (container->boundBuffers[i] != NULL) - { - manager->driver.DecBufferRef( - manager->driver.driverData, - container->boundBuffers[i] - ); - } - } - container->boundBufferCount = 0; - - /* Destroy resources marked for destruction */ - - for (i = 0; i < container->renderbuffersToDestroyCount; i += 1) - { - manager->driver.DestroyRenderbuffer( - manager->driver.driverData, - container->renderbuffersToDestroy[i] - ); - } - container->renderbuffersToDestroyCount = 0; - - for (i = 0; i < container->buffersToDestroyCount; i += 1) - { - manager->driver.DestroyBuffer( - manager->driver.driverData, - container->buffersToDestroy[i] - ); - } - container->buffersToDestroyCount = 0; - - for (i = 0; i < container->effectsToDestroyCount; i += 1) - { - manager->driver.DestroyEffect( - manager->driver.driverData, - container->effectsToDestroy[i] - ); - } - container->effectsToDestroyCount = 0; - - for (i = 0; i < container->texturesToDestroyCount; i += 1) - { - manager->driver.DestroyTexture( - manager->driver.driverData, - container->texturesToDestroy[i] - ); - } - container->texturesToDestroyCount = 0; - - /* Return the transfer buffers to the pool */ - for (i = 0; i < container->transferBufferCount; i += 1) - { - transferBuffer = container->transferBuffers[i]; - transferBuffer->offset = 0; - - if (transferBuffer == manager->transferBufferPool.fastTransferBuffer) - { - manager->transferBufferPool.fastTransferBufferAvailable = 1; - } - else - { - if (manager->transferBufferPool.availableSlowTransferBufferCount == manager->transferBufferPool.availableSlowTransferBufferCapacity) - { - manager->transferBufferPool.availableSlowTransferBufferCapacity += 1; - manager->transferBufferPool.availableSlowTransferBuffers = SDL_realloc( - manager->transferBufferPool.availableSlowTransferBuffers, - manager->transferBufferPool.availableSlowTransferBufferCapacity * sizeof(FNA3D_TransferBuffer*) - ); - } - - manager->transferBufferPool.availableSlowTransferBuffers[manager->transferBufferPool.availableSlowTransferBufferCount] = transferBuffer; - manager->transferBufferPool.availableSlowTransferBufferCount += 1; - } - } - container->transferBufferCount = 0; - - SDL_LockMutex(manager->commandLock); - - manager->driver.Reset( - manager->driver.driverData, - container->handle - ); - - SDL_UnlockMutex(manager->commandLock); - - /* Remove this command buffer from the submitted list */ - for (i = 0; i < manager->submittedCommandBufferContainerCount; i += 1) - { - if (manager->submittedCommandBufferContainers[i] == container) - { - manager->submittedCommandBufferContainers[i] = manager->submittedCommandBufferContainers[manager->submittedCommandBufferContainerCount - 1]; - manager->submittedCommandBufferContainerCount -= 1; - break; - } - } - - /* Add this command buffer to the inactive list */ - if (manager->inactiveCommandBufferContainerCount + 1 > manager->inactiveCommandBufferContainerCapacity) - { - manager->inactiveCommandBufferContainerCapacity = manager->inactiveCommandBufferContainerCount + 1; - manager->inactiveCommandBufferContainers = SDL_realloc( - manager->inactiveCommandBufferContainers, - manager->inactiveCommandBufferContainerCapacity * sizeof(FNA3D_CommandBufferContainer*) - ); - } - - manager->inactiveCommandBufferContainers[manager->inactiveCommandBufferContainerCount] = container; - manager->inactiveCommandBufferContainerCount += 1; -} - -/* Public Functions */ - -FNA3D_CommandBufferManager* FNA3D_CreateCommandBufferManager( - FNA3D_CommandBufferDriver *driver -) { - FNA3D_CommandBufferManager *manager = (FNA3D_CommandBufferManager*) SDL_malloc( - sizeof(FNA3D_CommandBufferManager) - ); - SDL_memcpy(&manager->driver, driver, sizeof(FNA3D_CommandBufferDriver)); - - manager->commandLock = SDL_CreateMutex(); - manager->transferLock = SDL_CreateMutex(); - - manager->inactiveCommandBufferContainerCapacity = 1; - manager->inactiveCommandBufferContainers = (FNA3D_CommandBufferContainer**) SDL_malloc( - sizeof(FNA3D_CommandBufferContainer*) - ); - manager->inactiveCommandBufferContainerCount = 0; - manager->currentCommandCount = 0; - - manager->submittedCommandBufferContainerCapacity = 1; - manager->submittedCommandBufferContainers = (FNA3D_CommandBufferContainer**) SDL_malloc( - sizeof(FNA3D_CommandBufferContainer*) - ); - manager->submittedCommandBufferContainerCount = 0; - - manager->defragCommandBufferContainer = FNA3D_INTERNAL_CreateCommandBufferContainer( - manager, - 1 - ); - - /* - * Initialize buffer space - */ - - manager->transferBufferPool.fastTransferBuffer = (FNA3D_TransferBuffer*) SDL_malloc( - sizeof(FNA3D_TransferBuffer) - ); - manager->transferBufferPool.fastTransferBuffer->offset = 0; - manager->transferBufferPool.fastTransferBuffer->buffer = manager->driver.CreateTransferBuffer( - manager->driver.driverData, - FAST_TRANSFER_SIZE, - 1 - ); - manager->transferBufferPool.fastTransferBufferAvailable = 1; - - manager->transferBufferPool.availableSlowTransferBufferCapacity = 4; - manager->transferBufferPool.availableSlowTransferBufferCount = 0; - manager->transferBufferPool.availableSlowTransferBuffers = (FNA3D_TransferBuffer**) SDL_malloc( - manager->transferBufferPool.availableSlowTransferBufferCapacity * sizeof(FNA3D_TransferBuffer*) - ); - - return manager; -} - -void FNA3D_DestroyCommandBufferManager( - FNA3D_CommandBufferManager *manager -) { - FNA3D_CommandBufferContainer *commandBufferContainer; - uint32_t i; - - if (manager->inactiveCommandBufferContainerCount + 1 > manager->inactiveCommandBufferContainerCapacity) - { - manager->inactiveCommandBufferContainerCapacity = manager->inactiveCommandBufferContainerCount + 1; - manager->inactiveCommandBufferContainers = SDL_realloc( - manager->inactiveCommandBufferContainers, - manager->inactiveCommandBufferContainerCapacity * sizeof(FNA3D_CommandBufferContainer*) - ); - } - - manager->inactiveCommandBufferContainers[manager->inactiveCommandBufferContainerCount] = manager->currentCommandBufferContainer; - manager->inactiveCommandBufferContainerCount += 1; - - manager->inactiveCommandBufferContainerCapacity += 1; - manager->inactiveCommandBufferContainers = SDL_realloc( - manager->inactiveCommandBufferContainers, - sizeof(FNA3D_CommandBufferContainer*) * manager->inactiveCommandBufferContainerCapacity - ); - - manager->inactiveCommandBufferContainers[manager->inactiveCommandBufferContainerCount] = manager->defragCommandBufferContainer; - manager->inactiveCommandBufferContainerCount += 1; - - for (i = 0; i < manager->inactiveCommandBufferContainerCount; i += 1) - { - commandBufferContainer = manager->inactiveCommandBufferContainers[i]; - - manager->driver.FreeCommandBuffer( - manager->driver.driverData, - commandBufferContainer->handle - ); - - SDL_free(commandBufferContainer->transferBuffers); - SDL_free(commandBufferContainer->boundBuffers); - - SDL_free(commandBufferContainer->renderbuffersToDestroy); - SDL_free(commandBufferContainer->buffersToDestroy); - SDL_free(commandBufferContainer->effectsToDestroy); - SDL_free(commandBufferContainer->texturesToDestroy); - - SDL_free(commandBufferContainer); - } - - manager->driver.DestroyBuffer( - manager->driver.driverData, - manager->transferBufferPool.fastTransferBuffer->buffer - ); - SDL_free(manager->transferBufferPool.fastTransferBuffer); - - for (i = 0; i < manager->transferBufferPool.availableSlowTransferBufferCount; i += 1) - { - manager->driver.DestroyBuffer( - manager->driver.driverData, - manager->transferBufferPool.availableSlowTransferBuffers[i]->buffer - ); - - SDL_free(manager->transferBufferPool.availableSlowTransferBuffers[i]); - } - SDL_free(manager->transferBufferPool.availableSlowTransferBuffers); - - SDL_DestroyMutex(manager->commandLock); - SDL_DestroyMutex(manager->transferLock); - - SDL_free(manager->inactiveCommandBufferContainers); - SDL_free(manager->submittedCommandBufferContainers); - SDL_free(manager); -} - -void FNA3D_CommandBuffer_BeginRecording(FNA3D_CommandBufferManager *manager) -{ - SDL_LockMutex(manager->commandLock); - - /* If we are out of unused command buffers, allocate some more */ - if (manager->inactiveCommandBufferContainerCount == 0) - { - manager->inactiveCommandBufferContainers[manager->inactiveCommandBufferContainerCount] = - FNA3D_INTERNAL_CreateCommandBufferContainer(manager, 0); - - manager->inactiveCommandBufferContainerCount += 1; - } - - manager->currentCommandBufferContainer = - manager->inactiveCommandBufferContainers[manager->inactiveCommandBufferContainerCount - 1]; - - manager->inactiveCommandBufferContainerCount -= 1; - - manager->driver.BeginRecording( - manager->driver.driverData, - manager->currentCommandBufferContainer->handle - ); - - SDL_UnlockMutex(manager->commandLock); -} - -void FNA3D_CommandBuffer_EndRecording(FNA3D_CommandBufferManager *manager) -{ - SDL_LockMutex(manager->commandLock); - - manager->driver.EndRecording( - manager->driver.driverData, - manager->currentCommandBufferContainer->handle - ); - - SDL_UnlockMutex(manager->commandLock); -} - -void FNA3D_CommandBuffer_Finish(FNA3D_CommandBufferManager *manager) -{ - int32_t i; - FNA3D_CommandBuffer **commandBuffers = SDL_stack_alloc( - FNA3D_CommandBuffer*, - manager->submittedCommandBufferContainerCount - ); - - for (i = 0; i < manager->submittedCommandBufferContainerCount; i += 1) - { - commandBuffers[i] = manager->submittedCommandBufferContainers[i]->handle; - } - - manager->driver.WaitForFences( - manager->driver.driverData, - commandBuffers, - manager->submittedCommandBufferContainerCount - ); - - for (i = manager->submittedCommandBufferContainerCount - 1; i >= 0; i -= 1) - { - FNA3D_CommandBuffer_CleanContainer( - manager, - manager->submittedCommandBufferContainers[i] - ); - } - - SDL_stack_free(commandBuffers); -} - -void FNA3D_CommandBuffer_LockForRendering(FNA3D_CommandBufferManager *manager) -{ - SDL_LockMutex(manager->commandLock); - if (manager->currentCommandBufferContainer == NULL) - { - FNA3D_CommandBuffer_BeginRecording(manager); - } -} - -void FNA3D_CommandBuffer_UnlockFromRendering(FNA3D_CommandBufferManager *manager) -{ - SDL_UnlockMutex(manager->commandLock); -} - -void FNA3D_CommandBuffer_LockForDefrag(FNA3D_CommandBufferManager *manager) -{ - SDL_LockMutex(manager->commandLock); - - /* FIXME: This is a kludge! */ - manager->currentCommandBufferContainer = manager->defragCommandBufferContainer; -} - -void FNA3D_CommandBuffer_UnlockFromDefrag(FNA3D_CommandBufferManager *manager) -{ - /* FIXME: This is a kludge! */ - manager->currentCommandBufferContainer = NULL; - - SDL_UnlockMutex(manager->commandLock); -} - -void FNA3D_CommandBuffer_LockForTransfer(FNA3D_CommandBufferManager *manager) -{ - SDL_LockMutex(manager->transferLock); -} - -void FNA3D_CommandBuffer_UnlockFromTransfer(FNA3D_CommandBufferManager *manager) -{ - SDL_UnlockMutex(manager->transferLock); -} - -void FNA3D_CommandBuffer_LockForSubmit(FNA3D_CommandBufferManager *manager) -{ - SDL_LockMutex(manager->commandLock); - SDL_LockMutex(manager->transferLock); -} - -void FNA3D_CommandBuffer_UnlockFromSubmit(FNA3D_CommandBufferManager *manager) -{ - SDL_UnlockMutex(manager->commandLock); - SDL_UnlockMutex(manager->transferLock); -} - -void FNA3D_CommandBuffer_AddDisposeTexture( - FNA3D_CommandBufferManager *manager, - FNA3D_Texture *texture -) { - FNA3D_CommandBufferContainer *container; - - SDL_LockMutex(manager->commandLock); - - container = manager->currentCommandBufferContainer; - - if (container->texturesToDestroyCount + 1 >= container->texturesToDestroyCapacity) - { - container->texturesToDestroyCapacity *= 2; - - container->texturesToDestroy = SDL_realloc( - container->texturesToDestroy, - sizeof(FNA3D_Texture*) * container->texturesToDestroyCapacity - ); - } - container->texturesToDestroy[container->texturesToDestroyCount] = texture; - container->texturesToDestroyCount += 1; - - SDL_UnlockMutex(manager->commandLock); -} - -void FNA3D_CommandBuffer_AddDisposeRenderbuffer( - FNA3D_CommandBufferManager *manager, - FNA3D_Renderbuffer *renderbuffer -) { - FNA3D_CommandBufferContainer *container; - - SDL_LockMutex(manager->commandLock); - - container = manager->currentCommandBufferContainer; - - if (container->renderbuffersToDestroyCount + 1 >= container->renderbuffersToDestroyCapacity) - { - container->renderbuffersToDestroyCapacity *= 2; - - container->renderbuffersToDestroy = SDL_realloc( - container->renderbuffersToDestroy, - sizeof(FNA3D_Renderbuffer*) * container->renderbuffersToDestroyCapacity - ); - } - container->renderbuffersToDestroy[container->renderbuffersToDestroyCount] = renderbuffer; - container->renderbuffersToDestroyCount += 1; - - SDL_UnlockMutex(manager->commandLock); -} - -void FNA3D_CommandBuffer_AddDisposeEffect( - FNA3D_CommandBufferManager *manager, - FNA3D_Effect *effect -) { - FNA3D_CommandBufferContainer *container; - - SDL_LockMutex(manager->commandLock); - - container = manager->currentCommandBufferContainer; - - if (container->effectsToDestroyCount + 1 >= container->effectsToDestroyCapacity) - { - container->effectsToDestroyCapacity *= 2; - - container->effectsToDestroy = SDL_realloc( - container->effectsToDestroy, - sizeof(FNA3D_Effect*) * container->effectsToDestroyCapacity - ); - } - container->effectsToDestroy[container->effectsToDestroyCount] = effect; - container->effectsToDestroyCount += 1; - - SDL_UnlockMutex(manager->commandLock); -} - -void FNA3D_CommandBuffer_AddDisposeBuffers( - FNA3D_CommandBufferManager *manager, - FNA3D_BufferHandle **handles, - size_t handleCount -) { - FNA3D_CommandBufferContainer *container; - size_t i; - - /* Queue buffer for destruction */ - SDL_LockMutex(manager->commandLock); - container = manager->currentCommandBufferContainer; - - /* FIXME: This is a lazy way of adding each buffer, do a memcpy instead */ - for (i = 0; i < handleCount; i += 1) - { - if (container->buffersToDestroyCount + 1 >= container->buffersToDestroyCapacity) - { - container->buffersToDestroyCapacity *= 2; - - container->buffersToDestroy = SDL_realloc( - container->buffersToDestroy, - sizeof(FNA3D_BufferHandle*) * container->buffersToDestroyCapacity - ); - } - - container->buffersToDestroy[ - container->buffersToDestroyCount - ] = handles[i]; - container->buffersToDestroyCount += 1; - } - SDL_UnlockMutex(manager->commandLock); -} - -uint8_t FNA3D_CommandBuffer_PerformCleanups(FNA3D_CommandBufferManager *manager) -{ - uint8_t result = 0; - int32_t i; - for (i = manager->submittedCommandBufferContainerCount - 1; i >= 0; i -= 1) - { - if (manager->driver.QueryFence( - manager->driver.driverData, - manager->submittedCommandBufferContainers[i]->handle - )) { - FNA3D_CommandBuffer_CleanContainer( - manager, - manager->submittedCommandBufferContainers[i] - ); - - result = 1; - } - } - - return result; -} - -void FNA3D_CommandBuffer_SubmitCurrent(FNA3D_CommandBufferManager *manager) -{ - if (manager->submittedCommandBufferContainerCount >= manager->submittedCommandBufferContainerCapacity) - { - manager->submittedCommandBufferContainerCapacity *= 2; - manager->submittedCommandBufferContainers = SDL_realloc( - manager->submittedCommandBufferContainers, - manager->submittedCommandBufferContainerCapacity * sizeof(FNA3D_CommandBufferContainer*) - ); - } - - manager->submittedCommandBufferContainers[manager->submittedCommandBufferContainerCount] = - manager->currentCommandBufferContainer; - manager->submittedCommandBufferContainerCount += 1; - manager->currentCommandBufferContainer = NULL; -} - -FNA3D_CommandBuffer* FNA3D_CommandBuffer_GetCurrent(FNA3D_CommandBufferManager *manager) -{ - return manager->currentCommandBufferContainer->handle; -} - -FNA3D_CommandBuffer* FNA3D_CommandBuffer_GetDefragBuffer(FNA3D_CommandBufferManager *manager) -{ - return manager->defragCommandBufferContainer->handle; -} - -void FNA3D_CommandBuffer_MarkBufferAsBound( - FNA3D_CommandBufferManager *manager, - FNA3D_BufferHandle *buffer -) { - uint32_t i; - - for (i = 0; i < manager->currentCommandBufferContainer->boundBufferCount; i += 1) - { - if (buffer == manager->currentCommandBufferContainer->boundBuffers[i]) - { - /* Buffer is already referenced, nothing to do */ - return; - } - } - - manager->driver.IncBufferRef( - manager->driver.driverData, - buffer - ); - - if (manager->currentCommandBufferContainer->boundBufferCount >= manager->currentCommandBufferContainer->boundBufferCapacity) - { - manager->currentCommandBufferContainer->boundBufferCapacity *= 2; - manager->currentCommandBufferContainer->boundBuffers = SDL_realloc( - manager->currentCommandBufferContainer->boundBuffers, - manager->currentCommandBufferContainer->boundBufferCapacity * sizeof(FNA3D_BufferHandle*) - ); - } - - manager->currentCommandBufferContainer->boundBuffers[manager->currentCommandBufferContainer->boundBufferCount] = buffer; - manager->currentCommandBufferContainer->boundBufferCount += 1; -} - -FNA3D_TransferBuffer* FNA3D_CommandBuffer_AcquireTransferBuffer( - FNA3D_CommandBufferManager *manager, - size_t requiredSize, - size_t alignment -) { - FNA3D_TransferBuffer *transferBuffer; - size_t parentBufferSize; - uint32_t i; - size_t size; - size_t offset; - FNA3D_CommandBufferContainer *commandBufferContainer = - manager->currentCommandBufferContainer; - - /* Search the command buffer's current transfer buffers */ - - for (i = 0; i < commandBufferContainer->transferBufferCount; i += 1) - { - transferBuffer = commandBufferContainer->transferBuffers[i]; - parentBufferSize = manager->driver.GetBufferSize( - manager->driver.driverData, - transferBuffer->buffer - ); - offset = transferBuffer->offset + alignment - (transferBuffer->offset % alignment); - - if (offset + requiredSize <= parentBufferSize) - { - transferBuffer->offset = offset; - return transferBuffer; - } - } - - /* Nothing fits so let's get a transfer buffer from the pool */ - - if (commandBufferContainer->transferBufferCount == commandBufferContainer->transferBufferCapacity) - { - commandBufferContainer->transferBufferCapacity += 1; - commandBufferContainer->transferBuffers = SDL_realloc( - commandBufferContainer->transferBuffers, - commandBufferContainer->transferBufferCapacity * sizeof(FNA3D_TransferBuffer*) - ); - } - - /* Is the fast transfer buffer available? */ - if ( manager->transferBufferPool.fastTransferBufferAvailable && - requiredSize < FAST_TRANSFER_SIZE ) - { - transferBuffer = manager->transferBufferPool.fastTransferBuffer; - manager->transferBufferPool.fastTransferBufferAvailable = 0; - - commandBufferContainer->transferBuffers[commandBufferContainer->transferBufferCount] = transferBuffer; - commandBufferContainer->transferBufferCount += 1; - - /* If the fast transfer buffer is available, the offset is always zero */ - return transferBuffer; - } - - /* Nope, let's get a slow buffer */ - for (i = 0; i < manager->transferBufferPool.availableSlowTransferBufferCount; i += 1) - { - transferBuffer = manager->transferBufferPool.availableSlowTransferBuffers[i]; - parentBufferSize = manager->driver.GetBufferSize( - manager->driver.driverData, - transferBuffer->buffer - ); - offset = transferBuffer->offset + alignment - (transferBuffer->offset % alignment); - - if (offset + requiredSize <= parentBufferSize) - { - commandBufferContainer->transferBuffers[commandBufferContainer->transferBufferCount] = transferBuffer; - commandBufferContainer->transferBufferCount += 1; - - manager->transferBufferPool.availableSlowTransferBuffers[i] = manager->transferBufferPool.availableSlowTransferBuffers[manager->transferBufferPool.availableSlowTransferBufferCount - 1]; - manager->transferBufferPool.availableSlowTransferBufferCount -= 1; - - transferBuffer->offset = offset; - return transferBuffer; - } - } - - /* Nothing fits still, so let's create a new transfer buffer */ - - size = STARTING_TRANSFER_BUFFER_SIZE; - - while (size < requiredSize) - { - size *= 2; - } - - transferBuffer = SDL_malloc(sizeof(FNA3D_TransferBuffer)); - transferBuffer->offset = 0; - transferBuffer->buffer = manager->driver.CreateTransferBuffer( - manager->driver.driverData, - size, - 0 - ); - - if (transferBuffer->buffer == NULL) - { - FNA3D_LogError("Failed to allocate transfer buffer!"); - return NULL; - } - - if (commandBufferContainer->transferBufferCount == commandBufferContainer->transferBufferCapacity) - { - commandBufferContainer->transferBufferCapacity += 1; - commandBufferContainer->transferBuffers = SDL_realloc( - commandBufferContainer->transferBuffers, - commandBufferContainer->transferBufferCapacity * sizeof(FNA3D_TransferBuffer*) - ); - } - - commandBufferContainer->transferBuffers[commandBufferContainer->transferBufferCount] = transferBuffer; - commandBufferContainer->transferBufferCount += 1; - - return transferBuffer; -} - -void FNA3D_CommandBuffer_ClearDestroyedBuffer( - FNA3D_CommandBufferManager *manager, - FNA3D_BufferHandle *buffer -) { - uint32_t i, j; - - /* Don't unbind destroyed buffers! */ - for (i = 0; i < manager->submittedCommandBufferContainerCount; i += 1) - { - for (j = 0; j < manager->submittedCommandBufferContainers[i]->boundBufferCount; j += 1) - { - if (buffer == manager->submittedCommandBufferContainers[i]->boundBuffers[j]) - { - manager->submittedCommandBufferContainers[i]->boundBuffers[j] = NULL; - } - } - } -} - -void FNA3D_CommandBuffer_ForEachSubmittedBuffer( - FNA3D_CommandBufferManager *manager, - void (*callback)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer *handle, - void* callbackData - ), - void* callbackData -) { - uint32_t i; - for (i = 0; i < manager->submittedCommandBufferContainerCount; i += 1) - { - callback( - manager->driver.driverData, - manager->submittedCommandBufferContainers[i]->handle, - callbackData - ); - } -} diff --git a/src/FNA3D_CommandBuffer.h b/src/FNA3D_CommandBuffer.h deleted file mode 100644 index a7aae42e..00000000 --- a/src/FNA3D_CommandBuffer.h +++ /dev/null @@ -1,220 +0,0 @@ -/* FNA3D - 3D Graphics Library for FNA - * - * Copyright (c) 2020-2024 Ethan Lee - * - * 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. - * - * Ethan "flibitijibibo" Lee - * - */ - -#ifndef FNA3D_COMMANDBUFFER_H -#define FNA3D_COMMANDBUFFER_H - -#include "FNA3D_Driver.h" -#include "FNA3D_Memory.h" - -/* Driver-defined command buffer structures */ - -typedef struct FNA3D_CommandBuffer FNA3D_CommandBuffer; - -/* Renderers will contain a command buffer driver, so we can call back into the - * renderer to do platform-specific things that don't have to do with the - * high-level command buffer management - */ - -typedef struct FNA3D_CommandBufferDriver -{ - FNA3D_CommandBuffer* (*AllocCommandBuffer)( - FNA3D_Renderer *driverData, - uint8_t fenceSignaled - ); - void (*FreeCommandBuffer)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer *handle - ); - - void (*BeginRecording)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer *handle - ); - void (*EndRecording)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer *handle - ); - void (*Reset)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer *handle - ); - uint8_t (*QueryFence)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer *handle - ); - void (*WaitForFences)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer **handles, - size_t handleCount - ); - - FNA3D_BufferHandle* (*CreateTransferBuffer)( - FNA3D_Renderer *driverData, - size_t size, - uint8_t preferDeviceLocal - ); - - void (*IncBufferRef)( - FNA3D_Renderer *renderer, - FNA3D_BufferHandle *handle - ); - void (*DecBufferRef)( - FNA3D_Renderer *renderer, - FNA3D_BufferHandle *handle - ); - size_t (*GetBufferSize)( - FNA3D_Renderer *driverData, - FNA3D_BufferHandle *handle - ); - - void (*DestroyTexture)( - FNA3D_Renderer *driverData, - FNA3D_Texture *texture - ); - void (*DestroyBuffer)( - FNA3D_Renderer *driverData, - FNA3D_BufferHandle *buffer - ); - void (*DestroyRenderbuffer)( - FNA3D_Renderer *driverData, - FNA3D_Renderbuffer *renderbuffer - ); - void (*DestroyEffect)( - FNA3D_Renderer *driverData, - FNA3D_Effect *effect - ); - - FNA3D_Renderer *driverData; -} FNA3D_CommandBufferDriver; - -#define ASSIGN_COMMANDBUFFER_DRIVER_FUNC(func, name) \ - commandBufferDriver.func = name##_CommandBuffer_##func; -#define ASSIGN_COMMANDBUFFER_DRIVER(name) \ - commandBufferDriver.driverData = (FNA3D_Renderer*) renderer; \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(AllocCommandBuffer, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(FreeCommandBuffer, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(BeginRecording, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(EndRecording, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(Reset, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(QueryFence, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(WaitForFences, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(CreateTransferBuffer, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(IncBufferRef, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(DecBufferRef, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(GetBufferSize, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(DestroyTexture, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(DestroyBuffer, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(DestroyRenderbuffer, name) \ - ASSIGN_COMMANDBUFFER_DRIVER_FUNC(DestroyEffect, name) - -/* - * Command Buffer Interface - */ - -typedef struct FNA3D_CommandBufferManager FNA3D_CommandBufferManager; - -/* Renderers will receive this struct, perform the transfer, then update the - * offset value for future AcquireTransferBuffer calls - */ -typedef struct FNA3D_TransferBuffer -{ - FNA3D_BufferHandle *buffer; - size_t offset; -} FNA3D_TransferBuffer; - -FNA3D_SHAREDINTERNAL FNA3D_CommandBufferManager* FNA3D_CreateCommandBufferManager( - FNA3D_CommandBufferDriver *driver -); -FNA3D_SHAREDINTERNAL void FNA3D_DestroyCommandBufferManager(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_BeginRecording(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_EndRecording(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_Finish(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_LockForRendering(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_UnlockFromRendering(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_LockForDefrag(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_UnlockFromDefrag(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_LockForTransfer(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_UnlockFromTransfer(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_LockForSubmit(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_UnlockFromSubmit(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_AddDisposeTexture( - FNA3D_CommandBufferManager *manager, - FNA3D_Texture *texture -); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_AddDisposeRenderbuffer( - FNA3D_CommandBufferManager *manager, - FNA3D_Renderbuffer *renderbuffer -); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_AddDisposeEffect( - FNA3D_CommandBufferManager *manager, - FNA3D_Effect *effect -); -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_AddDisposeBuffers( - FNA3D_CommandBufferManager *manager, - FNA3D_BufferHandle **handles, - size_t handleCount -); - -FNA3D_SHAREDINTERNAL uint8_t FNA3D_CommandBuffer_PerformCleanups(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_SubmitCurrent(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL FNA3D_CommandBuffer* FNA3D_CommandBuffer_GetCurrent(FNA3D_CommandBufferManager *manager); -FNA3D_SHAREDINTERNAL FNA3D_CommandBuffer* FNA3D_CommandBuffer_GetDefragBuffer(FNA3D_CommandBufferManager *manager); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_MarkBufferAsBound( - FNA3D_CommandBufferManager *manager, - FNA3D_BufferHandle *buffer -); -FNA3D_SHAREDINTERNAL FNA3D_TransferBuffer* FNA3D_CommandBuffer_AcquireTransferBuffer( - FNA3D_CommandBufferManager *manager, - size_t requiredSize, - size_t alignment -); - -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_ClearDestroyedBuffer( - FNA3D_CommandBufferManager *manager, - FNA3D_BufferHandle *buffer -); - -/* FIXME: This is kind of a kludge -flibit */ -FNA3D_SHAREDINTERNAL void FNA3D_CommandBuffer_ForEachSubmittedBuffer( - FNA3D_CommandBufferManager *manager, - void (*callback)( - FNA3D_Renderer *driverData, - FNA3D_CommandBuffer *handle, - void* callbackData - ), - void* callbackData -); - -#endif /* FNA3D_COMMANDBUFFER_H */ diff --git a/src/FNA3D_Driver.h b/src/FNA3D_Driver.h index 4f07960c..2c41c4e9 100644 --- a/src/FNA3D_Driver.h +++ b/src/FNA3D_Driver.h @@ -825,11 +825,9 @@ typedef struct FNA3D_Driver ); } FNA3D_Driver; -FNA3D_SHAREDINTERNAL FNA3D_Driver LegacyVulkanDriver; FNA3D_SHAREDINTERNAL FNA3D_Driver D3D11Driver; FNA3D_SHAREDINTERNAL FNA3D_Driver OpenGLDriver; FNA3D_SHAREDINTERNAL FNA3D_Driver SDLGPUDriver; -FNA3D_SHAREDINTERNAL FNA3D_Driver GNMXDriver; #endif /* FNA3D_DRIVER_H */ diff --git a/src/FNA3D_Driver_Vulkan_vkfuncs.h b/src/FNA3D_Driver_Vulkan_vkfuncs.h deleted file mode 100644 index 67de2905..00000000 --- a/src/FNA3D_Driver_Vulkan_vkfuncs.h +++ /dev/null @@ -1,179 +0,0 @@ -/* FNA3D - 3D Graphics Library for FNA - * - * Copyright (c) 2020-2024 Ethan Lee - * - * 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. - * - * Ethan "flibitijibibo" Lee - * - */ - -/* - * Global functions from the Vulkan Loader - */ - -#ifndef VULKAN_GLOBAL_FUNCTION -#define VULKAN_GLOBAL_FUNCTION(name) -#endif -VULKAN_GLOBAL_FUNCTION(vkCreateInstance) -VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties) -VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties) - -/* - * vkInstance, created by global vkCreateInstance function - */ - -#ifndef VULKAN_INSTANCE_FUNCTION -#define VULKAN_INSTANCE_FUNCTION(name) -#endif - -/* Vulkan 1.0 */ -VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr) -VULKAN_INSTANCE_FUNCTION(vkCreateDevice) -VULKAN_INSTANCE_FUNCTION(vkDestroyInstance) -VULKAN_INSTANCE_FUNCTION(vkEnumerateDeviceExtensionProperties) -VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties) - -/* VK_KHR_get_physical_device_properties2, needed for KHR_driver_properties */ -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2KHR) - -/* VK_KHR_surface */ -VULKAN_INSTANCE_FUNCTION(vkDestroySurfaceKHR) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR) -VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR) - -/* VK_EXT_debug_utils, Optional debug feature used by SetStringMarker */ -VULKAN_INSTANCE_FUNCTION(vkCmdInsertDebugUtilsLabelEXT) -VULKAN_INSTANCE_FUNCTION(vkSetDebugUtilsObjectNameEXT) - -/* - * vkDevice, created by a vkInstance - */ - -#ifndef VULKAN_DEVICE_FUNCTION -#define VULKAN_DEVICE_FUNCTION(name) -#endif - -/* Vulkan 1.0 */ -VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers) -VULKAN_DEVICE_FUNCTION(vkAllocateDescriptorSets) -VULKAN_DEVICE_FUNCTION(vkAllocateMemory) -VULKAN_DEVICE_FUNCTION(vkBeginCommandBuffer) -VULKAN_DEVICE_FUNCTION(vkBindBufferMemory) -VULKAN_DEVICE_FUNCTION(vkBindImageMemory) -VULKAN_DEVICE_FUNCTION(vkCmdBeginRenderPass) -VULKAN_DEVICE_FUNCTION(vkCmdBindDescriptorSets) -VULKAN_DEVICE_FUNCTION(vkCmdBindIndexBuffer) -VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline) -VULKAN_DEVICE_FUNCTION(vkCmdBindVertexBuffers) -VULKAN_DEVICE_FUNCTION(vkCmdBlitImage) -VULKAN_DEVICE_FUNCTION(vkCmdClearAttachments) -VULKAN_DEVICE_FUNCTION(vkCmdClearColorImage) -VULKAN_DEVICE_FUNCTION(vkCmdClearDepthStencilImage) -VULKAN_DEVICE_FUNCTION(vkCmdCopyBuffer) -VULKAN_DEVICE_FUNCTION(vkCmdCopyImage) -VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage) -VULKAN_DEVICE_FUNCTION(vkCmdCopyImageToBuffer) -VULKAN_DEVICE_FUNCTION(vkCmdDraw) -VULKAN_DEVICE_FUNCTION(vkCmdDrawIndexed) -VULKAN_DEVICE_FUNCTION(vkCmdEndRenderPass) -VULKAN_DEVICE_FUNCTION(vkCmdPipelineBarrier) -VULKAN_DEVICE_FUNCTION(vkCmdResolveImage) -VULKAN_DEVICE_FUNCTION(vkCmdSetBlendConstants) -VULKAN_DEVICE_FUNCTION(vkCmdSetDepthBias) -VULKAN_DEVICE_FUNCTION(vkCmdSetScissor) -VULKAN_DEVICE_FUNCTION(vkCmdSetStencilReference) -VULKAN_DEVICE_FUNCTION(vkCmdSetViewport) -VULKAN_DEVICE_FUNCTION(vkCreateBuffer) -VULKAN_DEVICE_FUNCTION(vkCreateCommandPool) -VULKAN_DEVICE_FUNCTION(vkCreateDescriptorPool) -VULKAN_DEVICE_FUNCTION(vkCreateDescriptorSetLayout) -VULKAN_DEVICE_FUNCTION(vkCreateFence) -VULKAN_DEVICE_FUNCTION(vkCreateFramebuffer) -VULKAN_DEVICE_FUNCTION(vkCreateGraphicsPipelines) -VULKAN_DEVICE_FUNCTION(vkCreateImage) -VULKAN_DEVICE_FUNCTION(vkCreateImageView) -VULKAN_DEVICE_FUNCTION(vkCreatePipelineCache) -VULKAN_DEVICE_FUNCTION(vkCreatePipelineLayout) -VULKAN_DEVICE_FUNCTION(vkCreateRenderPass) -VULKAN_DEVICE_FUNCTION(vkCreateSampler) -VULKAN_DEVICE_FUNCTION(vkCreateSemaphore) -VULKAN_DEVICE_FUNCTION(vkCreateShaderModule) -VULKAN_DEVICE_FUNCTION(vkCreateQueryPool) -VULKAN_DEVICE_FUNCTION(vkDestroyBuffer) -VULKAN_DEVICE_FUNCTION(vkDestroyCommandPool) -VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorPool) -VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorSetLayout) -VULKAN_DEVICE_FUNCTION(vkDestroyDevice) -VULKAN_DEVICE_FUNCTION(vkDestroyFence) -VULKAN_DEVICE_FUNCTION(vkDestroyFramebuffer) -VULKAN_DEVICE_FUNCTION(vkDestroyImage) -VULKAN_DEVICE_FUNCTION(vkDestroyImageView) -VULKAN_DEVICE_FUNCTION(vkDestroyPipeline) -VULKAN_DEVICE_FUNCTION(vkDestroyPipelineCache) -VULKAN_DEVICE_FUNCTION(vkDestroyPipelineLayout) -VULKAN_DEVICE_FUNCTION(vkDestroyRenderPass) -VULKAN_DEVICE_FUNCTION(vkDestroySampler) -VULKAN_DEVICE_FUNCTION(vkDestroySemaphore) -VULKAN_DEVICE_FUNCTION(vkDestroyQueryPool) -VULKAN_DEVICE_FUNCTION(vkDeviceWaitIdle) -VULKAN_DEVICE_FUNCTION(vkEndCommandBuffer) -VULKAN_DEVICE_FUNCTION(vkFreeCommandBuffers) -VULKAN_DEVICE_FUNCTION(vkFreeMemory) -VULKAN_DEVICE_FUNCTION(vkGetDeviceQueue) -VULKAN_DEVICE_FUNCTION(vkGetPipelineCacheData) -VULKAN_DEVICE_FUNCTION(vkGetFenceStatus) -VULKAN_DEVICE_FUNCTION(vkGetBufferMemoryRequirements) -VULKAN_DEVICE_FUNCTION(vkGetImageMemoryRequirements) -VULKAN_DEVICE_FUNCTION(vkMapMemory) -VULKAN_DEVICE_FUNCTION(vkQueueSubmit) -VULKAN_DEVICE_FUNCTION(vkQueueWaitIdle) -VULKAN_DEVICE_FUNCTION(vkResetCommandBuffer) -VULKAN_DEVICE_FUNCTION(vkResetCommandPool) -VULKAN_DEVICE_FUNCTION(vkResetDescriptorPool) -VULKAN_DEVICE_FUNCTION(vkResetFences) -VULKAN_DEVICE_FUNCTION(vkUnmapMemory) -VULKAN_DEVICE_FUNCTION(vkUpdateDescriptorSets) -VULKAN_DEVICE_FUNCTION(vkWaitForFences) -VULKAN_DEVICE_FUNCTION(vkCmdResetQueryPool) -VULKAN_DEVICE_FUNCTION(vkCmdBeginQuery) -VULKAN_DEVICE_FUNCTION(vkCmdEndQuery) -VULKAN_DEVICE_FUNCTION(vkGetQueryPoolResults) - -/* VK_KHR_swapchain */ -VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR) -VULKAN_DEVICE_FUNCTION(vkCreateSwapchainKHR) -VULKAN_DEVICE_FUNCTION(vkDestroySwapchainKHR) -VULKAN_DEVICE_FUNCTION(vkQueuePresentKHR) -VULKAN_DEVICE_FUNCTION(vkGetSwapchainImagesKHR) - -/* - * Redefine these every time you include this header! - */ -#undef VULKAN_GLOBAL_FUNCTION -#undef VULKAN_INSTANCE_FUNCTION -#undef VULKAN_DEVICE_FUNCTION diff --git a/src/FNA3D_Memory.c b/src/FNA3D_Memory.c deleted file mode 100644 index 8488f2c5..00000000 --- a/src/FNA3D_Memory.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* FNA3D - 3D Graphics Library for FNA - * - * Copyright (c) 2020-2024 Ethan Lee - * - * 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. - * - * Ethan "flibitijibibo" Lee - * - */ - -#include "FNA3D_Memory.h" - -#ifdef USE_SDL3 -#include -#else -#include -#define SDL_Mutex SDL_mutex -#endif - -/* - * Memory Allocator - */ - -#define STARTING_ALLOCATION_SIZE 64000000 /* 64MB */ -#define ALLOCATION_INCREMENT 16000000 /* 16MB */ - -typedef struct FNA3D_MemoryAllocation FNA3D_MemoryAllocation; - -typedef struct FNA3D_MemoryFreeRegion -{ - FNA3D_MemoryAllocation *parent; - - size_t offset; - size_t size; - - size_t allocationIndex; - size_t sortedIndex; -} FNA3D_MemoryFreeRegion; - -struct FNA3D_MemoryUsedRegion -{ - FNA3D_MemoryAllocation *parent; - - size_t offset; - size_t size; - size_t resourceOffset; /* Differs from offset based on alignment */ - size_t resourceSize; /* Differs from size based on alignment */ - size_t alignment; - - uint8_t isBuffer; - void* defragResource; -}; - -typedef struct FNA3D_SubAllocator FNA3D_SubAllocator; - -struct FNA3D_MemoryAllocation -{ - FNA3D_SubAllocator *parent; - - FNA3D_MemoryPlatformHandle handle; - size_t size; - - FNA3D_MemoryUsedRegion **usedRegions; - size_t usedRegionCount; - size_t usedRegionCapacity; - size_t usedSpace; - - FNA3D_MemoryFreeRegion **freeRegions; - size_t freeRegionCount; - size_t freeRegionCapacity; - size_t freeSpace; - - uint8_t dedicated; /* For renderers with device-local memory */ - uint8_t available; - - uint8_t *mapPointer; - SDL_Mutex *mapLock; -}; - -struct FNA3D_SubAllocator -{ - size_t index; /* Index within FNA3D_MemoryAllocator */ - size_t nextAllocationSize; - - FNA3D_MemoryAllocation **allocations; - size_t allocationCount; - - FNA3D_MemoryFreeRegion **sortedFreeRegions; - size_t sortedFreeRegionCount; - size_t sortedFreeRegionCapacity; -}; - -struct FNA3D_MemoryAllocator -{ - FNA3D_MemoryDriver driver; - - FNA3D_SubAllocator *subAllocators; - size_t subAllocatorCount; - - FNA3D_MemoryUsedRegion **usedRegionsToDestroy; - size_t usedRegionsToDestroyCount; - size_t usedRegionsToDestroyCapacity; - - SDL_Mutex *lock; -}; - -static void FNA3D_INTERNAL_RemoveMemoryFreeRegion( - FNA3D_MemoryAllocator *allocator, - FNA3D_MemoryFreeRegion *freeRegion -) { - size_t i; - FNA3D_MemoryAllocation *allocation; - FNA3D_SubAllocator *subAllocator; - - SDL_LockMutex(allocator->lock); - - allocation = freeRegion->parent; - subAllocator = allocation->parent; - - if (allocation->available) - { - /* Close the gap in the sorted list */ - if (subAllocator->sortedFreeRegionCount > 1) - { - for (i = freeRegion->sortedIndex; i < subAllocator->sortedFreeRegionCount - 1; i += 1) - { - subAllocator->sortedFreeRegions[i] = - subAllocator->sortedFreeRegions[i + 1]; - - subAllocator->sortedFreeRegions[i]->sortedIndex = i; - } - } - - subAllocator->sortedFreeRegionCount -= 1; - } - - /* Close the gap in the buffer list */ - if (allocation->freeRegionCount > 1 && freeRegion->allocationIndex != allocation->freeRegionCount - 1) - { - allocation->freeRegions[freeRegion->allocationIndex] = - allocation->freeRegions[allocation->freeRegionCount - 1]; - - allocation->freeRegions[freeRegion->allocationIndex]->allocationIndex = - freeRegion->allocationIndex; - } - - allocation->freeRegionCount -= 1; - - allocation->freeSpace -= freeRegion->size; - - SDL_free(freeRegion); - - SDL_UnlockMutex(allocator->lock); -} - -static void FNA3D_INTERNAL_NewMemoryFreeRegion( - FNA3D_MemoryAllocator *allocator, - FNA3D_MemoryAllocation *allocation, - size_t offset, - size_t size -) { - FNA3D_SubAllocator *subAllocator; - FNA3D_MemoryFreeRegion *newFreeRegion; - size_t newOffset, newSize; - size_t insertionIndex; - int32_t i; - - SDL_LockMutex(allocator->lock); - - /* Look for an adjacent region to merge */ - for (i = allocation->freeRegionCount - 1; i >= 0; i -= 1) - { - /* Check left side */ - if (allocation->freeRegions[i]->offset + allocation->freeRegions[i]->size == offset) - { - newOffset = allocation->freeRegions[i]->offset; - newSize = allocation->freeRegions[i]->size + size; - - FNA3D_INTERNAL_RemoveMemoryFreeRegion( - allocator, - allocation->freeRegions[i] - ); - FNA3D_INTERNAL_NewMemoryFreeRegion( - allocator, - allocation, - newOffset, - newSize - ); - - SDL_UnlockMutex(allocator->lock); - return; - } - - /* Check right side */ - if (allocation->freeRegions[i]->offset == offset + size) - { - newOffset = offset; - newSize = allocation->freeRegions[i]->size + size; - - FNA3D_INTERNAL_RemoveMemoryFreeRegion( - allocator, - allocation->freeRegions[i] - ); - FNA3D_INTERNAL_NewMemoryFreeRegion( - allocator, - allocation, - newOffset, - newSize - ); - - SDL_UnlockMutex(allocator->lock); - return; - } - } - - /* Region is not contiguous with another free region, make a new one */ - allocation->freeRegionCount += 1; - if (allocation->freeRegionCount > allocation->freeRegionCapacity) - { - allocation->freeRegionCapacity *= 2; - allocation->freeRegions = (FNA3D_MemoryFreeRegion**) SDL_realloc( - allocation->freeRegions, - sizeof(FNA3D_MemoryFreeRegion*) * allocation->freeRegionCapacity - ); - } - - newFreeRegion = (FNA3D_MemoryFreeRegion*) SDL_malloc(sizeof(FNA3D_MemoryFreeRegion)); - newFreeRegion->offset = offset; - newFreeRegion->size = size; - newFreeRegion->parent = allocation; - - allocation->freeSpace += size; - - allocation->freeRegions[allocation->freeRegionCount - 1] = newFreeRegion; - newFreeRegion->allocationIndex = allocation->freeRegionCount - 1; - - if (allocation->available) - { - subAllocator = allocation->parent; - insertionIndex = 0; - - for (i = 0; i < subAllocator->sortedFreeRegionCount; i += 1) - { - if (subAllocator->sortedFreeRegions[i]->size < size) - { - /* This is where the new region should go */ - break; - } - - insertionIndex += 1; - } - - if (subAllocator->sortedFreeRegionCount + 1 > subAllocator->sortedFreeRegionCapacity) - { - subAllocator->sortedFreeRegionCapacity *= 2; - subAllocator->sortedFreeRegions = SDL_realloc( - subAllocator->sortedFreeRegions, - sizeof(FNA3D_MemoryFreeRegion*) * subAllocator->sortedFreeRegionCapacity - ); - } - - /* Perform insertion sort */ - if ( subAllocator->sortedFreeRegionCount > 0 && - insertionIndex != subAllocator->sortedFreeRegionCount ) - { - for (i = subAllocator->sortedFreeRegionCount; i > insertionIndex && i > 0; i -= 1) - { - subAllocator->sortedFreeRegions[i] = subAllocator->sortedFreeRegions[i - 1]; - subAllocator->sortedFreeRegions[i]->sortedIndex = i; - } - } - - subAllocator->sortedFreeRegionCount += 1; - subAllocator->sortedFreeRegions[insertionIndex] = newFreeRegion; - newFreeRegion->sortedIndex = insertionIndex; - } - - SDL_UnlockMutex(allocator->lock); -} - -uint8_t FNA3D_INTERNAL_RemoveMemoryUsedRegion( - FNA3D_MemoryAllocator *allocator, - FNA3D_MemoryUsedRegion *usedRegion -) { - uint32_t i; - uint8_t needsDefrag; - FNA3D_MemoryAllocation *allocation; - - SDL_LockMutex(allocator->lock); - - allocation = usedRegion->parent; - - for (i = 0; i < allocation->usedRegionCount; i += 1) - { - if (allocation->usedRegions[i] == usedRegion) - { - /* Plug the hole */ - if (i != allocation->usedRegionCount - 1) - { - allocation->usedRegions[i] = - allocation->usedRegions[allocation->usedRegionCount - 1]; - } - - break; - } - } - - allocation->usedSpace -= usedRegion->size; - allocation->usedRegionCount -= 1; - - FNA3D_INTERNAL_NewMemoryFreeRegion( - allocator, - usedRegion->parent, - usedRegion->offset, - usedRegion->size - ); - - needsDefrag = !allocation->dedicated; - - SDL_free(usedRegion); - - SDL_UnlockMutex(allocator->lock); - - return needsDefrag; -} - -static FNA3D_MemoryUsedRegion* FNA3D_INTERNAL_NewMemoryUsedRegion( - FNA3D_MemoryAllocator *allocator, - FNA3D_MemoryAllocation *allocation, - size_t offset, - size_t size, - size_t resourceOffset, - size_t resourceSize, - size_t alignment -) { - FNA3D_MemoryUsedRegion *memoryUsedRegion; - - SDL_LockMutex(allocator->lock); - - if (allocation->usedRegionCount == allocation->usedRegionCapacity) - { - allocation->usedRegionCapacity *= 2; - allocation->usedRegions = (FNA3D_MemoryUsedRegion**) SDL_realloc( - allocation->usedRegions, - allocation->usedRegionCapacity * sizeof(FNA3D_MemoryUsedRegion*) - ); - } - - memoryUsedRegion = (FNA3D_MemoryUsedRegion*) SDL_malloc(sizeof(FNA3D_MemoryUsedRegion)); - memoryUsedRegion->parent = allocation; - memoryUsedRegion->offset = offset; - memoryUsedRegion->size = size; - memoryUsedRegion->resourceOffset = resourceOffset; - memoryUsedRegion->resourceSize = resourceSize; - memoryUsedRegion->alignment = alignment; - - allocation->usedSpace += size; - - allocation->usedRegions[allocation->usedRegionCount] = memoryUsedRegion; - allocation->usedRegionCount += 1; - - SDL_UnlockMutex(allocator->lock); - - return memoryUsedRegion; -} - -static FNA3D_MemoryAllocation* FNA3D_INTERNAL_Allocate( - FNA3D_MemoryAllocator *allocator, - size_t subAllocatorIndex, - size_t memorySize, - uint8_t dedicated, - uint8_t deviceLocal, - uint8_t hostVisible -) { - FNA3D_SubAllocator *subAllocator = &allocator->subAllocators[subAllocatorIndex]; - FNA3D_MemoryAllocation *allocation; - uint8_t result; - - allocation = (FNA3D_MemoryAllocation*) SDL_malloc(sizeof(FNA3D_MemoryAllocation)); - allocation->size = memorySize; - allocation->freeSpace = 0; /* added by FreeRegions */ - allocation->usedSpace = 0; /* added by UsedRegions */ - allocation->mapLock = SDL_CreateMutex(); - - subAllocator->allocationCount += 1; - subAllocator->allocations = (FNA3D_MemoryAllocation**) SDL_realloc( - subAllocator->allocations, - sizeof(FNA3D_MemoryAllocation*) * subAllocator->allocationCount - ); - - subAllocator->allocations[subAllocator->allocationCount - 1] = allocation; - - if (dedicated) - { - allocation->dedicated = 1; - allocation->available = 0; - } - else - { - allocation->dedicated = 0; - allocation->available = 1; - } - - allocation->usedRegions = (FNA3D_MemoryUsedRegion**) SDL_malloc(sizeof(FNA3D_MemoryUsedRegion*)); - allocation->usedRegionCount = 0; - allocation->usedRegionCapacity = 1; - - allocation->freeRegions = (FNA3D_MemoryFreeRegion**) SDL_malloc(sizeof(FNA3D_MemoryFreeRegion*)); - allocation->freeRegionCount = 0; - allocation->freeRegionCapacity = 1; - - allocation->parent = subAllocator; - - result = allocator->driver.AllocDeviceMemory( - allocator->driver.driverData, - subAllocatorIndex, - memorySize, - deviceLocal, - hostVisible, - (FNA3D_MemoryPlatformHandle*) &allocation->handle, - &allocation->mapPointer - ); - - if (!result) - { - /* Uh oh, we couldn't allocate, time to clean up */ - SDL_free(allocation->freeRegions); - - subAllocator->allocationCount -= 1; - subAllocator->allocations = (FNA3D_MemoryAllocation**) SDL_realloc( - subAllocator->allocations, - sizeof(FNA3D_MemoryAllocation*) * subAllocator->allocationCount - ); - - SDL_free(allocation); - return NULL; - } - - FNA3D_INTERNAL_NewMemoryFreeRegion( - allocator, - allocation, - 0, - allocation->size - ); - - return allocation; -} - -static void FNA3D_INTERNAL_Deallocate( - FNA3D_MemoryAllocator *allocator, - FNA3D_SubAllocator *subAllocator, - size_t allocationIndex -) { - size_t i; - FNA3D_MemoryAllocation *allocation; - - SDL_LockMutex(allocator->lock); - - allocation = subAllocator->allocations[allocationIndex]; - - for (i = 0; i < allocation->freeRegionCount; i += 1) - { - FNA3D_INTERNAL_RemoveMemoryFreeRegion( - allocator, - allocation->freeRegions[i] - ); - } - SDL_free(allocation->freeRegions); - - /* No need to iterate used regions because deallocate - * only happens when there are 0 used regions - */ - SDL_free(allocation->usedRegions); - - allocator->driver.FreeDeviceMemory( - allocator->driver.driverData, - allocation->handle, - allocation->size, - subAllocator->index - ); - - SDL_DestroyMutex(allocation->mapLock); - SDL_free(allocation); - - if (allocationIndex != subAllocator->allocationCount - 1) - { - subAllocator->allocations[allocationIndex] = subAllocator->allocations[ - subAllocator->allocationCount - 1 - ]; - } - - subAllocator->allocationCount -= 1; - - SDL_UnlockMutex(allocator->lock); -} - -FNA3D_MemoryAllocator* FNA3D_CreateMemoryAllocator( - FNA3D_MemoryDriver *driver, - size_t numSubAllocators -) { - size_t i; - FNA3D_MemoryAllocator *result; - FNA3D_SubAllocator *subAllocator; - - result = (FNA3D_MemoryAllocator*) SDL_malloc( - sizeof(FNA3D_MemoryAllocator) - ); - SDL_memcpy(&result->driver, driver, sizeof(FNA3D_MemoryDriver)); - result->subAllocators = (FNA3D_SubAllocator*) SDL_malloc( - sizeof(FNA3D_SubAllocator) * numSubAllocators - ); - result->subAllocatorCount = numSubAllocators; - - for (i = 0; i < result->subAllocatorCount; i += 1) - { - subAllocator = &result->subAllocators[i]; - - subAllocator->index = i; - subAllocator->nextAllocationSize = STARTING_ALLOCATION_SIZE; - subAllocator->allocations = NULL; - subAllocator->allocationCount = 0; - - subAllocator->sortedFreeRegions = (FNA3D_MemoryFreeRegion**) SDL_malloc( - sizeof(FNA3D_MemoryFreeRegion*) * 4 - ); - subAllocator->sortedFreeRegionCount = 0; - subAllocator->sortedFreeRegionCapacity = 4; - } - - result->usedRegionsToDestroyCapacity = 16; - result->usedRegionsToDestroyCount = 0; - result->usedRegionsToDestroy = (FNA3D_MemoryUsedRegion**) SDL_malloc( - sizeof(FNA3D_MemoryUsedRegion*) * - result->usedRegionsToDestroyCapacity - ); - - result->lock = SDL_CreateMutex(); - - return result; -} - -void FNA3D_DestroyMemoryAllocator(FNA3D_MemoryAllocator *allocator) -{ - size_t i; - int32_t j, k; - FNA3D_SubAllocator *subAllocator; - - for (i = 0; i < allocator->subAllocatorCount; i += 1) - { - subAllocator = &allocator->subAllocators[i]; - - for (j = subAllocator->allocationCount - 1; j >= 0; j -= 1) - { - for (k = subAllocator->allocations[j]->usedRegionCount - 1; k >= 0; k -= 1) - { - FNA3D_INTERNAL_RemoveMemoryUsedRegion( - allocator, - subAllocator->allocations[j]->usedRegions[k] - ); - } - - FNA3D_INTERNAL_Deallocate( - allocator, - subAllocator, - j - ); - } - - if (subAllocator->allocations != NULL) - { - SDL_free(subAllocator->allocations); - } - SDL_free(subAllocator->sortedFreeRegions); - } - - SDL_free(allocator->usedRegionsToDestroy); - - SDL_DestroyMutex(allocator->lock); - SDL_free(allocator->subAllocators); - SDL_free(allocator); -} - -void FNA3D_Memory_LockAllocator(FNA3D_MemoryAllocator *allocator) -{ - SDL_LockMutex(allocator->lock); -} - -void FNA3D_Memory_UnlockAllocator(FNA3D_MemoryAllocator *allocator) -{ - SDL_UnlockMutex(allocator->lock); -} - -static inline size_t FNA3D_INTERNAL_NextHighestAlignment( - size_t n, - size_t align -) { - return align * ((n + align - 1) / align); -} - -uint8_t FNA3D_Memory_BindResource( - FNA3D_MemoryAllocator *allocator, - size_t subAllocatorIndex, - size_t requiredSize, - size_t requiredAlignment, - uint8_t isHostVisible, - uint8_t isDeviceLocal, - uint8_t shouldAllocDedicated, - size_t resourceSize, /* may be different from requirements size! */ - uint8_t resourceIsImage, - FNA3D_MemoryPlatformHandle resource, - void *defragResourceHandle, - FNA3D_MemoryUsedRegion** pMemoryUsedRegion -) { - FNA3D_MemoryAllocation *allocation; - FNA3D_SubAllocator *subAllocator; - FNA3D_MemoryFreeRegion *region; - FNA3D_MemoryUsedRegion *usedRegion; - - size_t allocationSize; - size_t alignedOffset; - uint32_t newRegionSize, newRegionOffset; - uint8_t bindResult; - - subAllocator = &allocator->subAllocators[subAllocatorIndex]; - - SDL_assert(resource != 0); - - SDL_LockMutex(allocator->lock); - - /* find the largest free region and use it */ - if (!shouldAllocDedicated && subAllocator->sortedFreeRegionCount > 0) - { - region = subAllocator->sortedFreeRegions[0]; - allocation = region->parent; - - alignedOffset = FNA3D_INTERNAL_NextHighestAlignment( - region->offset, - requiredAlignment - ); - - if (alignedOffset + requiredSize <= region->offset + region->size) - { - usedRegion = FNA3D_INTERNAL_NewMemoryUsedRegion( - allocator, - allocation, - region->offset, - requiredSize + (alignedOffset - region->offset), - alignedOffset, - resourceSize, - requiredAlignment - ); - - usedRegion->isBuffer = !resourceIsImage; - usedRegion->defragResource = defragResourceHandle; - - newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize); - newRegionOffset = alignedOffset + requiredSize; - - /* remove and add modified region to re-sort */ - FNA3D_INTERNAL_RemoveMemoryFreeRegion( - allocator, - region - ); - - /* if size is 0, no need to re-insert */ - if (newRegionSize != 0) - { - FNA3D_INTERNAL_NewMemoryFreeRegion( - allocator, - allocation, - newRegionOffset, - newRegionSize - ); - } - - SDL_UnlockMutex(allocator->lock); - - SDL_LockMutex(usedRegion->parent->mapLock); - if (!resourceIsImage) - { - bindResult = allocator->driver.BindBufferMemory( - allocator->driver.driverData, - usedRegion->parent->handle, - alignedOffset, - resource - ); - } - else - { - bindResult = allocator->driver.BindImageMemory( - allocator->driver.driverData, - usedRegion->parent->handle, - alignedOffset, - resource - ); - } - SDL_UnlockMutex(usedRegion->parent->mapLock); - if (!bindResult) - { - FNA3D_INTERNAL_RemoveMemoryUsedRegion( - allocator, - usedRegion - ); - - return 0; - } - - *pMemoryUsedRegion = usedRegion; - return 1; - } - } - - /* No suitable free regions exist, allocate a new memory region */ - - if (shouldAllocDedicated) - { - allocationSize = requiredSize; - } - else if (requiredSize > subAllocator->nextAllocationSize) - { - /* allocate a page of required size aligned to ALLOCATION_INCREMENT increments */ - allocationSize = - FNA3D_INTERNAL_NextHighestAlignment(requiredSize, ALLOCATION_INCREMENT); - } - else - { - allocationSize = subAllocator->nextAllocationSize; - } - - allocation = FNA3D_INTERNAL_Allocate( - allocator, - subAllocatorIndex, - allocationSize, - shouldAllocDedicated, - isDeviceLocal, - isHostVisible - ); - - /* Uh oh, we're out of memory */ - if (allocation == NULL) - { - SDL_UnlockMutex(allocator->lock); - - /* Responsibility of the caller to handle being out of memory */ - FNA3D_LogWarn("Failed to allocate memory!"); - return 2; - } - - usedRegion = FNA3D_INTERNAL_NewMemoryUsedRegion( - allocator, - allocation, - 0, - requiredSize, - 0, - resourceSize, - requiredAlignment - ); - - usedRegion->isBuffer = !resourceIsImage; - usedRegion->defragResource = defragResourceHandle; - - region = allocation->freeRegions[0]; - - newRegionOffset = region->offset + requiredSize; - newRegionSize = region->size - requiredSize; - - FNA3D_INTERNAL_RemoveMemoryFreeRegion( - allocator, - region - ); - - if (newRegionSize != 0) - { - FNA3D_INTERNAL_NewMemoryFreeRegion( - allocator, - allocation, - newRegionOffset, - newRegionSize - ); - } - - SDL_UnlockMutex(allocator->lock); - - SDL_LockMutex(usedRegion->parent->mapLock); - if (!resourceIsImage) - { - bindResult = allocator->driver.BindBufferMemory( - allocator->driver.driverData, - usedRegion->parent->handle, - 0, - resource - ); - } - else - { - bindResult = allocator->driver.BindImageMemory( - allocator->driver.driverData, - usedRegion->parent->handle, - 0, - resource - ); - } - SDL_UnlockMutex(usedRegion->parent->mapLock); - if (!bindResult) - { - FNA3D_INTERNAL_RemoveMemoryUsedRegion( - allocator, - usedRegion - ); - - return 0; - } - - *pMemoryUsedRegion = usedRegion; - return 1; -} - -uint8_t* FNA3D_Memory_GetHostPointer( - FNA3D_MemoryUsedRegion *usedRegion, - size_t offset -) { - return ( - usedRegion->parent->mapPointer + - usedRegion->resourceOffset + - offset - ); -} - -void FNA3D_Memory_FreeEmptyAllocations(FNA3D_MemoryAllocator *allocator) -{ - FNA3D_SubAllocator *subAllocator; - size_t i; - int32_t j; - - SDL_LockMutex(allocator->lock); - - for (i = 0; i < allocator->subAllocatorCount; i += 1) - { - subAllocator = &allocator->subAllocators[i]; - - for (j = subAllocator->allocationCount - 1; j >= 0; j -= 1) - { - if (subAllocator->allocations[j]->usedRegionCount == 0) - { - FNA3D_INTERNAL_Deallocate( - allocator, - subAllocator, - j - ); - } - } - } - - SDL_UnlockMutex(allocator->lock); -} - -static uint8_t FNA3D_INTERNAL_FindAllocationToDefragment( - FNA3D_MemoryAllocator *allocator, - FNA3D_SubAllocator **subAllocator, - size_t *allocationIndexToDefrag -) { - size_t i, j; - FNA3D_SubAllocator *curAllocator; - - for (i = 0; i < allocator->subAllocatorCount; i += 1) - { - curAllocator = &allocator->subAllocators[i]; - - for (j = 0; j < curAllocator->allocationCount; j += 1) - { - if (curAllocator->allocations[j]->freeRegionCount > 1) - { - *subAllocator = curAllocator; - *allocationIndexToDefrag = j; - return 1; - } - } - } - - return 0; -} - -uint8_t FNA3D_Memory_Defragment(FNA3D_MemoryAllocator *allocator) -{ - FNA3D_SubAllocator *subAllocator; - FNA3D_MemoryAllocation *allocation; - size_t allocationIndexToDefrag; - FNA3D_MemoryFreeRegion *freeRegion; - FNA3D_MemoryUsedRegion *currentRegion; - uint8_t defragResult; - size_t i, j; - - SDL_LockMutex(allocator->lock); - - allocator->driver.BeginDefragCommands(allocator->driver.driverData); - - if (FNA3D_INTERNAL_FindAllocationToDefragment( - allocator, - &subAllocator, - &allocationIndexToDefrag - )) { - - allocation = subAllocator->allocations[allocationIndexToDefrag]; - - /* Make the allocation temporarily unavailable */ - allocation->available = 0; - for (i = 0; i < allocation->freeRegionCount; i += 1) - { - freeRegion = allocation->freeRegions[i]; - - /* close the gap in the sorted list */ - if (subAllocator->sortedFreeRegionCount > 1) - { - for (j = freeRegion->sortedIndex; j < subAllocator->sortedFreeRegionCount - 1; j += 1) - { - subAllocator->sortedFreeRegions[j] = - subAllocator->sortedFreeRegions[j + 1]; - - subAllocator->sortedFreeRegions[j]->sortedIndex = j; - } - } - - subAllocator->sortedFreeRegionCount -= 1; - } - - for (i = 0; i < allocation->usedRegionCount; i += 1) - { - currentRegion = allocation->usedRegions[i]; - - if (currentRegion->isBuffer) - { - defragResult = allocator->driver.DefragBuffer( - allocator->driver.driverData, - currentRegion->defragResource, - currentRegion->resourceSize - ); - } - else - { - defragResult = allocator->driver.DefragImage( - allocator->driver.driverData, - currentRegion->defragResource, - currentRegion->resourceSize - ); - } - - if (!defragResult) - { - return 0; - } - - if (allocator->usedRegionsToDestroyCount >= allocator->usedRegionsToDestroyCapacity) - { - allocator->usedRegionsToDestroyCapacity *= 2; - allocator->usedRegionsToDestroy = (FNA3D_MemoryUsedRegion**) SDL_realloc( - allocator->usedRegionsToDestroy, - sizeof(FNA3D_MemoryUsedRegion*) * allocator->usedRegionsToDestroyCapacity - ); - } - - allocator->usedRegionsToDestroy[ - allocator->usedRegionsToDestroyCount - ] = currentRegion; - - allocator->usedRegionsToDestroyCount += 1; - } - } - - allocator->driver.EndDefragCommands(allocator->driver.driverData); - - SDL_UnlockMutex(allocator->lock); - - return 1; -} - -uint8_t FNA3D_Memory_DestroyDefragmentedRegions(FNA3D_MemoryAllocator *allocator) -{ - uint8_t needsDefrag = 0; - size_t i; - for (i = 0; i < allocator->usedRegionsToDestroyCount; i += 1) - { - needsDefrag |= FNA3D_INTERNAL_RemoveMemoryUsedRegion( - allocator, - allocator->usedRegionsToDestroy[i] - ); - } - - allocator->usedRegionsToDestroyCount = 0; - return needsDefrag; -} - -/* - * Buffer Containers - */ - -struct FNA3D_BufferContainer -{ - size_t sizeInBytes; - FNA3D_BufferHandle *activeBuffer; - - /* These are all the buffers that have been used by this container. - * If a buffer is bound and then updated with Discard, a new buffer - * will be added to this list. - * These can be reused after they are submitted and command processing is complete. - */ - size_t bufferCapacity; - size_t bufferCount; - FNA3D_BufferHandle **referencedBuffers; -}; - -FNA3D_BufferContainer* FNA3D_Memory_CreateBufferContainer( - FNA3D_MemoryAllocator *allocator, - uint8_t isVertexData, - size_t sizeInBytes -) { - FNA3D_BufferContainer *result = (FNA3D_BufferContainer*) SDL_malloc( - sizeof(FNA3D_BufferContainer) - ); - - result->sizeInBytes = sizeInBytes; - result->bufferCapacity = 1; - result->bufferCount = 1; - result->activeBuffer = allocator->driver.CreateBufferHandle( - allocator->driver.driverData, - isVertexData, - sizeInBytes - ); - result->referencedBuffers = SDL_malloc(sizeof(FNA3D_BufferHandle*)); - result->referencedBuffers[0] = result->activeBuffer; - - return result; -} - -void FNA3D_Memory_DestroyBufferContainer( - FNA3D_MemoryAllocator *allocator, - FNA3D_BufferContainer *container -) { - allocator->driver.MarkBufferHandlesForDestroy( - allocator->driver.driverData, - container->referencedBuffers, - container->bufferCount - ); - - SDL_free(container->referencedBuffers); - SDL_free(container); -} - -FNA3D_BufferHandle* FNA3D_Memory_GetActiveBuffer( - FNA3D_BufferContainer *container -) { - return container->activeBuffer; -} - -FNA3D_BufferHandle* FNA3D_Memory_DiscardActiveBuffer( - FNA3D_MemoryAllocator *allocator, - FNA3D_BufferContainer *container -) { - size_t i; - - /* If a previously-discarded buffer is available, we can use that. */ - for (i = 0; i < container->bufferCount; i += 1) - { - if (!allocator->driver.BufferHandleInUse( - allocator->driver.driverData, - container->referencedBuffers[i] - )) { - container->activeBuffer = container->referencedBuffers[i]; - break; - } - } - - /* If no buffer is available, generate a new one. */ - if (i == container->bufferCount) - { - container->activeBuffer = allocator->driver.CloneBufferHandle( - allocator->driver.driverData, - container->activeBuffer - ); - - if (container->bufferCount >= container->bufferCapacity) - { - container->bufferCapacity += 1; - container->referencedBuffers = SDL_realloc( - container->referencedBuffers, - container->bufferCapacity * sizeof(FNA3D_BufferHandle*) - ); - } - - container->referencedBuffers[container->bufferCount] = - container->activeBuffer; - container->bufferCount += 1; - } - - return container->activeBuffer; -} diff --git a/src/FNA3D_Memory.h b/src/FNA3D_Memory.h deleted file mode 100644 index 9151de24..00000000 --- a/src/FNA3D_Memory.h +++ /dev/null @@ -1,215 +0,0 @@ -/* FNA3D - 3D Graphics Library for FNA - * - * Copyright (c) 2020-2024 Ethan Lee - * - * 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. - * - * Ethan "flibitijibibo" Lee - * - */ - -#ifndef FNA3D_MEMORY_H -#define FNA3D_MEMORY_H - -#include "FNA3D_Driver.h" - -#include /* for size_t */ - -/* Driver-defined memory structures */ - -typedef uint64_t FNA3D_MemoryPlatformHandle; -typedef struct FNA3D_BufferHandle FNA3D_BufferHandle; - -/* Renderers will contain a memory driver, so we can call back into the renderer - * to do platform-specific things that don't have to do with the high-level - * memory management - */ - -typedef struct FNA3D_MemoryDriver -{ - uint8_t (*AllocDeviceMemory)( - FNA3D_Renderer *driverData, - size_t subAllocatorIndex, - size_t memorySize, - uint8_t deviceLocal, - uint8_t hostVisible, - FNA3D_MemoryPlatformHandle* driverMemory, - uint8_t **mapPointer - ); - void (*FreeDeviceMemory)( - FNA3D_Renderer *driverData, - FNA3D_MemoryPlatformHandle driverMemory, - size_t memorySize, - size_t subAllocatorIndex - ); - uint8_t (*BindBufferMemory)( - FNA3D_Renderer *driverData, - FNA3D_MemoryPlatformHandle deviceMemory, - size_t alignedOffset, - FNA3D_MemoryPlatformHandle buffer - ); - uint8_t (*BindImageMemory)( - FNA3D_Renderer *driverData, - FNA3D_MemoryPlatformHandle deviceMemory, - size_t alignedOffset, - FNA3D_MemoryPlatformHandle image - ); - void (*BeginDefragCommands)( - FNA3D_Renderer *driverData - ); - void (*EndDefragCommands)( - FNA3D_Renderer *driverData - ); - uint8_t (*DefragBuffer)( - FNA3D_Renderer *driverData, - void* resource, - size_t resourceSize - ); - uint8_t (*DefragImage)( - FNA3D_Renderer *driverData, - void* resource, - size_t resourceSize - ); - - FNA3D_BufferHandle *(*CreateBufferHandle)( - FNA3D_Renderer *driverData, - uint8_t isVertexData, - size_t sizeInBytes - ); - FNA3D_BufferHandle *(*CloneBufferHandle)( - FNA3D_Renderer *driverData, - FNA3D_BufferHandle *buffer - ); - void (*MarkBufferHandlesForDestroy)( - FNA3D_Renderer *driverData, - FNA3D_BufferHandle **buffers, - size_t bufferCount - ); - uint8_t (*BufferHandleInUse)( - FNA3D_Renderer *driverData, - FNA3D_BufferHandle *buffer - ); - - FNA3D_Renderer *driverData; -} FNA3D_MemoryDriver; - -#define ASSIGN_MEMORY_DRIVER_FUNC(func, name) \ - memoryDriver.func = name##_Memory_##func; -#define ASSIGN_MEMORY_DRIVER(name) \ - memoryDriver.driverData = (FNA3D_Renderer*) renderer; \ - ASSIGN_MEMORY_DRIVER_FUNC(AllocDeviceMemory, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(FreeDeviceMemory, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(BindBufferMemory, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(BindImageMemory, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(BeginDefragCommands, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(EndDefragCommands, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(DefragBuffer, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(DefragImage, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(CreateBufferHandle, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(CloneBufferHandle, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(MarkBufferHandlesForDestroy, name) \ - ASSIGN_MEMORY_DRIVER_FUNC(BufferHandleInUse, name) - -/* - * Memory Allocator Interface - */ - -typedef struct FNA3D_MemoryAllocator FNA3D_MemoryAllocator; - -typedef struct FNA3D_MemoryUsedRegion FNA3D_MemoryUsedRegion; - -FNA3D_SHAREDINTERNAL FNA3D_MemoryAllocator* FNA3D_CreateMemoryAllocator( - FNA3D_MemoryDriver *driver, - size_t numSubAllocators -); - -FNA3D_SHAREDINTERNAL void FNA3D_DestroyMemoryAllocator(FNA3D_MemoryAllocator *allocator); - -FNA3D_SHAREDINTERNAL void FNA3D_Memory_LockAllocator(FNA3D_MemoryAllocator *allocator); -FNA3D_SHAREDINTERNAL void FNA3D_Memory_UnlockAllocator(FNA3D_MemoryAllocator *allocator); - -FNA3D_SHAREDINTERNAL uint8_t FNA3D_Memory_BindResource( - FNA3D_MemoryAllocator *allocator, - size_t subAllocatorIndex, - size_t requiredSize, - size_t requiredAlignment, - uint8_t isHostVisible, - uint8_t isDeviceLocal, - uint8_t shouldAllocDedicated, - size_t resourceSize, /* may be different from requirements size! */ - uint8_t resourceIsImage, - FNA3D_MemoryPlatformHandle resource, - void* defragResourceHandle, - FNA3D_MemoryUsedRegion** pMemoryUsedRegion -); - -FNA3D_SHAREDINTERNAL uint8_t* FNA3D_Memory_GetHostPointer( - FNA3D_MemoryUsedRegion *usedRegion, - size_t offset -); - -FNA3D_SHAREDINTERNAL void FNA3D_Memory_FreeEmptyAllocations(FNA3D_MemoryAllocator *allocator); - -FNA3D_SHAREDINTERNAL uint8_t FNA3D_Memory_Defragment(FNA3D_MemoryAllocator *allocator); - -FNA3D_SHAREDINTERNAL uint8_t FNA3D_Memory_DestroyDefragmentedRegions(FNA3D_MemoryAllocator *allocator); - -FNA3D_SHAREDINTERNAL uint8_t FNA3D_INTERNAL_RemoveMemoryUsedRegion( - FNA3D_MemoryAllocator *allocator, - FNA3D_MemoryUsedRegion *usedRegion -); - -/* - * Buffer Container Interface - */ - -/* Buffer containers refer to locations in memory previously allocated - * - * To properly support SETDATAOPTIONS_DISCARD the renderer's "buffer handle" is - * actually a container pointing to a buffer. - * - * This lets us change out the internal buffer without affecting - * the client or requiring a stall. - * - * The "discarded" buffers are kept around to avoid memory fragmentation - * being created by buffers that frequently discard. - */ -typedef struct FNA3D_BufferContainer FNA3D_BufferContainer; - -FNA3D_SHAREDINTERNAL FNA3D_BufferContainer* FNA3D_Memory_CreateBufferContainer( - FNA3D_MemoryAllocator *allocator, - uint8_t isVertexData, - size_t sizeInBytes -); - -FNA3D_SHAREDINTERNAL void FNA3D_Memory_DestroyBufferContainer( - FNA3D_MemoryAllocator *allocator, - FNA3D_BufferContainer *container -); - -FNA3D_SHAREDINTERNAL FNA3D_BufferHandle* FNA3D_Memory_GetActiveBuffer( - FNA3D_BufferContainer *container -); - -FNA3D_SHAREDINTERNAL FNA3D_BufferHandle* FNA3D_Memory_DiscardActiveBuffer( - FNA3D_MemoryAllocator *allocator, - FNA3D_BufferContainer *container -); - -#endif /* FNA3D_MEMORY_H */ diff --git a/visualc/FNA3D.vcxproj b/visualc/FNA3D.vcxproj index 919d2ea0..5b994395 100644 --- a/visualc/FNA3D.vcxproj +++ b/visualc/FNA3D.vcxproj @@ -42,14 +42,14 @@ - ..\..\SDL2\include;..\MojoShader;..\include;$(DXSDK_DIR)\Include;..\Vulkan-Headers\include;$(IncludePath) + ..\..\SDL2\include;..\MojoShader;..\include;$(DXSDK_DIR)\Include;$(IncludePath) ..\..\SDL2\lib\$(PlatformShortName);$(LibraryPath) Level3 Disabled - FNA3D_DRIVER_OPENGL;FNA3D_DRIVER_D3D11;FNA3D_DRIVER_VULKAN;MOJOSHADER_NO_VERSION_INCLUDE;MOJOSHADER_USE_SDL_STDLIB;MOJOSHADER_EFFECT_SUPPORT;MOJOSHADER_DEPTH_CLIPPING;MOJOSHADER_FLIP_RENDERTARGET;MOJOSHADER_XNA4_VERTEX_TEXTURES;SUPPORT_PROFILE_ARB1=0;SUPPORT_PROFILE_ARB1_NV=0;SUPPORT_PROFILE_BYTECODE=0;SUPPORT_PROFILE_D3D=0;SUPPORT_PROFILE_METAL=0;%(PreprocessorDefinitions) + FNA3D_DRIVER_OPENGL;FNA3D_DRIVER_D3D11;MOJOSHADER_NO_VERSION_INCLUDE;MOJOSHADER_USE_SDL_STDLIB;MOJOSHADER_EFFECT_SUPPORT;MOJOSHADER_DEPTH_CLIPPING;MOJOSHADER_FLIP_RENDERTARGET;MOJOSHADER_XNA4_VERTEX_TEXTURES;SUPPORT_PROFILE_ARB1=0;SUPPORT_PROFILE_ARB1_NV=0;SUPPORT_PROFILE_BYTECODE=0;SUPPORT_PROFILE_D3D=0;SUPPORT_PROFILE_METAL=0;%(PreprocessorDefinitions) true @@ -60,7 +60,7 @@ Level3 MaxSpeed - FNA3D_DRIVER_OPENGL;FNA3D_DRIVER_D3D11;FNA3D_DRIVER_VULKAN;MOJOSHADER_NO_VERSION_INCLUDE;MOJOSHADER_USE_SDL_STDLIB;MOJOSHADER_EFFECT_SUPPORT;MOJOSHADER_DEPTH_CLIPPING;MOJOSHADER_FLIP_RENDERTARGET;MOJOSHADER_XNA4_VERTEX_TEXTURES;SUPPORT_PROFILE_ARB1=0;SUPPORT_PROFILE_ARB1_NV=0;SUPPORT_PROFILE_BYTECODE=0;SUPPORT_PROFILE_D3D=0;SUPPORT_PROFILE_METAL=0;%(PreprocessorDefinitions) + FNA3D_DRIVER_OPENGL;FNA3D_DRIVER_D3D11;MOJOSHADER_NO_VERSION_INCLUDE;MOJOSHADER_USE_SDL_STDLIB;MOJOSHADER_EFFECT_SUPPORT;MOJOSHADER_DEPTH_CLIPPING;MOJOSHADER_FLIP_RENDERTARGET;MOJOSHADER_XNA4_VERTEX_TEXTURES;SUPPORT_PROFILE_ARB1=0;SUPPORT_PROFILE_ARB1_NV=0;SUPPORT_PROFILE_BYTECODE=0;SUPPORT_PROFILE_D3D=0;SUPPORT_PROFILE_METAL=0;%(PreprocessorDefinitions) true true @@ -89,9 +89,6 @@ CompileAsCpp - - CompileAsCpp - CompileAsCpp @@ -111,26 +108,20 @@ CompileAsCpp - - - - - - diff --git a/visualc/FNA3D.vcxproj.filters b/visualc/FNA3D.vcxproj.filters index 1a862363..e6978433 100644 --- a/visualc/FNA3D.vcxproj.filters +++ b/visualc/FNA3D.vcxproj.filters @@ -39,13 +39,9 @@ mojoshader - - mojoshader - mojoshader - @@ -57,7 +53,6 @@ -