diff --git a/.gitmodules b/.gitmodules index 072c876..c2c720e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,9 @@ [submodule "external/GameNetworkingSockets"] path = external/GameNetworkingSockets url = https://github.com/ValveSoftware/GameNetworkingSockets.git +[submodule "external/volk"] + path = external/volk + url = https://github.com/zeux/volk +[submodule "external/Vulkan-Utility-Libraries"] + path = external/Vulkan-Utility-Libraries + url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries diff --git a/build.cpp b/build.cpp index 79f9659..2443b5b 100644 --- a/build.cpp +++ b/build.cpp @@ -1,11 +1,14 @@ -#include "build/tools/public/target.h" #include "target.h" -#include "tier1/utlstring.h" #include "helper.h" +#include "tier1/utlstring.h" + CUtlVector all_IncludeDirectories = { "public", "external", + "external/Vulkan-Headers/include", + "external/Vulkan-Utility-Libraries/include", + "external/volk", "external/cglm/include", "external/stb", "external/SDL/include", @@ -71,6 +74,7 @@ CUtlString client_lib; #include "tier0/__build.cpp" #include "tier1/__build.cpp" +#include "tier2/__build.cpp" #include "game/server/__build.cpp" #include "game/client/__build.cpp" diff --git a/engine/__build.cpp b/engine/__build.cpp index 0fc93d1..3c3eb22 100644 --- a/engine/__build.cpp +++ b/engine/__build.cpp @@ -7,9 +7,7 @@ CUtlVector engine_CompiledFiles = { "engine/engine.cpp", "engine/cvar.cpp", - "engine/filesystem.cpp", "engine/filesystem_pak.cpp", - "engine/filesystem_libc.cpp", "engine/gamewindow_sdl.cpp", @@ -38,7 +36,9 @@ DECLARE_BUILD_STAGE(engine) else { ldProject.objects.AppendTail((Object_t){tier1_lib}); + ldProject.objects.AppendTail((Object_t){tier2_lib}); ldProject.objects.AppendTail((Object_t){rapier_lib}); + ldProject.objects.AppendTail((Object_t){material_lib}); if (bSteam) ldProject.objects.AppendTail((Object_t){steam_lib}); ldProject.linkType = ELINK_DYNAMIC_LIBRARY; diff --git a/engine/cvar.cpp b/engine/cvar.cpp index e69de29..dada8ce 100644 --- a/engine/cvar.cpp +++ b/engine/cvar.cpp @@ -0,0 +1,338 @@ +#include "icvar.h" +#include "tier2/ifilesystem.h" +#include "tier1/utlstring.h" +#include "tier1/utlvector.h" +#include "stdarg.h" + + +enum EConsoleMessageType +{ + CONSOLE_MESSAGE_TYPE_MESSAGE, + CONSOLE_MESSAGE_TYPE_WARNING, + CONSOLE_MESSAGE_TYPE_ERROR, +}; + +struct ConsoleMessage_t +{ + EConsoleMessageType type; + CUtlString szMessage; +}; + +void Msg( const char* message ) +{ + printf(message); + +} + +void Warning( const char* message ) +{ + +} + +void Error( const char* message ) +{ + +} + +class CConsole: public IConsole +{ +public: + virtual void Init() override; + virtual void Shutdown() override; + + // Variables + virtual void RegisterVar( ConVar *cvar ) override; + virtual void UnRegisterVar( ConVar *cvar ) override; + virtual ConVar *FindVar( const char *pName ) override; + + // Commands + virtual void RegisterCommand( ConCommand *cvar ) override; + virtual void UnRegisterCommand( ConCommand *cvar ) override; + virtual ConCommand *FindCommand( const char *pName ) override; + + // Command buffer + virtual void Execute( void ) override; + virtual void ExecuteArguments( CUtlVector &args ) override; + virtual CUtlVector> ParseCommandLine( CUtlString psz ) override; + + virtual void AddCommand( const char *psz ) override; + virtual void InsertCommand( const char *psz ) override; +}; + +IConsole *Console() +{ + static CConsole s_console; + return &s_console; +} + +void CConsole::Init() +{ +} + +void CConsole::Shutdown() +{ + +} + + +void CConsole::RegisterVar( ConVar *cvar ) +{ + m_convars.AppendTail(cvar); +} +void CConsole::UnRegisterVar( ConVar *cvar ) +{ + +} +ConVar *CConsole::FindVar( const char *pName ) +{ + for (auto &var: m_convars) + { + if (!V_strcmp(var->GetName(), pName)) + return var; + } + return NULL; +} + +void CConsole::RegisterCommand( ConCommand *cvar ) +{ + m_commands.AppendTail(cvar); +} +void CConsole::UnRegisterCommand( ConCommand *cvar ) +{ + +} +ConCommand *CConsole::FindCommand( const char *pName ) +{ + for (auto &var: m_commands) + { + if (!V_strcmp(var->GetName(), pName)) + return var; + } + return NULL; +} +CUtlString g_commandBuffer; + +//----------------------------------------------------------------------------- +// Executes arguments from CConsole::Execute +//----------------------------------------------------------------------------- +void CConsole::ExecuteArguments( CUtlVector &args ) +{ + if (args.GetSize()<1) + return; + + ConCommand *cmd = CConsole::FindCommand(args[0]); + if (!cmd) + { + V_printf("%s not found\n", args[0].GetString()); + return; + } + CUtlBuffer strbuffer(args.GetSize()); + for ( size_t i = 0; i < args.GetSize(); i++) + { + strbuffer[i] = args[i].GetString(); + }; + (cmd->GetCallback())(args.GetSize(), strbuffer); +} + +void CConsole::Execute( void ) +{ + CUtlVector> commands = ParseCommandLine(g_commandBuffer); + g_commandBuffer = 0; + for (auto &command: commands) + { + ExecuteArguments(command); + } +} + +//----------------------------------------------------------------------------- +// Parses command buffer. +//----------------------------------------------------------------------------- +CUtlVector> CConsole::ParseCommandLine( CUtlString psz ) +{ + CUtlVector arguments; + CUtlVector> commands; + CUtlString szArgument; + bool bIsQuote = false; + for ( auto &c: (CUtlVector&)psz ) + { + if ( c == '\"' ) + { + bIsQuote = !bIsQuote; + continue; + } + + if ( c == ';' || c == '\n' ) + { + if (bIsQuote) + { + continue; + } + if (szArgument != 0) + arguments.AppendTail(szArgument); + if ( arguments.GetSize() > 0 ) + commands.AppendTail(arguments); + szArgument = 0; + arguments = {}; + continue; + } + if ( c == '\t' || c == ' ' ) + { + if (bIsQuote) + { + szArgument.AppendTail(c); + continue; + } + + if (szArgument != 0) + arguments.AppendTail(szArgument); + szArgument = 0; + continue; + } + szArgument.AppendTail(c); + }; + if (szArgument != 0) + arguments.AppendTail(szArgument); + if ( arguments.GetSize() > 0 ) + commands.AppendTail(arguments); + return commands; +} + +void CConsole::AddCommand( const char *psz ) +{ + g_commandBuffer.AppendTail(psz); +} + +void CConsole::InsertCommand( const char *psz ) +{ + g_commandBuffer.AppendHead(psz); +}; + +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags ) + : ConVar(pName, pDefaultValue, flags, 0) +{ + +} +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString ) + : ConVar(pName, pDefaultValue, flags, pHelpString, 0) +{ +} +ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString, ConCommandFn callback ) +{ + m_szName = pName; + m_flags = flags; + m_szValue = pDefaultValue; + m_fValue = V_atof(pDefaultValue); + m_nValue = V_atoi(pDefaultValue); + Console()->RegisterVar(this); +} + +bool ConVar::IsFlagSet( int flag ) +{ + +} +const char *ConVar::GetHelpText( void ) +{ + return m_szHelpString; +} +bool ConVar::IsRegistered( void ) +{ + +} +const char *ConVar::GetName( void ) +{ + return m_szName; +} +void ConVar::AddFlags( int flags ) +{ + +} +bool ConVar::IsCommand( void ) +{ + +} + +void ConVar::InstallChangeCallback( ConCommandFn ) +{ + +} + +float ConVar::GetFloat( void ) +{ + return m_fValue; +} +int ConVar::GetInt( void ) +{ + return m_nValue; +} +bool ConVar::GetBool( void ) +{ + return m_nValue; +} +const char *ConVar::GetString( void ) +{ + +} + +void ConVar::SetValue( const char *szValue ) +{ + if (!szValue) + return; + m_szValue = szValue; + m_fValue = V_atof(szValue); + m_nValue = V_atoi(szValue); +} +void ConVar::SetValue( float fValue ) +{ + m_fValue = fValue; + m_nValue = fValue; + m_szValue = CUtlString("%f\n",fValue); +} +void ConVar::SetValue( int iValue ) +{ + m_fValue = iValue; + m_nValue = iValue; + m_szValue = CUtlString("%i\n",iValue); +} + +ConCommand::ConCommand(const char *pName, ConCommandFn callback, + const char *pHelpString, int flags) +{ + m_szName = pName; + m_callback = callback; + m_flags = flags; + Console()->RegisterCommand(this); +}; +const char *ConCommand::GetHelpText( void ) +{ + return m_szHelpString; +} +const char *ConCommand::GetName( void ) +{ + return m_szName; +} +ConCommandFn ConCommand::GetCallback( void ) +{ + return m_callback; +} + + + +void IConsole_Exec( int argc, char **argv) +{ + if (argc != 2) + return; + + IFileHandle *f = filesystem->Open(argv[1], FILEMODE_READ); + if (!f) + return; + CUtlBuffer b(f->Size()+1); + f->Read(b, b.GetSize()); + b[b.GetSize()-1] = 0; + Console()->AddCommand(b); + Console()->AddCommand(";"); + Console()->Execute(); +} + +ConCommand IConsole_ExecCmd("exec", IConsole_Exec); diff --git a/engine/engine.cpp b/engine/engine.cpp index 2135997..4ca6efe 100644 --- a/engine/engine.cpp +++ b/engine/engine.cpp @@ -1,6 +1,7 @@ -#include "ifilesystem.h" +#include "tier2/ifilesystem.h" #include "igamewindow.h" +#include "materialsystem/materialsystem.h" #include "tier1/interface.h" #include "tier1/commandline.h" #include "tier0/mem.h" @@ -16,6 +17,8 @@ extern "C" void FunnyMain( int argc, char **argv ) ServerGameDLL()->Init(); + Materials()->Init(); + for (;;) { gamewindow->UpdateWindow(); diff --git a/engine/filesystem_pak.cpp b/engine/filesystem_pak.cpp index 28029fc..675f50e 100644 --- a/engine/filesystem_pak.cpp +++ b/engine/filesystem_pak.cpp @@ -1,4 +1,4 @@ -#include "ifilesystem.h" +#include "tier2/ifilesystem.h" #include "tier1/interface.h" #include "tier0/lib.h" @@ -47,14 +47,14 @@ public: { int eLibcSeekMode = 0; switch (eSeekMode) { - case SEEKMODE_SET: - eLibcSeekMode = SEEK_SET; + case SEEKMODE_RELATIVE_CURRENT: + eLibcSeekMode = SEEK_CUR; break; case SEEKMODE_RELATIVE_END: eLibcSeekMode = SEEK_END; break; case SEEKMODE_RELATIVE_START: - eLibcSeekMode = SEEK_CUR; + eLibcSeekMode = SEEK_SET; break; } CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile; @@ -68,6 +68,12 @@ public: if (!pHandle) return 0; } + virtual size_t Size( IFileHandle *pFile ) override + { + CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile; + if (!pHandle) + return 0; + } virtual void Close( IFileHandle *pFile ) override { diff --git a/engine/gamewindow_sdl.cpp b/engine/gamewindow_sdl.cpp index d77f18b..3c909a5 100644 --- a/engine/gamewindow_sdl.cpp +++ b/engine/gamewindow_sdl.cpp @@ -11,7 +11,6 @@ #include "SDL3/SDL_vulkan.h" #include "SDL3/SDL_events.h" -SDL_Window *g_pWindow; class CSDLGameWindow: public IGameWindow { @@ -19,6 +18,20 @@ public: virtual void Init() override; virtual void Shutdown() override; virtual void UpdateWindow() override; + + virtual EGraphicsAPI GetGraphicsAPI() override; + + virtual int GetVulkanInstanceExtensionCount() override; + virtual const char **GetVulkanInstanceExtensions() override; + virtual void CreateVulkanSurface( void *pInstance ) override; + virtual void DestroyVulkanSurface( void *pInstance ) override; + virtual void *GetVulkanSurface() override; + +private: + SDL_Window *m_pWindow; + EGraphicsAPI m_ePreferredGraphicsAPI; + + void *m_pVulkanSurface; }; CSDLGameWindow g_sdlGameWindow; @@ -27,12 +40,14 @@ IGameWindow *gamewindow = &g_sdlGameWindow; void CSDLGameWindow::Init() { + m_ePreferredGraphicsAPI = GRAPHICS_API_VULKAN; + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD)) Plat_FatalErrorFunc("SDL_Init: %s\n", SDL_GetError()); - g_pWindow = SDL_CreateWindow("funnygame", 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); - if (!g_pWindow) - Plat_FatalErrorFunc("SDL_Init: %s\n", SDL_GetError()); + m_pWindow = SDL_CreateWindow("funnygame", 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); + if (!m_pWindow) + Plat_FatalErrorFunc("SDL_CreateWindow: %s\n", SDL_GetError()); } void CSDLGameWindow::Shutdown() @@ -47,6 +62,8 @@ void CSDLGameWindow::UpdateWindow() { switch (event.type) { + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + break; case SDL_EVENT_QUIT: SDL_Quit(); Plat_Exit(0); @@ -56,3 +73,50 @@ void CSDLGameWindow::UpdateWindow() } } } +EGraphicsAPI CSDLGameWindow::GetGraphicsAPI() +{ + return GRAPHICS_API_VULKAN; +} + +int CSDLGameWindow::GetVulkanInstanceExtensionCount() +{ + if ( m_ePreferredGraphicsAPI != GRAPHICS_API_VULKAN ) + return -1; + + uint32_t nCount; + SDL_Vulkan_GetInstanceExtensions(&nCount); + + return nCount; +} + +const char **CSDLGameWindow::GetVulkanInstanceExtensions() +{ + if ( m_ePreferredGraphicsAPI != GRAPHICS_API_VULKAN ) + return 0; + + uint32_t nCount; + return (const char **)SDL_Vulkan_GetInstanceExtensions(&nCount); +} + +void CSDLGameWindow::CreateVulkanSurface( void *pInstance ) +{ + if ( m_ePreferredGraphicsAPI != GRAPHICS_API_VULKAN ) + return; + + SDL_Vulkan_CreateSurface(m_pWindow, (VkInstance)pInstance, NULL, (VkSurfaceKHR*)&m_pVulkanSurface); +} + +void CSDLGameWindow::DestroyVulkanSurface( void *pInstance ) +{ + SDL_Vulkan_DestroySurface((VkInstance)pInstance, (VkSurfaceKHR)m_pVulkanSurface, NULL); +} + +void *CSDLGameWindow::GetVulkanSurface() +{ + if ( m_ePreferredGraphicsAPI != GRAPHICS_API_VULKAN ) + return 0; + + + return m_pVulkanSurface; +} + diff --git a/external/Vulkan-Headers b/external/Vulkan-Headers index 75ad707..2e0a6e6 160000 --- a/external/Vulkan-Headers +++ b/external/Vulkan-Headers @@ -1 +1 @@ -Subproject commit 75ad707a587e1469fb53a901b9b68fe9f6fbc11f +Subproject commit 2e0a6e699e35c9609bde2ca4abb0d380c0378639 diff --git a/external/Vulkan-Utility-Libraries b/external/Vulkan-Utility-Libraries new file mode 160000 index 0000000..4f4c0b6 --- /dev/null +++ b/external/Vulkan-Utility-Libraries @@ -0,0 +1 @@ +Subproject commit 4f4c0b6c61223b703f1c753a404578d7d63932ad diff --git a/external/volk b/external/volk new file mode 160000 index 0000000..d64d20b --- /dev/null +++ b/external/volk @@ -0,0 +1 @@ +Subproject commit d64d20b4eaf2698296e085d9d9638c69af280e3e diff --git a/fpc/fpc_temp b/fpc/fpc_temp new file mode 100644 index 0000000..6b5b748 Binary files /dev/null and b/fpc/fpc_temp differ diff --git a/fpc/library/clang/c.cpp b/fpc/library/clang/c.cpp index 7ad6c28..4668901 100644 --- a/fpc/library/clang/c.cpp +++ b/fpc/library/clang/c.cpp @@ -34,7 +34,6 @@ LinkProject_t CClangCompiler::Compile( CProject_t *pProject ) { if (!clangbackend && CommandLine()->CheckParam("-experimental_header_include")) clangbackend = (IClangBackend*)CreateInterface(CLANG_BACKEND_INTERFACE_NAME, NULL); - V_printf("CLANG: %p\n", clangbackend); if (pProject->m_szName == 0) { @@ -121,11 +120,12 @@ LinkProject_t CClangCompiler::Compile( CProject_t *pProject ) } if (clangbackend) - bAreDependenciesUpdated = clangbackend->AreFileDependenciesUpdated(file, szOutputFile, args); + bAreDependenciesUpdated = clangbackend->AreFileDependenciesUpdated(file, 0, szOutputFile, args); if (!filesystem2->ShouldRecompile(file, szOutputFile) && !bAreDependenciesUpdated) goto skipcompile; args.AppendTail("-c"); + args.AppendTail("-g"); args.AppendTail("-o"); args.AppendTail(szOutputFile); args.AppendTail(file); @@ -150,7 +150,7 @@ skipcompile: if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID) { if (!pProject->m_target.szSysroot) - Plat_FatalErrorFunc("-sysroot must be specified for android\n"); + Plat_FatalErrorFunc("sysroot must be specified for android\n"); cfile.m_szArguments.AppendHead(CUtlString("%s/bin/clang",pProject->m_target.szSysroot)); } else diff --git a/fpc/library/clang/c_libclang.cpp b/fpc/library/clang/c_libclang.cpp index 455cc8e..c3c5b6d 100644 --- a/fpc/library/clang/c_libclang.cpp +++ b/fpc/library/clang/c_libclang.cpp @@ -10,10 +10,11 @@ class CClangBackend: public IClangBackend { public: - virtual bool AreFileDependenciesUpdated( CUtlString szFile, CUtlString szOutputFile, CUtlVector arguments ) override; + virtual bool AreFileDependenciesUpdated( CUtlString szFile, CUtlString szOutputFile, CUtlString szHashFile, CUtlVector arguments ) override; bool bAnyOutdated; CUtlString szCurrentFile; + CUtlString szHashFile; private: static void InclusionVisitor( CXFile included_file, CXSourceLocation *include_stack, unsigned include_len, CXClientData client_data ); @@ -21,7 +22,7 @@ private: EXPOSE_INTERFACE(CClangBackend, IClangBackend, CLANG_BACKEND_INTERFACE_NAME); -bool CClangBackend::AreFileDependenciesUpdated( CUtlString szFile, CUtlString szOutputFile, CUtlVector arguments ) +bool CClangBackend::AreFileDependenciesUpdated( CUtlString szFile, CUtlString szOutputFile, CUtlString szHashFile, CUtlVector arguments ) { szCurrentFile = szOutputFile; bAnyOutdated = false; diff --git a/fpc/library/clang/c_libclang.h b/fpc/library/clang/c_libclang.h index fd6eac7..e726cd6 100644 --- a/fpc/library/clang/c_libclang.h +++ b/fpc/library/clang/c_libclang.h @@ -9,7 +9,7 @@ abstract_class IClangBackend { public: - virtual bool AreFileDependenciesUpdated( CUtlString szFile, CUtlString szOutputFile, CUtlVector arguments ) = 0; + virtual bool AreFileDependenciesUpdated( CUtlString szFile, CUtlString szOutputFile, CUtlString szHashFile, CUtlVector arguments ) = 0; }; extern IClangBackend *clangbackend; diff --git a/fpc/library/clang/ld.cpp b/fpc/library/clang/ld.cpp index 6018d9c..c76ebd0 100644 --- a/fpc/library/clang/ld.cpp +++ b/fpc/library/clang/ld.cpp @@ -53,7 +53,7 @@ CUtlString CClangLinker::Link( LinkProject_t *pProject ) filesystem2->MakeDirectory(szOutputDir); if (pProject->linkType == ELINK_STATIC_LIBRARY) { - V_printf(" AR %s\n", pProject->m_szName.GetString()); + V_printf(" AR %s\n", pProject->m_szName.GetString()); bool shouldRecompile = false; CUtlVector args; for (auto object: pProject->objects) diff --git a/materialsystem/__build.cpp b/materialsystem/__build.cpp index 131d013..a33d6d0 100644 --- a/materialsystem/__build.cpp +++ b/materialsystem/__build.cpp @@ -5,10 +5,10 @@ #include "tier1/commandline.h" CUtlVector MaterialSystem_CompiledFiles = { + "materialsystem/materialsystem.cpp", + "materialsystem/vulkan/rendercontext.cpp", "materialsystem/vulkan/material.cpp", - "materialsystem/vulkan/materialsystem.cpp", - "materialsystem/vulkan/shader.cpp", - "materialsystem/vulkan/vulkan_state.cpp", + "external/volk/volk.c", }; CUtlString material_lib; @@ -23,6 +23,7 @@ DECLARE_BUILD_STAGE(MaterialSystem) compileProject.bFPIC = true; ldProject = ccompiler->Compile(&compileProject); ldProject.linkType = ELINK_STATIC_LIBRARY; + ldProject.libraries = { "vulkan" }; CUtlString outputProject = linker->Link(&ldProject); material_lib = outputProject; diff --git a/materialsystem/materialsystem.cpp b/materialsystem/materialsystem.cpp new file mode 100644 index 0000000..5cdf297 --- /dev/null +++ b/materialsystem/materialsystem.cpp @@ -0,0 +1,41 @@ +#include "materialsystem/materialsystem.h" + +class CMaterialSystem: public IMaterialSystem +{ +public: + virtual void Init() override; + virtual void Frame( float fTime ) override; + virtual void Shutdown() override; + + virtual IRenderContext *GetRenderContext( void ) override; +}; + +void CMaterialSystem::Init() +{ + GetRenderContext()->Init(); +} + +void CMaterialSystem::Frame( float fTime ) +{ + GetRenderContext()->Frame(fTime); +} + +void CMaterialSystem::Shutdown() +{ + GetRenderContext()->Shutdown(); +} + +extern IRenderContext *g_pVkRenderContext; + + +IRenderContext *CMaterialSystem::GetRenderContext( void ) +{ + return g_pVkRenderContext; +} + + +IMaterialSystem *Materials( void ) +{ + static CMaterialSystem s_materialSystem; + return &s_materialSystem; +} diff --git a/materialsystem/vulkan/vulkan_state.cpp b/materialsystem/vulkan/commandbuffer.cpp similarity index 100% rename from materialsystem/vulkan/vulkan_state.cpp rename to materialsystem/vulkan/commandbuffer.cpp diff --git a/materialsystem/vulkan/computeshader.cpp b/materialsystem/vulkan/computeshader.cpp new file mode 100644 index 0000000..e69de29 diff --git a/materialsystem/vulkan/device_extensions.h b/materialsystem/vulkan/device_extensions.h new file mode 100644 index 0000000..41747d8 --- /dev/null +++ b/materialsystem/vulkan/device_extensions.h @@ -0,0 +1,2 @@ +REQUIRED_EXTENSION(VK_KHR_SWAPCHAIN) +OPTIONAL_EXTENSION(VK_KHR_RAY_TRACING_PIPELINE) diff --git a/materialsystem/vulkan/materialsystem.cpp b/materialsystem/vulkan/materialsystem.cpp deleted file mode 100644 index 36c0361..0000000 --- a/materialsystem/vulkan/materialsystem.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "materialsystem/imaterialsystem.h" - -class CVkRenderingContext -{ - -}; - -CVkRenderingContext g_vkRenderingContext; - -class CVkMaterialSystem: public IMaterialSystem -{ -public: - virtual void Init(); - virtual void Frame( float fDeltaTime ); - virtual void Shutdown(); - - IRenderContext *GetRenderContext(); -}; - -CVkMaterialSystem g_vkMaterialSystem; -IMaterialSystem *materials = &g_vkMaterialSystem; - - -void CVkMaterialSystem::Init() -{ - -} - -void CVkMaterialSystem::Frame( float fDeltaTime ) -{ - -} - -void CVkMaterialSystem::Shutdown() -{ - -} - - - diff --git a/materialsystem/vulkan/raytracingshader.cpp b/materialsystem/vulkan/raytracingshader.cpp new file mode 100644 index 0000000..e69de29 diff --git a/materialsystem/vulkan/rendercontext.cpp b/materialsystem/vulkan/rendercontext.cpp new file mode 100644 index 0000000..c2997dd --- /dev/null +++ b/materialsystem/vulkan/rendercontext.cpp @@ -0,0 +1,274 @@ +#include "SDL3/SDL_vulkan.h" +#include "materialsystem/materialsystem.h" +#include "tier0/platform.h" +#include "tier1/utlvector.h" +#define VK_NO_PROTOTYPES +#include "vulkan/vulkan_core.h" +#include "vulkan_state.h" +#include "igamewindow.h" + + +#define REQUIRED_EXTENSION(ext) ext##_EXTENSION_NAME, +#define OPTIONAL_EXTENSION(ext) ext##_EXTENSION_NAME, +const char *g_vkDeviceExtensions[] = { +#include "device_extensions.h" +}; +#undef REQUIRED_EXTENSION +#undef OPTIONAL_EXTENSION + + + +class CVkRenderContext: public IRenderContext +{ +public: + virtual void Init() override; + virtual void Frame( float fDeltaTime ) override; + virtual void Shutdown() override; + + virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) override; + virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) override; + virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) override; + virtual IImage *CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) override; + + virtual void DestroyBuffer( IBuffer *pBuffer ) override; + virtual void DestroyImage( IImage *pImage ) override; +private: + IBuffer *CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage ); + IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage ); + + VkPhysicalDevice SelectPhysicalDevice( CUtlVector physicalDevices ); + + void CreateSwapchain(); + void DestroySwapchain(); +}; + +//----------------------------------------------------------------------------- +// Creates vertex buffer. Wrapper over CreateBuffer +//----------------------------------------------------------------------------- +IVertexBuffer *CVkRenderContext::CreateVertexBuffer( uint32_t nSize ) +{ + return (IVertexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT); +} + +//----------------------------------------------------------------------------- +// Creates index buffer. Wrapper over CreateBuffer +//----------------------------------------------------------------------------- +IIndexBuffer *CVkRenderContext::CreateIndexBuffer( uint32_t nSize ) +{ + return (IIndexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT); +} + +//----------------------------------------------------------------------------- +// Creates basic vulkan buffer +//----------------------------------------------------------------------------- +IBuffer *CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage ) +{ +} + +//----------------------------------------------------------------------------- +// Creates vulkan buffer aligned to the nAlignment +// Useful for everything eg: ray tracing, which requires them to be aligned +// to the groupBaseAlignment. +//----------------------------------------------------------------------------- +IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage ) +{ + +} + + +IImage *CVkRenderContext::CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) +{ + +} + +IImage *CVkRenderContext::CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) +{ + +} + + +void CVkRenderContext::DestroyBuffer( IBuffer *pBuffer ) +{ + +} + +void CVkRenderContext::DestroyImage( IImage *pImage ) +{ + +} + +CVkRenderContext s_vkRenderContext; +IRenderContext *g_pVkRenderContext = &s_vkRenderContext; + + +uint32_t g_iDrawFamily; +uint32_t g_iPresentFamily; + +VkInstance g_vkInstance; +VkPhysicalDevice g_vkPhysicalDevice; +VkDevice g_vkDevice; +VkSwapchainKHR g_vkSwapchain; + + +void CVkRenderContext::Init() +{ + VkResult r; + + int nExtensionCount; + CUtlVector extensions = {}; + + uint32_t nPhysicalDevicesCount; + CUtlVector physicalDevices; + + uint32_t nNumQueueFamilies = 0; + CUtlVector queueFamilyProperties; + + VkApplicationInfo stApplicationInfo = {}; + VkInstanceCreateInfo stInstanceCreateInfo = {}; + + VkDeviceQueueCreateInfo stDeviceQueueCreateInfo = {}; + VkDeviceCreateInfo stDeviceCreateInfo = {}; + + float fPriority = 1.0; + + r = volkInitialize(); + VULKAN_RESULT_PRINT(r, volkInitialize) + + // Get extensions required by game window + nExtensionCount = gamewindow->GetVulkanInstanceExtensionCount(); + extensions.Resize(nExtensionCount); + V_memcpy(extensions.GetData(), gamewindow->GetVulkanInstanceExtensions(), extensions.GetSize()*sizeof(const char*)); + + // Create instance + stApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + stApplicationInfo.apiVersion = VK_API_VERSION_1_4; + stApplicationInfo.pApplicationName = "funny"; + stApplicationInfo.pEngineName = "funny"; + + stInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + stInstanceCreateInfo.pApplicationInfo = &stApplicationInfo; + stInstanceCreateInfo.enabledExtensionCount = extensions.GetSize(); + stInstanceCreateInfo.ppEnabledExtensionNames = extensions.GetData(); + + r = vkCreateInstance(&stInstanceCreateInfo, NULL, &g_vkInstance); + VULKAN_RESULT_PRINT(r, vkCreateInstance) + + // volk requires to load instance this way + volkLoadInstance(g_vkInstance); + + + // Get amount of physical devices + r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, NULL); + VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) + physicalDevices.Resize(nPhysicalDevicesCount); + + // Read all physical devices + r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, physicalDevices.GetData()); + VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) + + g_vkPhysicalDevice = SelectPhysicalDevice(physicalDevices); + + + // Get all queues + vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL); + queueFamilyProperties.Resize(nNumQueueFamilies); + + uint32_t i = 0; + vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, queueFamilyProperties.GetData()); + + for (auto &family: queueFamilyProperties) + { + if (family.queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + g_iDrawFamily = i; + g_iPresentFamily = i; + } + i++; + } + + + // Create device + stDeviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + stDeviceQueueCreateInfo.queueCount = 1; + stDeviceQueueCreateInfo.pQueuePriorities = &fPriority; + stDeviceQueueCreateInfo.queueFamilyIndex = g_iDrawFamily; + + stDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + stDeviceCreateInfo.queueCreateInfoCount = 1; + stDeviceCreateInfo.pQueueCreateInfos = &stDeviceQueueCreateInfo; + vkCreateDevice(g_vkPhysicalDevice, &stDeviceCreateInfo, NULL, &g_vkDevice); + + CreateSwapchain(); +} + +void CVkRenderContext::Frame( float fDeltaTime ) +{ + +} + +void CVkRenderContext::CreateSwapchain() +{ + gamewindow->CreateVulkanSurface(g_vkInstance); + +} + +void CVkRenderContext::DestroySwapchain() +{ + vkDestroySwapchainKHR(g_vkDevice, g_vkSwapchain, NULL); + gamewindow->DestroyVulkanSurface(g_vkInstance); +} + +//----------------------------------------------------------------------------- +// TODO: Move to the rendering context +//----------------------------------------------------------------------------- +void CVkRenderContext::Shutdown() +{ + vkDestroyInstance(g_vkInstance, NULL); +} + + +//----------------------------------------------------------------------------- +// Selects best device to be used in rendering. +// We want to get the best perfomance out of the GPU, so we need to select the +// best driver. +//----------------------------------------------------------------------------- +VkPhysicalDevice CVkRenderContext::SelectPhysicalDevice( CUtlVector physicalDevices ) +{ + uint32_t uMaxScore = 0; + VkPhysicalDevice selectedDevice = 0; + VkResult r; + + for (auto &device: physicalDevices) + { + uint32_t nExtensionCount; + CUtlVector extensions; + VkPhysicalDeviceFeatures stPhysicalDeviceFeatures; + VkPhysicalDeviceProperties stPhysicalDeviceProperties; + uint32_t uScore = 0; + + r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, NULL); + VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) + extensions.Resize(nExtensionCount); + + r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, extensions.GetData()); + VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) + + vkGetPhysicalDeviceProperties(device, &stPhysicalDeviceProperties); + vkGetPhysicalDeviceFeatures(device, &stPhysicalDeviceFeatures); + + if (stPhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + uScore += 1000; + if (stPhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) + uScore += 500; + + if (uScore >= uMaxScore) + { + selectedDevice = device; + uMaxScore = uScore; + } + } + + return selectedDevice; +} + + diff --git a/materialsystem/vulkan/vulkan_state.h b/materialsystem/vulkan/vulkan_state.h index e69de29..f6fdb92 100644 --- a/materialsystem/vulkan/vulkan_state.h +++ b/materialsystem/vulkan/vulkan_state.h @@ -0,0 +1,57 @@ +#ifndef VULKAN_STATE_H +#define VULKAN_STATE_H + + +#include "volk.h" +#include "vk_mem_alloc.h" +#include "tier0/platform.h" +#include "iappsystem.h" +#include "materialsystem/materialsystem.h" + +#define REQUIRED_EXTENSION(ext) bool bIsSupported_##ext; +#define OPTIONAL_EXTENSION(ext) bool bIsSupported_##ext; +struct SupportedVulkanExtensions_t +{ +#include "device_extensions.h" +}; +#undef REQUIRED_EXTENSION +#undef OPTIONAL_EXTENSION + +enum EDependencyMode +{ + DEPENDENCY_MODE_SHADER_IMAGE, + DEPENDENCY_MODE_SHADER_BUFFER, + DEPENDENCY_MODE_SHADER_ACCELERATION_STRUCTURE, + + + DEPENDENCY_MODE_DRAWCALL_VERTEX_BUFFER, + DEPENDENCY_MODE_DRAWCALL_INDEX_BUFFER, + DEPENDENCY_MODE_DRAWCALL_OUTPUT_IMAGE, +}; + +abstract_class IVkCommand +{ +public: + virtual void Call() = 0; + void AddDependency( IRenderingObject *pObject, EDependencyMode eDependencyMode ); +}; + +abstract_class IVkCommandBuffer: public IAppSystem +{ +public: + void PushCommand( IVkCommand *pCommand ); + + void Submit(); +}; + +extern IVkCommandBuffer *vkcommandbuffer; + +#undef __cplusplus +#include "vulkan/vk_enum_string_helper.h" +#define __cplusplus + +#define VULKAN_RESULT_PRINT(r, func) \ +if (r != VK_SUCCESS) \ + Plat_FatalErrorFunc(#func " failed: %s\n", string_VkResult(r)); + +#endif diff --git a/public/funnyformat.h b/public/funnyformat.h index 1611ac7..89dd360 100644 --- a/public/funnyformat.h +++ b/public/funnyformat.h @@ -2,7 +2,7 @@ #define FUNNY_FORMAT_H #include "tier0/platform.h" -#include "ifilesystem.h" +#include "tier2/ifilesystem.h" #include "tier1/utlvector.h" struct FunnyFormatParameter_t diff --git a/public/icvar.h b/public/icvar.h index e69de29..51fe502 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -0,0 +1,119 @@ +#ifndef CONSOLE_H +#define CONSOLE_H + +#include "iappsystem.h" +#include "tier0/platform.h" +#include "tier1/utlstring.h" +#include "tier1/utlvector.h" + +class ConVar; +class ConCommand; + + +typedef void(*ConCommandFn)(int argc, char **argv); + +abstract_class IConsole: public IAppSystem +{ +public: + // Variables + virtual void RegisterVar( ConVar *cvar ) = 0; + virtual void UnRegisterVar( ConVar *cvar ) = 0; + virtual ConVar *FindVar( const char *pName ) = 0; + + // Commands + virtual void RegisterCommand( ConCommand *cvar ) = 0; + virtual void UnRegisterCommand( ConCommand *cvar ) = 0; + virtual ConCommand *FindCommand( const char *pName ) = 0; + + // Command buffer + virtual void Execute( void ) = 0; + virtual void ExecuteArguments( CUtlVector &args ) = 0; + virtual CUtlVector> ParseCommandLine( CUtlString psz ) = 0; + + virtual void AddCommand( const char *psz ) = 0; + virtual void InsertCommand( const char *psz ) = 0; + + CUtlVector m_convars; + CUtlVector m_commands; +}; + +IConsole *Console(); + + +#define FCVAR_NONE 0 +#define FCVAR_DEVELOPMENTONLY 0x1 +#define FCVAR_GAMEDLL 0x2 +#define FCVAR_CLIENTDLL 0x4 +#define FCVAR_HIDDEN 0x8 + +#define FCVAR_PROTECTED 0x10 +#define FCVAR_SPONLY 0x20 +#define FCVAR_ARCHIVE 0x40 +#define FCVAR_NOTIFY 0x80 +#define FCVAR_CHEAT 0x100 +#define FCVAR_REPLICATED 0x200 + +class ConVar +{ +public: + ConVar( const char *pName, const char *pDefaultValue, int flags ); + ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString ); + ConVar( const char *pName, const char *pDefaultValue, int flags, + const char *pHelpString, ConCommandFn callback ); + + bool IsFlagSet( int flag ); + const char *GetHelpText( void ); + bool IsRegistered( void ); + const char *GetName( void ); + void AddFlags( int flags ); + bool IsCommand( void ); + + void InstallChangeCallback( ConCommandFn ); + + float GetFloat( void ); + int GetInt( void ); + bool GetBool( void ); + const char *GetString( void ); + + void SetValue( const char *szValue ); + void SetValue( float fValue ); + void SetValue( int iValue ); +private: + CUtlString m_szName; + CUtlString m_szHelpString; + CUtlString m_szDefaultValue; + + CUtlString m_szValue; + float m_fValue; + int m_nValue; + + int m_flags; +}; + + +class ConCommand +{ +public: + ConCommand(const char *pName, ConCommandFn callback, + const char *pHelpString=0, int flags=0); + + const char *GetName( void ); + const char *GetHelpText( void ); + ConCommandFn GetCallback( void ); +private: + CUtlString m_szName; + CUtlString m_szHelpString = NULL; + ConCommandFn m_callback; + + int m_flags; +}; + +#undef V_printf +#define V_printf(...) Msg(CUtlString(__VA_ARGS__).GetString()) + +void Msg( const char* message ); +void Warning( const char* message ); +void Error( const char* message ); + +#endif diff --git a/public/igamewindow.h b/public/igamewindow.h index 1185399..885cd75 100644 --- a/public/igamewindow.h +++ b/public/igamewindow.h @@ -4,10 +4,24 @@ #include "iappsystem.h" #include "tier0/platform.h" +enum EGraphicsAPI +{ + GRAPHICS_API_METAL, + GRAPHICS_API_VULKAN, +}; + abstract_class IGameWindow: public IAppSystem { public: virtual void UpdateWindow() = 0; + + virtual EGraphicsAPI GetGraphicsAPI() = 0; + + virtual int GetVulkanInstanceExtensionCount() = 0; + virtual const char **GetVulkanInstanceExtensions() = 0; + virtual void CreateVulkanSurface( void *pInstance ) = 0; + virtual void DestroyVulkanSurface( void *pInstance ) = 0; + virtual void *GetVulkanSurface() = 0; }; extern IGameWindow *gamewindow; diff --git a/public/materialsystem/imaterialsystem.h b/public/materialsystem/materialsystem.h similarity index 77% rename from public/materialsystem/imaterialsystem.h rename to public/materialsystem/materialsystem.h index cc68416..049965e 100644 --- a/public/materialsystem/imaterialsystem.h +++ b/public/materialsystem/materialsystem.h @@ -61,31 +61,30 @@ enum EMultisampleType abstract_class IImage : public IRenderingObject { public: - virtual void BlitTo( IImage *pImage ); + }; abstract_class IRenderContext: public IAppSystem { public: + virtual void Frame( float fTime ) = 0; virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) = 0; virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) = 0; - virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ); - virtual IImage *CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ); + virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) = 0; + virtual IImage *CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) = 0; - virtual void DestroyBuffer( IBuffer *pBuffer ); - virtual void DestroyImage( IImage *pImage ); + virtual void DestroyBuffer( IBuffer *pBuffer ) = 0; + virtual void DestroyImage( IImage *pImage ) = 0; }; abstract_class IMaterialSystem: public IAppSystem { public: - virtual void Init(); - virtual void Frame( float fTime ); - virtual void Shutdown(); + virtual void Frame( float fTime ) = 0; - IRenderContext *GetRenderContext(); + virtual IRenderContext *GetRenderContext( void) = 0; }; -extern IMaterialSystem *materials; +IMaterialSystem *Materials( void ); #endif diff --git a/public/tier0/lib.h b/public/tier0/lib.h index 78497ec..c6c7b65 100644 --- a/public/tier0/lib.h +++ b/public/tier0/lib.h @@ -13,6 +13,7 @@ #include "string.h" #include "stdio.h" #include "stdlib.h" +#include "ctype.h" //----------------------------------------------------------------------------- // string.h @@ -106,4 +107,24 @@ #define V_atoi atoi #define V_atof atof +//----------------------------------------------------------------------------- +// ctype.h +//----------------------------------------------------------------------------- + +#define V_isalnum isalnum +#define V_isalpha isalpha +#define V_isblank isblank +#define V_iscntrl iscntrl +#define V_isdigit isdigit +#define V_isgraph isgraph +#define V_islower islower +#define V_isprint isprint +#define V_ispunct ispunct +#define V_isspace isspace +#define V_isupper isupper +#define V_isxdigit isxdigit +#define V_tolower tolower +#define V_toupper toupper + + #endif diff --git a/public/tier1/utlbuffer.h b/public/tier1/utlbuffer.h index 549b646..0d0b525 100644 --- a/public/tier1/utlbuffer.h +++ b/public/tier1/utlbuffer.h @@ -23,10 +23,11 @@ template class CUtlBuffer { public: - CUtlBuffer( void ); + CUtlBuffer( void ); CUtlBuffer( size_t nSize ); CUtlBuffer( const CUtlBuffer& buffer ); CUtlBuffer( const CUtlResizableBuffer& buffer ); + ~CUtlBuffer( void ); size_t GetSize( void ) const; T* GetMemory(void) const; @@ -81,6 +82,12 @@ CUtlBuffer::CUtlBuffer( const CUtlResizableBuffer& buffer ) : m_nSize(buff V_memcpy(m_pData,buffer.pData,sizeof(T)*buffer.nSize); } +template +CUtlBuffer::~CUtlBuffer() +{ + if ( m_pData != 0) + V_free(m_pData); +} //----------------------------------------------------------------------------- // Gets memory size. //----------------------------------------------------------------------------- @@ -145,9 +152,10 @@ CUtlBuffer& CUtlBuffer::operator=(const CUtlBuffer& other) if ( m_pData != 0) V_free(m_pData); m_pData = (T*)V_malloc(sizeof(T)*other.m_nSize); + m_nSize = other.m_nSize; V_memcpy(m_pData, other.m_pData, sizeof(T)*other.m_nSize); } - return this; + return *this; } //----------------------------------------------------------------------------- diff --git a/public/tier2/fileformats/ini.h b/public/tier2/fileformats/ini.h index 1c2306a..fe16be0 100644 --- a/public/tier2/fileformats/ini.h +++ b/public/tier2/fileformats/ini.h @@ -3,6 +3,7 @@ #include "tier0/platform.h" #include "tier1/utlstring.h" +#include "tier1/utlvector.h" abstract_class IINISection { @@ -16,7 +17,7 @@ public: abstract_class IINIFile { public: - virtual void GetSection( const char *szSectionName ) = 0; + virtual IINISection *GetSection( const char *szSectionName ) = 0; }; abstract_class IINIManager diff --git a/public/ifilesystem.h b/public/tier2/ifilesystem.h similarity index 69% rename from public/ifilesystem.h rename to public/tier2/ifilesystem.h index bedf6f5..2f26440 100644 --- a/public/ifilesystem.h +++ b/public/tier2/ifilesystem.h @@ -11,15 +11,9 @@ enum EFileMode FILEMODE_APPEND = 0x04, }; -enum EFileType { - FILETYPE_NONE, - FILETYPE_SYSTEM, - FILETYPE_PAK, -}; - enum ESeekMode { - SEEKMODE_SET, + SEEKMODE_RELATIVE_CURRENT, SEEKMODE_RELATIVE_START, SEEKMODE_RELATIVE_END, }; @@ -35,6 +29,7 @@ public: size_t Read( void *pData, size_t nDataSize ); size_t Seek( ESeekMode eSeekMode, size_t nOffset ); size_t Tell( void ); + size_t Size( void ); void Close( void ); @@ -56,12 +51,28 @@ public: virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) = 0; virtual size_t Tell( IFileHandle *pFile ) = 0; + virtual size_t Size( IFileHandle *pFile ) = 0; virtual void Close( IFileHandle *pFile ) = 0; + + IFileSystem *m_pNext; + + void RegisterFileSystem(); }; extern IFileSystem *filesystem; -extern IFileSystem *filesystem_backend; -extern IFileSystem *filesystem_pak; +extern IFileSystem *g_pFileSystems; + +typedef IFileSystem *( *InstantiateFileSystemFn )( void ); +class CFileSystemRegistry +{ +public: + CFileSystemRegistry( InstantiateFileSystemFn fn, const char *szFileSystem ); +}; + +#define EXPOSE_FILESYSTEM( className, filesystemName ) \ + static IFileSystem *__Create##className##_filesystem() { return ( IFileSystem* )( new className ); }; \ + static CFileSystemRegistry __Create##className##_registry( __Create##className##_filesystem, filesystemName ); + #endif diff --git a/tests/ini/build.cpp b/tests/ini/build.cpp new file mode 100644 index 0000000..2ef1f20 --- /dev/null +++ b/tests/ini/build.cpp @@ -0,0 +1,35 @@ +#include "c.h" +#include "target.h" +#include "helper.h" + +DECLARE_BUILD_STAGE(ini_test) +{ + CProject_t p = { + .files = { + "../../tier0/lib.cpp", + "../../tier0/mem.cpp", + "../../tier0/platform.cpp", + "../../tier1/interface.cpp", + "../../tier1/utlbuffer.cpp", + "../../tier1/utlstring.cpp", + "../../tier1/utlvector.cpp", + "../../tier1/utlmap.cpp", + "../../tier1/commandline.cpp", + "../../tier2/fileformats/ini.cpp", + "../../tier2/filesystem.cpp", + "../../tier2/filesystem_libc.cpp", + "main.cpp", + }, + .includeDirectories = + { + "../../public" + }, + }; + p.m_szName = "initest"; + LinkProject_t l = ccompiler->Compile(&p); + CUtlString szPath = linker->Link(&l); + filesystem2->CopyFile("./", szPath); + + + return 0; +} diff --git a/tests/ini/initest b/tests/ini/initest new file mode 100644 index 0000000..01d2d95 Binary files /dev/null and b/tests/ini/initest differ diff --git a/tests/ini/main.cpp b/tests/ini/main.cpp new file mode 100644 index 0000000..14b74fa --- /dev/null +++ b/tests/ini/main.cpp @@ -0,0 +1,49 @@ +#include "tier0/lib.h" +#include "tier0/mem.h" +#include "tier1/utlbuffer.h" +#include "tier1/commandline.h" +#include "tier2/fileformats/ini.h" +#include "tier2/ifilesystem.h" + +int main( int argc, char **argv ) +{ + + const char *szFileName; + IFileHandle *pHandle = NULL; + size_t nSize = 0; + CUtlBuffer szData; + + CommandLine()->CreateCommandLine(argc, argv); + filesystem->Init(); + + // Get file + szFileName = CommandLine()->ParamValue("-f"); + if (!szFileName) + return 0; + + // Load it + pHandle = filesystem->Open(szFileName, FILEMODE_READ); + if (!pHandle) + return 0; + + // Get size + pHandle->Seek(SEEKMODE_RELATIVE_END, 0); + nSize = pHandle->Tell(); + pHandle->Seek(SEEKMODE_RELATIVE_START, 0); + + // Read it + szData = CUtlBuffer(nSize+1); + pHandle->Read(szData, nSize); + pHandle->Close(); + + szData[nSize] = 0; + + IINIFile *pIniFile = INIManager()->ReadString(szData); + if (!pIniFile) + return 0; + IINISection *pTestValues = pIniFile->GetSection("Test_Values"); + if (!pTestValues) + return 0; + V_printf("%s\n",pTestValues->GetStringValue("abc3d")); + +}; diff --git a/tests/ini/test1.ini b/tests/ini/test1.ini new file mode 100644 index 0000000..f86614a --- /dev/null +++ b/tests/ini/test1.ini @@ -0,0 +1,12 @@ + +[Test_Values] +a = "Hello world!\n" +b = true +c = false +c = 3.1415926 +d = 123456 +e = -2.71828 +f = -890 +g = .34 +abc3d = "Hello world from the funny engine, you can use \" to add quotes" + diff --git a/tests/ini/test2.ini b/tests/ini/test2.ini new file mode 100644 index 0000000..558ed37 --- /dev/null +++ b/tests/ini/test2.ini @@ -0,0 +1 @@ +[ diff --git a/tests/ini/test3.ini b/tests/ini/test3.ini new file mode 100644 index 0000000..95ef80c --- /dev/null +++ b/tests/ini/test3.ini @@ -0,0 +1 @@ +[Hello diff --git a/tests/ini/test4.ini b/tests/ini/test4.ini new file mode 100644 index 0000000..e849c76 --- /dev/null +++ b/tests/ini/test4.ini @@ -0,0 +1 @@ +[Test Hello] diff --git a/tests/ini/test5.ini b/tests/ini/test5.ini new file mode 100644 index 0000000..5ef5672 --- /dev/null +++ b/tests/ini/test5.ini @@ -0,0 +1,2 @@ +["Hello world"] +Test diff --git a/tests/ini/test6.ini b/tests/ini/test6.ini new file mode 100644 index 0000000..53973bf --- /dev/null +++ b/tests/ini/test6.ini @@ -0,0 +1,2 @@ +[Test] +a b diff --git a/tests/ini/test7.ini b/tests/ini/test7.ini new file mode 100644 index 0000000..4df87f3 --- /dev/null +++ b/tests/ini/test7.ini @@ -0,0 +1,2 @@ +[Test] +a = diff --git a/tests/ini/test8.ini b/tests/ini/test8.ini new file mode 100644 index 0000000..f6da3f4 --- /dev/null +++ b/tests/ini/test8.ini @@ -0,0 +1,5 @@ +[Test] +a = b +c = d + +d = test diff --git a/tier2/__build.cpp b/tier2/__build.cpp new file mode 100644 index 0000000..b13ac9e --- /dev/null +++ b/tier2/__build.cpp @@ -0,0 +1,31 @@ +#include "helper.h" +#include "c.h" +#include "ld.h" +#include "tier1/utlstring.h" +#include "tier1/commandline.h" + +CUtlVector tier2_CompiledFiles = { + "tier2/fileformats/ini.cpp", + "tier2/fileformats/json.cpp", + "tier2/filesystem.cpp", + "tier2/filesystem_libc.cpp", +}; +CUtlString tier2_lib; + +DECLARE_BUILD_STAGE(tier2) +{ + CProject_t compileProject = {}; + LinkProject_t ldProject = {}; + + compileProject.m_szName = "tier2"; + compileProject.files = tier2_CompiledFiles; + compileProject.includeDirectories = all_IncludeDirectories; + compileProject.bFPIC = true; + ldProject = ccompiler->Compile(&compileProject); + ldProject.linkType = ELINK_STATIC_LIBRARY; + + CUtlString outputProject = linker->Link(&ldProject); + tier2_lib = outputProject; + + return 0; +}; diff --git a/tier2/fileformats/ini.cpp b/tier2/fileformats/ini.cpp index 01a65ab..03daf55 100644 --- a/tier2/fileformats/ini.cpp +++ b/tier2/fileformats/ini.cpp @@ -1,7 +1,27 @@ #include "tier2/fileformats/ini.h" +#include "tier0/platform.h" #include "tier1/utlstring.h" #include "tier1/utlvector.h" +#include "tier0/lib.h" + +enum ESectionType +{ + SECTIONTYPE_String, + SECTIONTYPE_Boolean, + SECTIONTYPE_Float, +}; + + +struct SectionData_t +{ + ESectionType m_eSectionType; + CUtlString m_szKey; + + bool m_bData; + float m_fData; + CUtlString m_szData; +}; abstract_class CINISection: public IINISection { @@ -11,27 +31,247 @@ public: virtual const char *GetStringValue( const char *szKeyName ) override; virtual CUtlString GetUTLStringValue( const char *szKeyName ) override; - CUtlVector m_values; + CUtlVector m_values; + CUtlString m_szSectionName; }; +bool CINISection::GetBoolValue( const char *szKeyName ) +{ + +} + +int CINISection::GetIntValue( const char *szKeyName ) +{ + +} + +const char *CINISection::GetStringValue( const char *szKeyName ) +{ + return 0; +} + +CUtlString CINISection::GetUTLStringValue( const char *szKeyName ) +{ + +} + class CINIFile: public IINIFile { - virtual void GetSection( const char *szSectionName ) override; +public: + virtual IINISection *GetSection( const char *szSectionName ) override; CUtlVector m_sections; }; +IINISection *CINIFile::GetSection( const char *szSectionName ) +{ + for ( auto §ion: m_sections ) + { + if ( section->m_szSectionName == szSectionName ) + return (IINISection*)§ion; + } + return 0; +} + + class CINIManager: public IINIManager { public: virtual IINIFile *ReadString( const char *psz ) override; + bool IsWordSymbol( char c ); + CUtlVector TokenizeString(); }; IINIFile *CINIManager::ReadString( const char *psz ) { - CINIFile *pFile = new CINIFile; + CINIFile *pFile = 0; + CINIFile file = {}; + bool bIsQuoted; + bool bIsSlash; + + bool bIsVarName; + bool bIsVarValue; + bool bIsSectionName; + + CINISection currentSection; + SectionData_t currentSectionData; + size_t i = 0; + + char c; + + CUtlString szStringValue; + + CUtlVector tokens; + uint32_t nCurrentLine = 0; + + while (true) + { + c = psz[i]; + i++; + if (c == '\0') + break; + if (c == '\n') + nCurrentLine++; + + + if (bIsQuoted) + { + if (bIsSlash) + { + bIsSlash = false; + switch (c) + { + case '\\': + szStringValue.AppendTail('\\'); + continue; + case '"': + szStringValue.AppendTail('"'); + continue; + case 'n': + szStringValue.AppendTail('\n'); + continue; + case 't': + szStringValue.AppendTail('\n'); + continue; + case '\n': + szStringValue.AppendTail('\n'); + continue; + default: + szStringValue.AppendTail(c); + continue; + } + } else { + switch (c) + { + + case '\\': + bIsSlash = true; + continue; + + case '\n': + V_printf("line %i: new line was found but the string wasn't finished, did you forget to place \" in the end of the line?\n", nCurrentLine); + case '"': + bIsQuoted = false; + if (szStringValue == 0) + continue; + tokens.AppendTail(szStringValue); + szStringValue = 0; + continue; + default: + szStringValue.AppendTail(c); + continue; + } + } + + } else { + if (c == '"') + { + bIsQuoted = true; + } + + if (IsWordSymbol(c)) + { + szStringValue.AppendTail(c); + continue; + } else { + if (szStringValue != 0) + tokens.AppendTail(szStringValue); + szStringValue = 0; + if (V_isgraph(c) && c != '"') + tokens.AppendTail(CUtlString("%c", c)); + } + } + }; + + currentSectionData.m_eSectionType = SECTIONTYPE_String; + + for ( int i = 0; i < tokens.GetSize(); i++ ) + { + if (tokens[i] == "]") + { + V_printf("Error: unexpected ]\n"); + return 0; + } + if (tokens[i] == "[") + { + i++; + if (i>=tokens.GetSize()) + { + V_printf("Error: Trailing section start\n"); + return 0; + } + currentSection = {}; + currentSection.m_szSectionName = tokens[i]; + V_printf("[%s]\n",currentSection.m_szSectionName.GetString()); + + i++; + if (i>=tokens.GetSize()) + { + V_printf("Error: Trailing section name\n"); + return 0; + } + if (tokens[i] != "]") + { + V_printf("Error: expected ]\n"); + return 0; + } + continue; + } + if (tokens[i] == "=") + { + V_printf("Error: expected key\n"); + return 0; + } + currentSectionData = {}; + currentSectionData.m_szKey = tokens[i]; + + + + i++; + if (i>=tokens.GetSize()) + { + V_printf("Error: trailing key\n"); + return 0; + } + if (tokens[i] != "=") + { + V_printf("Error: expected =\n"); + return 0; + } + + i++; + + if (i>=tokens.GetSize()) + { + V_printf("Error: expected value\n"); + return 0; + } + currentSectionData.m_szData = tokens[i]; + currentSection.m_values.AppendTail(currentSectionData); + + } + + pFile = new CINIFile; + *pFile = file; + return (IINIFile*)pFile; } +bool CINIManager::IsWordSymbol( char c ) +{ + if (V_isalnum(c)) + return true; + switch (c) + { + case '-': + case '_': + case '.': + return true; + default: + return false; + } +} + +CUtlVector TokenizeString(); IINIManager *INIManager() { diff --git a/engine/filesystem.cpp b/tier2/filesystem.cpp similarity index 64% rename from engine/filesystem.cpp rename to tier2/filesystem.cpp index 25d627a..e2b7ad9 100644 --- a/engine/filesystem.cpp +++ b/tier2/filesystem.cpp @@ -1,4 +1,4 @@ -#include "ifilesystem.h" +#include "tier2/ifilesystem.h" #include "tier1/interface.h" #include "tier0/lib.h" @@ -22,6 +22,11 @@ size_t IFileHandle::Tell( void ) return m_pFileSystem->Tell(this); } +size_t IFileHandle::Size( void ) +{ + return m_pFileSystem->Size(this); +} + void IFileHandle::Close( void ) { m_pFileSystem->Close(this); @@ -32,8 +37,6 @@ class CFileSystem : public IFileSystem { public: virtual void Init() override { - filesystem_backend->Init(); - filesystem_pak->Init(); }; virtual void Shutdown() override { @@ -41,13 +44,14 @@ public: virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override { + IFileSystem *pFileSystem; IFileHandle *pHandle = NULL; - pHandle = filesystem_pak->Open(szFileName, eOpCode); - if (pHandle) return pHandle; - - pHandle = filesystem_backend->Open(szFileName, eOpCode); - if (pHandle) return pHandle; + for ( pFileSystem = g_pFileSystems; pFileSystem; pFileSystem = pFileSystem->m_pNext ) + { + pHandle = pFileSystem->Open(szFileName, eOpCode); + if (pHandle) return pHandle; + } return NULL; } @@ -71,11 +75,30 @@ public: { return pFile->Tell(); } + virtual size_t Size( IFileHandle *pFile ) override + { + return pFile->Size(); + } virtual void Close( IFileHandle *pFile ) override { } }; -CFileSystem g_fileSystem; -IFileSystem *filesystem = &g_fileSystem; + +static CFileSystem s_fileSystem; +IFileSystem *filesystem = &s_fileSystem; + +IFileSystem *g_pFileSystems; + +CFileSystemRegistry::CFileSystemRegistry( InstantiateFileSystemFn fn, const char *szFileSystem ) +{ + IFileSystem *pFileSystem = fn(); + pFileSystem->RegisterFileSystem(); +} + +void IFileSystem::RegisterFileSystem() +{ + m_pNext = g_pFileSystems; + g_pFileSystems = this; +}; diff --git a/engine/filesystem_libc.cpp b/tier2/filesystem_libc.cpp similarity index 76% rename from engine/filesystem_libc.cpp rename to tier2/filesystem_libc.cpp index 1718620..821d7a8 100644 --- a/engine/filesystem_libc.cpp +++ b/tier2/filesystem_libc.cpp @@ -1,4 +1,4 @@ -#include "ifilesystem.h" +#include "tier2/ifilesystem.h" #include "tier1/interface.h" #include "tier0/lib.h" @@ -6,14 +6,16 @@ class CLIBCFileHandle : public IFileHandle { public: FILE *m_pFile; - + size_t m_nSize; }; class CLIBCFileSystem : public IFileSystem { public: - virtual void Init() override {}; + virtual void Init() override { + + }; virtual void Shutdown() override {}; virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override @@ -25,7 +27,7 @@ public: switch (eOpCode) { case FILEMODE_READ: - szOperation = "r"; + szOperation = "rb"; break; default: V_printf("Operation is not supported\n"); @@ -39,6 +41,9 @@ public: pHandle = new CLIBCFileHandle; pHandle->m_pFileSystem = this; pHandle->m_pFile = pFile; + pHandle->Seek(SEEKMODE_RELATIVE_START, 0); + pHandle->m_nSize = pHandle->Tell(); + pHandle->Seek(SEEKMODE_RELATIVE_END, 0); return pHandle; } virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override @@ -57,20 +62,23 @@ public: { CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile; int eLibcSeekMode = 0; + + if (!pHandle) + return 0; + switch (eSeekMode) { - case SEEKMODE_SET: - eLibcSeekMode = SEEK_SET; + case SEEKMODE_RELATIVE_CURRENT: + eLibcSeekMode = SEEK_CUR; break; case SEEKMODE_RELATIVE_END: eLibcSeekMode = SEEK_END; break; case SEEKMODE_RELATIVE_START: - eLibcSeekMode = SEEK_CUR; + eLibcSeekMode = SEEK_SET; break; } - if (!pHandle) - return 0; - return V_fseek( pHandle->m_pFile, eLibcSeekMode, nOffset ); + + return V_fseek( pHandle->m_pFile, nOffset, eLibcSeekMode ); } virtual size_t Tell( IFileHandle *pFile ) override @@ -80,6 +88,16 @@ public: return 0; return V_ftell(pHandle->m_pFile); } + + virtual size_t Size( IFileHandle *pFile ) override + { + CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile; + if (!pHandle) + return 0; + return pHandle->m_nSize; + } + + virtual void Close( IFileHandle *pFile ) override { @@ -91,5 +109,4 @@ public: } }; -CLIBCFileSystem g_libcFileSystem; -IFileSystem *filesystem_backend = &g_libcFileSystem; +EXPOSE_FILESYSTEM(CLIBCFileSystem, "sysfs");