commit 7f054e2904adf959e3bc0f0858bff3b8e915a4b4 Author: kotofyt Date: Sun May 25 23:37:40 2025 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd58497 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build +.god +.git +.cache +compile_commands.json diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b8e4e86 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "external/cglm"] + path = external/cglm + url = https://github.com/recp/cglm.git +[submodule "external/Vulkan-Headers"] + path = external/Vulkan-Headers + url = https://github.com/KhronosGroup/Vulkan-Headers +[submodule "external/VulkanMemoryAllocator"] + path = external/VulkanMemoryAllocator + url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git +[submodule "external/stb"] + path = external/stb + url = https://github.com/nothings/stb.git diff --git a/build.c b/build.c new file mode 100644 index 0000000..4bd622a --- /dev/null +++ b/build.c @@ -0,0 +1,47 @@ +#include "god/build.h" +#include "god/utils.h" + +#define GAME_NAME "funnygame" + +char* include_dirs[] = { + "public", + "external/cglm/include", + "external/Vulkan-Headers/include", + "external/VulkanMemoryAllocator/include", + "external/stb", + NULL, +}; + +#include "tier0/__build.c" +#include "tier1/__build.c" +#include "fgui/__build.c" +#include "launcher/__build.c" +#include "engine/__build.c" +#include "game/__build.c" +#include "funnyassets/__build.c" + +int build(struct build_data b) { + if (!step("trace")) + trace = 1; + + makedir("build/"GAME_NAME"/game/" GAME_NAME); + makedir("build/"GAME_NAME"/game/" GAME_NAME "/bin"); + makedir("build/"GAME_NAME"/game/bin/"); + tier0_build(b); + tier1_build(b); + fgui_build(b); + engine_build(b); + launcher_build(b); + + server_build(b); + + assets_build(b); + mv("build", "tools"); + + if (step("run")!=STEP_FAILED) + { + struct run_project rp = run_new("build/"GAME_NAME"/game/bin/"GAME_NAME); + run_run(&rp); + } + return 0; +}; diff --git a/engine/__build.c b/engine/__build.c new file mode 100644 index 0000000..da3b813 --- /dev/null +++ b/engine/__build.c @@ -0,0 +1,63 @@ +#include "god/c.h" +#include "god/ld.h" +#include "god/utils.h" + +void engine_build(struct build_data b) +{ + char* files[] = { + "engine/console.cpp", + "engine/filesystem.cpp", + "engine/server.cpp", + "engine/engine.cpp", + + /* rendering */ + "engine/vk_videolinux.cpp", + "engine/vk_video.cpp", + "engine/vk_brush.cpp", + + /* entities */ + + "engine/baseentity.cpp", + "engine/level.cpp", + "engine/brush.cpp", + + /* server */ + "engine/sv_worldspawn.cpp", + "engine/sv_light.cpp", + + /* client */ + "engine/cl_worldspawn.cpp", + "engine/cl_light.cpp", + NULL, + }; + char *rustFiles[] = { + "engine/rust/physics.rs" + }; + + + struct project p = { + .b = &b, + .files = files, + .name = "engine", + }; + + struct project o = C_compile(p, (struct C_settings){ + .generation_flags = C_GENERATION_FLAGS_PIC, + .compile_flags = C_COMPILE_FLAGS_WALL, + .include_dirs = include_dirs, + }); + add_item(&o.files, tier1_lib); + + char* libs[] = { + "c", + "vulkan", + "X11", + NULL, + }; + + char* dll = ld_link_project(o, (struct link_settings){ + .type = LINK_TYPE_DYNAMIC, + .libs = libs, + }); + mv("build/"GAME_NAME"/game/bin",dll); +} diff --git a/engine/baseentity.cpp b/engine/baseentity.cpp new file mode 100644 index 0000000..4fe2a78 --- /dev/null +++ b/engine/baseentity.cpp @@ -0,0 +1,22 @@ +#include "baseentity.h" + +CUtlSelfReferencingVector g_entities; +CUtlVector g_RegisteredEntities; + +CEntityRegistry::CEntityRegistry(const char *szName, const char *szClass, EntityRegistryFn pfn) : + m_szName(szName), m_szClass(szClass), m_pfn(pfn), m_pClientfn(0) +{ + g_RegisteredEntities.AppendTail(this); +}; + + +C_EntityRegistry::C_EntityRegistry( const char *szName, ClientEntityRegistryFn pfn ) +{ + for (auto &entity: g_RegisteredEntities) + { + if (!V_strcmp(entity->m_szClass, szName)) + { + entity->m_pClientfn = pfn; + } + } +} diff --git a/engine/brush.cpp b/engine/brush.cpp new file mode 100644 index 0000000..989f410 --- /dev/null +++ b/engine/brush.cpp @@ -0,0 +1,84 @@ +#include "brush.h" +#include "rendering.h" +#include "tier0/platform.h" +#include "tier1/utlvector.h" + +void CBrushEntity::Precache() +{ + +} + +void CBrushEntity::Spawn() +{ + +}; + +void CBrushEntity::Destroy() +{ + +} +void CBrushEntity::Think( float fDelta ) +{ + +}; + + +void C_BrushEntity::Precache() +{ + CBrushEntity* pBrushEntity = dynamic_cast(pEntity); + if (!pBrushEntity) + Plat_FatalErrorFunc("pEntity is not a CBrushEntity"); +} + +void C_BrushEntity::Spawn() +{ + struct Vertex_t + { + float position[3]; + float uv[2]; + }; + + pAlbedo = ITextureManager::LoadTexture("gfx/bricks.png"); + CBrushEntity* pBrushEntity = (CBrushEntity*)pEntity; + uint32_t numVertices = 15*pBrushEntity->m_mesh.GetSize(); + vertexBuffer = IBrushRenderer::CreateVertexBuffer(numVertices*4); + Vertex_t *pTriangles = (Vertex_t*)vertexBuffer->Map(); + uint32_t i = 0; + for (auto &triangle: pBrushEntity->m_mesh) + { + pTriangles[i].position[0] = triangle.location[0]; + pTriangles[i].position[1] = triangle.location[1]; + pTriangles[i].position[2] = triangle.location[2]; + pTriangles[i].uv[0] = triangle.uv[0]; + pTriangles[i].uv[1] = triangle.uv[1]; + pTriangles[i+1].position[0] = triangle.location[3]; + pTriangles[i+1].position[1] = triangle.location[4]; + pTriangles[i+1].position[2] = triangle.location[5]; + pTriangles[i+1].uv[0] = triangle.uv[2]; + pTriangles[i+1].uv[1] = triangle.uv[3]; + pTriangles[i+2].position[0] = triangle.location[6]; + pTriangles[i+2].position[1] = triangle.location[7]; + pTriangles[i+2].position[2] = triangle.location[8]; + pTriangles[i+2].uv[0] = triangle.uv[4]; + pTriangles[i+2].uv[1] = triangle.uv[5]; + i+=3; + } + vertexBuffer->Unmap(); + + mesh = IBrushRenderer::CreateMesh(); + mesh->SetVertexBuffer(vertexBuffer); + +}; + +void C_BrushEntity::Destroy() +{ + +} +void C_BrushEntity::Think( float fDelta ) +{ + material.m.albedo = ITextureManager::GetTexture(pAlbedo); + IBrushRenderer::SetMaterial(&material); + mesh->Draw(); +}; + + diff --git a/engine/cl_light.cpp b/engine/cl_light.cpp new file mode 100644 index 0000000..b6dfc2d --- /dev/null +++ b/engine/cl_light.cpp @@ -0,0 +1,31 @@ +#include "baseentity.h" + + +class C_Light: public C_BaseEntity +{ +public: + virtual void Precache ( void ) override; + virtual void Spawn( void ) override; + virtual void Destroy( void ) override; + virtual void Think( float fDelta ) override; +}; + +void C_Light::Precache() +{ + +} + +void C_Light::Spawn() +{ +}; + +void C_Light::Destroy() +{ + +} +void C_Light::Think( float fDelta ) +{ + +}; + +LINK_CLIENT_ENTITY(C_Light, CLight) diff --git a/engine/cl_worldspawn.cpp b/engine/cl_worldspawn.cpp new file mode 100644 index 0000000..d3be7db --- /dev/null +++ b/engine/cl_worldspawn.cpp @@ -0,0 +1,33 @@ + +#include "brush.h" +#include "rendering.h" + +class C_WorldSpawn: public C_BrushEntity +{ +public: + virtual void Precache ( void ) override; + virtual void Spawn( void ) override; + virtual void Destroy( void ) override; + virtual void Think( float fDelta ) override; +}; + +void C_WorldSpawn::Precache() +{ + +} + +void C_WorldSpawn::Spawn() +{ + C_BrushEntity::Spawn(); +}; + +void C_WorldSpawn::Destroy() +{ + C_BrushEntity::Destroy(); +} +void C_WorldSpawn::Think( float fDelta ) +{ + C_BrushEntity::Think(fDelta); +}; + +LINK_CLIENT_ENTITY(C_WorldSpawn, CWorldSpawn) diff --git a/engine/console.cpp b/engine/console.cpp new file mode 100644 index 0000000..e0a465b --- /dev/null +++ b/engine/console.cpp @@ -0,0 +1,132 @@ +#include "console.h" +#include "tier1/utlvector.h" + +void IConsole::RegisterVar( ConVar *cvar ) +{ + +} +void IConsole::UnRegisterVar( ConVar *cvar ) +{ + +} +ConVar *IConsole::FindVar( const char *pName ) +{ + +} + +void IConsole::RegisterCommand( ConVar *cvar ) +{ + +} +void IConsole::UnRegisterCommand( ConVar *cvar ) +{ + +} +ConCommand *IConsole::FindCommand( const char *pName ) +{ + +} + +void IConsole::Execute( void ) +{ + +} + +void IConsole::AddCommand( const char *psz ) +{ + +} + +void IConsole::InsertCommand( const char *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 = CUtlString(pName); + m_flags = flags; + m_szValue = pDefaultValue; + m_fValue = V_atof(pDefaultValue); + m_nValue = V_atoi(pDefaultValue); + IConsole::RegisterVar(this); +} + +bool ConVar::IsFlagSet( int flag ) +{ + +} +const char *ConVar::GetHelpText( void ) +{ + +} +bool ConVar::IsRegistered( void ) +{ + +} +const char *ConVar::GetName( void ) +{ + +} +void ConVar::AddFlags( int flags ) +{ + +} +bool ConVar::IsCommand( void ) +{ + +} + +void ConVar::InstallChangeCallback( ConCommandFn ) +{ + +} + +float ConVar::GetFloat( void ) +{ + +} +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); +} \ No newline at end of file diff --git a/engine/engine.cpp b/engine/engine.cpp new file mode 100644 index 0000000..b176098 --- /dev/null +++ b/engine/engine.cpp @@ -0,0 +1,117 @@ +#include "tier1/commandline.h" +#include "tier1/utlstring.h" +#include "tier0/lib.h" +#include "console.h" +#include "filesystem.h" +#include "rendering.h" +#include "engine.h" +#include "baseentity.h" +#include "server.h" + +#ifdef __linux +#include "signal.h" +#endif + +double fPrev = 0; +double fCurrent = 0; +//----------------------------------------------------------------------------- +// Purpose: Engine entry point +//----------------------------------------------------------------------------- +extern "C" void FunnyMain( int argc, char **argv ) { + + ICommandLine::CreateCommandLine(argc, argv); + IEngine::Init(); + for (;;) + { + fPrev = fCurrent; + fCurrent = Plat_GetTime(); + IEngine::Frame(fCurrent-fPrev); + }; + /* deinit is handled explicitly */ +}; + +void IEngine_Signal(int sig) +{ + printf("Trapped signal %i\n",sig); + switch (sig) + { + case SIGSEGV: + case SIGILL: + case SIGABRT: + printf("Consider running app with debugger attached\n"); + Plat_Backtrace(); + break; + default: + break; + }; + IEngine::Shutdown(); + _exit(0); +}; + +void IEngine::Init() +{ + /* trap signals */ + #ifdef __linux + signal(SIGHUP, IEngine_Signal); + signal(SIGINT, IEngine_Signal); + signal(SIGQUIT, IEngine_Signal); + signal(SIGILL, IEngine_Signal); + signal(SIGTRAP, IEngine_Signal); + signal(SIGIOT, IEngine_Signal); + signal(SIGBUS, IEngine_Signal); + signal(SIGFPE, IEngine_Signal); + signal(SIGSEGV, IEngine_Signal); + signal(SIGTERM, IEngine_Signal); + #endif + + IFileSystem::InitFilesystem(); + IVideo::Init(); + IServer::LoadGame("funnygame"); +}; + +void IEngine::Frame(float fDelta) +{ + IServer::Think(fDelta); + IVideo::Frame(fDelta); +}; + +void IEngine::Shutdown() +{ + +}; +void IIEngine::PrecacheModel( const char *psz ) +{ + +} +void IIEngine::PrecacheSound( const char *psz ) +{ + +} + + +CBaseEntity *IIEngine::SpawnEntity( const char *szName ) +{ + V_printf("%s\n", szName); + for (auto &entity: g_RegisteredEntities) + { + if (!V_strcmp(entity->m_szName, szName)) + { + CBaseEntity *pEnt = entity->m_pfn(); + pEnt->Spawn(); + g_entities.AppendTail(pEnt); + if (entity->m_pClientfn) + { + pEnt->pClientEntity = entity->m_pClientfn(); + pEnt->pClientEntity->Spawn(); + pEnt->pClientEntity->pEntity = pEnt; + } + return pEnt; + } + } + return 0; +}; + +void IIEngine::DestroyEntity( CBaseEntity *pEntity ) +{ + +}; diff --git a/engine/filesystem.cpp b/engine/filesystem.cpp new file mode 100644 index 0000000..fa7feed --- /dev/null +++ b/engine/filesystem.cpp @@ -0,0 +1,210 @@ +#include "tier0/platform.h" +#include "tier1/commandline.h" +#include "filesystem.h" +#include "unistd.h" +#include + +#define BASEDIR "rtt" +#define GAMEDIR "funnygame" + + +struct PackHeader_t +{ + char id[8]; + unsigned long long offset; + unsigned long long size; +}; +struct PackDirectory_t +{ + char name[56]; + unsigned long long offset; + unsigned long long size; +}; +struct Pack_t +{ + FILE* handle; + PackHeader_t header; + CUtlVector files; +}; +struct FileDirectory_t +{ + CUtlString path; + Pack_t pack; +}; + + +CUtlString fs_basedir; +CUtlString fs_gamedir; +CUtlSelfReferencingVector fs_directories; + +class CFileSystem: public IFileSystem +{ +public: + static void AddDirectory( const char *psz ); + static void AddFile( const char *psz ); +}; + +void IFileSystem::InitFilesystem() +{ + fs_basedir = ICommandLine::ParamValue("-basedir"); + if ( fs_basedir == 0 ) + fs_basedir=BASEDIR; + if ( fs_basedir.GetString()[0] == '-' ) + fs_basedir=BASEDIR; + fs_gamedir = ICommandLine::ParamValue("-gamedir"); + if ( fs_gamedir == 0 ) + fs_gamedir=GAMEDIR; + if ( fs_gamedir.GetString()[0] == '-' ) + fs_gamedir=GAMEDIR; + + AddGameDirectory(fs_gamedir); +} +void CFileSystem::AddFile( const char *psz ) +{ + CUtlString extension = Plat_GetExtension(psz); + if (extension=="pak") + { + IFileSystem::LoadPackFile(psz); + }; +} + +void IFileSystem::AddGameDirectory( const char *psz ) +{ + FileDirectory_t dir = {}; + dir.path = psz; + fs_directories.AppendTail(dir); + + Plat_ListDirRecursive(psz, CFileSystem::AddFile, 0); + for (auto &dir: fs_directories) + { + V_printf("%s\n",(char*)dir.path); + }; + +}; +bool IFileSystem::LoadPackFile( const char *szFilename ) +{ + Pack_t pack = {}; + PackHeader_t header = {}; + unsigned long long nNumFiles = 0; + PackDirectory_t *pDirs = NULL; + + FILE* f = V_fopen(szFilename, "r"); + if (!f) + Plat_FatalErrorFunc("Failed to open %s",szFilename); + V_fread(&header,1,sizeof(header),f); + // check for rttpacku + if ( + header.id[0]!='r' || header.id[1] != 't' || header.id[2] != 't' || header.id[3]!='p' || + header.id[4]!='a' || header.id[5] != 'c' || header.id[6] != 'k' || header.id[7]!='u' + ) + { + Plat_FatalErrorFunc("%s is not a pack file",szFilename); + } + nNumFiles = header.size/sizeof(PackDirectory_t); + + pDirs = (PackDirectory_t*)V_malloc(header.size); + V_fseek(f, header.offset, SEEK_SET); + V_fread(pDirs, sizeof(PackDirectory_t), nNumFiles, f); + pack.header = header; + pack.handle = f; + pack.files = CUtlVector(nNumFiles); + V_memcpy(pack.files.GetData(),pDirs, header.size); + for (auto &i: pack.files) + { + V_printf(" LOADED %s\n",i.name); + } + V_free(pDirs); + + nNumFiles = header.size/sizeof(PackDirectory_t); + + FileDirectory_t fd = {}; + fd.path = szFilename; + fd.pack = pack; + fs_directories.AppendTail(fd); + + return true; +} +void IFileSystem::CreatePath( const char *szPath ) +{ + +} +FileHandle_t IFileSystem::Open( const char *szFilename, EFileOptions options ) +{ + if (options == IFILE_READ) + { + FILE *file = V_fopen(szFilename, "rb"); + + /* found in fs */ + if ( file != NULL ) + { + FileHandle_t filehandle = new FileHandle_s; + filehandle->file = file; + filehandle->nPtr = 0; + filehandle->options = IFILE_READ; + + /* get size */ + V_fseek(file, 0, SEEK_END); + filehandle->nSize = V_ftell(file); + V_fseek(file, 0, SEEK_SET); + + return filehandle; + } + + /* not found in fs, try to search in packs */ + for ( auto &pak: fs_directories ) + { + for ( auto &file: pak.pack.files ) + { + if ( !strncmp(file.name, szFilename, 56) ) + { + FileHandle_t filehandle = new FileHandle_s; + filehandle->file = 0; + filehandle->parent = pak.pack.handle; + filehandle->nSize = file.size; + filehandle->nOffset = file.offset; + filehandle->nPtr = 0; + filehandle->options = IFILE_READ; + return filehandle; + } + } + }; + } + return 0; +} + +void IFileSystem::Close( FileHandle_t file ) +{ + /* close only fs files */ + if (file->file) + { + V_fclose(file->file); + } + delete file; + +} +size_t IFileSystem::Size( FileHandle_t file ) +{ + return file->nSize; +} +size_t IFileSystem::Read( FileHandle_t file, void *pOutput, size_t nSize) +{ + if (file->file) + { + size_t readsize = V_fread(pOutput, 1, nSize, file->file); + file->nPtr+=readsize; + return readsize; + } + + size_t readsize = V_fseek(file->parent, file->nOffset, file->nPtr); + V_fread(pOutput, 1, nSize, file->parent); + + return readsize; +} +size_t IFileSystem::ReadLine( FileHandle_t file, void *pOutput, size_t nSize) +{ + +} +size_t IFileSystem::Write( FileHandle_t file, void *pInput, size_t nSize) +{ + +} diff --git a/engine/level.cpp b/engine/level.cpp new file mode 100644 index 0000000..2948007 --- /dev/null +++ b/engine/level.cpp @@ -0,0 +1,90 @@ +#include "level.h" +#include "baseentity.h" +#include "brush.h" +#include "engine.h" +#include "filesystem.h" +#include "tier1/utlbuffer.h" +#include "tier1/utlstring.h" + +struct MapHeader_t +{ + char id[8]; + uint32_t nEntities; +}; + +struct EntityHeader_t +{ + uint32_t nTriangles; + uint32_t nProperties; +}; + +void ILevel::LoadLevel( const char *szLevelName ) +{ + FileHandle_t handle = IFileSystem::Open(CUtlString("%s.fmap",szLevelName), IFILE_READ); + CUtlBuffer mapdata(IFileSystem::Size(handle)); + IFileSystem::Read(handle, mapdata.GetMemory(), mapdata.GetSize()); + IFileSystem::Close(handle); + MapHeader_t* pHeader = (MapHeader_t*)mapdata.GetMemory(); + char *pData = (char*)mapdata.GetMemory()+sizeof(MapHeader_t); + for ( uint32_t i = 0; i < pHeader->nEntities; i++ ) + { + + CUtlBuffer szEntityType(V_strlen(pData)+1); + V_strcpy(szEntityType, pData); + pData+=szEntityType.GetSize(); + EntityHeader_t* pEntityHeader = (EntityHeader_t*)pData; + pData+=sizeof(EntityHeader_t); + + CBaseEntity *pEntity = NULL; + for (auto &entity: g_RegisteredEntities) + { + if (!V_strcmp(entity->m_szName, (char*)szEntityType.GetMemory())) + { + CBaseEntity *pEnt = entity->m_pfn(); + g_entities.AppendTail(pEnt); + if (entity->m_pClientfn) + { + pEnt->pClientEntity = entity->m_pClientfn(); + pEnt->pClientEntity->pEntity = pEnt; + } + pEntity = pEnt; + break; + } + } + for ( uint32_t j = 0; jnProperties; j++ ) + { + CUtlBuffer szParamName(V_strlen(pData)+1); + V_strcpy(szParamName, pData); + pData+=szParamName.GetSize(); + CUtlBuffer szParamValue(V_strlen(pData)+1); + V_strcpy(szParamValue, pData); + pData+=szParamValue.GetSize(); + }; + + CBrushEntity *pBrush = dynamic_cast(pEntity); + if (!pBrush) + { + pEntity->Spawn(); + if (pEntity->pClientEntity) + pEntity->pClientEntity->Spawn(); + continue; + } + pBrush->m_mesh = CUtlVector(0); + V_printf("%i\n",pBrush->m_mesh.GetSize()); + for ( uint32_t j = 0; jnTriangles; j++ ) + { + Triangle_t triangle = {}; + V_memcpy(triangle.location, pData, 4*9); + pData+=4*9; + V_memcpy(triangle.uv, pData, 4*6); + pData+=4*6; + CUtlBuffer szTextureName(V_strlen(pData)+1); + V_strcpy(szTextureName, pData); + pData+=szTextureName.GetSize(); + pBrush->m_mesh.AppendTail(triangle); + }; + pBrush->Spawn(); + if (pBrush->pClientEntity) + pBrush->pClientEntity->Spawn(); + }; +}; diff --git a/engine/server.cpp b/engine/server.cpp new file mode 100644 index 0000000..d8c638f --- /dev/null +++ b/engine/server.cpp @@ -0,0 +1,38 @@ +#include "server.h" +#include "tier1/utlstring.h" +#include "baseentity.h" +#include "console.h" + +void *g_serverdll; + +void IServer::LoadGame( const char *psz ) +{ + g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.so", psz)); + void (*GameLoadfn)() = (void(*)())Plat_GetProc(g_serverdll, "IGame_Load"); + if (!GameLoadfn) + Plat_FatalErrorFunc("IGame_Load not found in libserver.so\n"); + GameLoadfn(); +}; + +ConVar g_tickrate("tickrate","64",FCVAR_PROTECTED); +float g_fAccumulator = 0; + +void IServer::Think( float fDelta ) +{ + g_fAccumulator += fDelta; + float fTickrate = 1.0/g_tickrate.GetInt(); + /* tickrate */ + while(g_fAccumulator>=fTickrate) + { + for (auto &entity: g_entities) + { + entity->Think(fTickrate); + g_fAccumulator-=fTickrate; + } + } + for (auto &entity: g_entities) + { + if (entity->pClientEntity) + entity->pClientEntity->Think(fDelta); + } +}; diff --git a/engine/sv_light.cpp b/engine/sv_light.cpp new file mode 100644 index 0000000..4975853 --- /dev/null +++ b/engine/sv_light.cpp @@ -0,0 +1,31 @@ +#include "baseentity.h" + +class CLight: public CBaseEntity +{ +public: + virtual void Precache ( void ) override; + virtual void Spawn( void ) override; + virtual void Destroy( void ) override; + virtual void Think( float fDelta ) override; +}; + +void CLight::Precache() +{ + +} + +void CLight::Spawn() +{ + +}; + +void CLight::Destroy() +{ + +} +void CLight::Think( float fDelta ) +{ + +}; + +DECLARE_ENTITY(light, CLight) diff --git a/engine/sv_worldspawn.cpp b/engine/sv_worldspawn.cpp new file mode 100644 index 0000000..f5857d4 --- /dev/null +++ b/engine/sv_worldspawn.cpp @@ -0,0 +1,32 @@ + +#include "brush.h" + +class CWorldSpawn: public CBrushEntity +{ +public: + virtual void Precache ( void ) override; + virtual void Spawn( void ) override; + virtual void Destroy( void ) override; + virtual void Think( float fDelta ) override; +}; + +void CWorldSpawn::Precache() +{ + +} + +void CWorldSpawn::Spawn() +{ + +}; + +void CWorldSpawn::Destroy() +{ + +} +void CWorldSpawn::Think( float fDelta ) +{ + +}; + +DECLARE_ENTITY(worldspawn, CWorldSpawn) diff --git a/engine/vk_brush.cpp b/engine/vk_brush.cpp new file mode 100644 index 0000000..6f13307 --- /dev/null +++ b/engine/vk_brush.cpp @@ -0,0 +1,406 @@ +#include "filesystem.h" +#include "rendering.h" +#include "tier1/utlvector.h" +#include "vk_helper.h" +#include "vulkan/vulkan_core.h" + +extern VkSampler g_invalidTextureSampler; +abstract_class CBrush: public IBrush +{ +public: + void SetPosition( vec3 position ) override; + void SetRotationEuler( vec3 angle ) override; + void SetRotationQuat( vec4 quaternion) override; + void SetMatrix( mat3 matrix ) override; + void SetScale( vec3 scale ) override; + + void SetVertexBuffer( IVertexBuffer *pBuffer ) override; + void SetIndexBuffer( IIndexBuffer *pBuffer ) override; + void Draw() override; + + IMaterial *m_pMaterial = NULL; + CVertexBuffer *m_pVertexBuffer = NULL; + CIndexBuffer *m_pIndexBuffer = NULL; +}; +void CBrush::SetPosition( vec3 position ) +{ + +} + +void CBrush::SetRotationEuler( vec3 angle ) +{ + +} + +void CBrush::SetRotationQuat( vec4 quaternion) +{ + +} + +void CBrush::SetMatrix( mat3 matrix ) +{ + +} + +void CBrush::SetScale( vec3 scale ) +{ + +} + + +void CBrush::SetVertexBuffer( IVertexBuffer *pBuffer ) +{ + m_pVertexBuffer = (CVertexBuffer*)pBuffer; +} + +void CBrush::SetIndexBuffer( IIndexBuffer *pBuffer ) +{ + m_pIndexBuffer = (CIndexBuffer*)pBuffer; +} + +CUtlVector g_drawnMeshes; +IMaterial *g_pDefaultMaterial; +IMaterial *g_pCurrentMaterial; + +void CBrush::Draw() +{ + g_drawnMeshes.AppendTail(*this); +} + +abstract_class CMaterial: public IMaterial +{ +}; + +extern CUtlVector g_textures; + +vk_tripipeline_t g_brushPipeline = {}; +vk_image2d_t meshdepth; +vk_image2d_t meshcolor; +extern bool g_bConfigNotify; + +VkDescriptorPool g_brushDescriptorPool; +VkDescriptorSet g_brushDescriptorSet; +vk_buffer_t g_brushProjection; +struct MeshProjection { + mat4 projection; +} *g_brushProject; + +VkSampler g_brushSampler; + +void IBrushRenderer::Init() +{ + CUtlVector shaders(2); + for (auto &shader: shaders) + { + shader.m_shaderModule = NULL; + } + shaders[0].Create("gfx/brush_vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaders[1].Create("gfx/brush_frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + CUtlVector bindings(2); + bindings[0] = {}; + bindings[0].binding = 0; + bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + bindings[0].descriptorCount = 1; + bindings[1] = {}; + bindings[1].binding = 1; + bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[1].descriptorCount = 1024; + g_brushPipeline.Create(shaders, bindings, 4); + shaders[1].Destroy(); + shaders[0].Destroy(); + + meshdepth.Create(1280, 720, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + meshcolor.Create(1280, 720, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + + CUtlVector pools; + for (auto &binding: bindings) + { + VkDescriptorPoolSize dps = {}; + dps.type = binding.descriptorType; + dps.descriptorCount = binding.descriptorCount; + pools.AppendTail(dps); + } + + VkDescriptorPoolCreateInfo poolInfo = {}; + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.poolSizeCount = pools.GetSize(); + poolInfo.pPoolSizes = pools.GetData(); + poolInfo.maxSets = 1; + vkCreateDescriptorPool(g_vkDevice, &poolInfo, NULL, &g_brushDescriptorPool); + + VkDescriptorSetAllocateInfo allocInfo = {}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = g_brushDescriptorPool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &g_brushPipeline.m_descriptorSetLayout; + vkAllocateDescriptorSets(g_vkDevice, &allocInfo, &g_brushDescriptorSet); + + g_brushProjection.Create(64, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + g_brushProject = (MeshProjection*)g_brushProjection.Map(0, 64); + + VkPhysicalDeviceProperties properties{}; + vkGetPhysicalDeviceProperties(g_vkPhysicalDevice, &properties); + VkSamplerCreateInfo samplerInfo{}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 0.0f; + vkCreateSampler(g_vkDevice, &samplerInfo, nullptr, &g_brushSampler); +} + +void IBrushRenderer::Frame( float fDelta ) +{ + glm_mat4_identity(g_brushProject->projection); + glm_perspective(glm_rad(90),(float)g_nWindowWidth/g_nWindowHeight, 0.01, 100, g_brushProject->projection); + glm_rotate(g_brushProject->projection, glm_rad(90), (vec4){1,0,0,0}); + glm_scale(g_brushProject->projection, (vec4){1,-1,1,1}); + if (g_bConfigNotify) + { + meshdepth.Destroy(); + meshdepth.Create(g_nWindowWidth, g_nWindowHeight, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + } + + + CUtlVector writes(2); + for (auto &write: writes) + { + write = {}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = g_brushDescriptorSet; + write.dstArrayElement = 0; + } + + VkDescriptorBufferInfo bufferInfo = {}; + bufferInfo.buffer = g_brushProjection.m_buffer; + bufferInfo.offset = 0; + bufferInfo.range = g_brushProjection.m_nSize; + writes[0].dstBinding = 0; + writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + writes[0].descriptorCount = 1; + writes[0].pBufferInfo = &bufferInfo; + + CUtlVector textures; + textures.Reserve(g_textures.GetSize()); + for (ITexture *t: g_textures) + { + CTexture *texture = (CTexture*)t; + VkDescriptorImageInfo image = {}; + image.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image.imageView = texture->image.m_imageView; + image.sampler = g_brushSampler; + textures.AppendTail(image); + }; + textures[0].sampler = g_invalidTextureSampler; + writes[1].dstBinding = 1; + writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[1].descriptorCount = textures.GetSize(); + writes[1].pImageInfo = textures.GetData(); + vkUpdateDescriptorSets(g_vkDevice, writes.GetSize(), writes.GetData(), 0, NULL); + + + VkImageMemoryBarrier barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .image = g_swapchainImage, + .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} + }; + vkCmdPipelineBarrier(g_vkCommandBuffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, 0, NULL, 0, NULL, 1, &barrier); + + VkRenderingAttachmentInfo colorAttachment = { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .imageView = g_swapchainImageView, + .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = {.color = {0.0f, 0.0f, 0.0f, 1.0f}} + }; + VkRenderingAttachmentInfo depthAttachment = { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .imageView = meshdepth.m_imageView, + .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = {.depthStencil = {.depth = 1}}, + }; + + VkRenderingInfo renderInfo = { + .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, + .renderArea = {{0, 0}, {g_nWindowWidth, g_nWindowHeight}}, + .layerCount = 1, + .colorAttachmentCount = 1, + .pColorAttachments = &colorAttachment, + .pDepthAttachment = &depthAttachment, + }; + vkCmdBeginRendering(g_vkCommandBuffer, &renderInfo); + + vkCmdSetRasterizerDiscardEnable(g_vkCommandBuffer, VK_FALSE); + vkCmdSetDepthBiasEnable(g_vkCommandBuffer, VK_FALSE); + _vkCmdSetPolygonModeEXT(g_vkCommandBuffer, VK_POLYGON_MODE_FILL); + vkCmdSetCullMode(g_vkCommandBuffer, VK_CULL_MODE_BACK_BIT); + vkCmdSetFrontFace(g_vkCommandBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE); + + vkCmdSetDepthTestEnable(g_vkCommandBuffer, VK_TRUE); + vkCmdSetDepthWriteEnable(g_vkCommandBuffer, VK_TRUE); + vkCmdSetDepthCompareOp(g_vkCommandBuffer, VK_COMPARE_OP_LESS); + vkCmdSetStencilTestEnable(g_vkCommandBuffer, VK_FALSE); + + _vkCmdSetRasterizationSamplesEXT(g_vkCommandBuffer, VK_SAMPLE_COUNT_1_BIT); + VkSampleMask sampleMask = 0xFFFFFFFF; + _vkCmdSetSampleMaskEXT(g_vkCommandBuffer, VK_SAMPLE_COUNT_1_BIT, &sampleMask); + _vkCmdSetAlphaToCoverageEnableEXT(g_vkCommandBuffer, VK_FALSE); + + VkViewport viewport = {0, 0, (float)g_nWindowWidth, (float)g_nWindowHeight, 0.0f, 1.0f}; + VkRect2D scissor = {{0, 0}, {g_nWindowWidth, g_nWindowHeight}}; + vkCmdSetViewportWithCount(g_vkCommandBuffer, 1, &viewport); + vkCmdSetScissorWithCount(g_vkCommandBuffer, 1, &scissor); + + vkCmdSetPrimitiveTopology(g_vkCommandBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + vkCmdSetPrimitiveRestartEnable(g_vkCommandBuffer, VK_FALSE); + + VkVertexInputBindingDescription2EXT binding = { + .sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, + .binding = 0, + .stride = 20, + .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, + .divisor = 1, + }; + VkVertexInputAttributeDescription2EXT attributes[2] = { + { + VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, + NULL, + 0, 0, + VK_FORMAT_R32G32B32_SFLOAT, + 0 + }, + { + VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, + NULL, + 1, 0, + VK_FORMAT_R32G32_SFLOAT, + 12 + } + }; + _vkCmdSetVertexInputEXT(g_vkCommandBuffer, 1, &binding, 2, attributes); + + VkBool32 blendEnable = VK_FALSE; + VkColorBlendEquationEXT blendEquation = { + VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD, + VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD + }; + VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + _vkCmdSetColorBlendEnableEXT(g_vkCommandBuffer, 0, 1, &blendEnable); + _vkCmdSetColorBlendEquationEXT(g_vkCommandBuffer, 0, 1, &blendEquation); + _vkCmdSetColorWriteMaskEXT(g_vkCommandBuffer, 0, 1, &writeMask); + + vkCmdBindPipeline(g_vkCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_brushPipeline.m_pipeline); + vkCmdBindDescriptorSets(g_vkCommandBuffer,VK_PIPELINE_BIND_POINT_GRAPHICS, g_brushPipeline.m_layout, 0, 1, &g_brushDescriptorSet, 0, NULL); + for (auto &mesh: g_drawnMeshes) + { + VkDeviceSize offset = 0; + uint32_t textureID = 0; + if (g_pCurrentMaterial == 0) + textureID = 0; + else + textureID = ((CMaterial*)g_pCurrentMaterial)->m.albedo; + vkCmdPushConstants(g_vkCommandBuffer, g_brushPipeline.m_layout, VK_SHADER_STAGE_ALL, 0, 4, &textureID); + vkCmdBindVertexBuffers(g_vkCommandBuffer, 0, 1, &mesh.m_pVertexBuffer->m_buffer.m_buffer, &offset); + if (mesh.m_pIndexBuffer) + { + vkCmdBindIndexBuffer( + g_vkCommandBuffer, + mesh.m_pIndexBuffer->m_buffer.m_buffer, + 0, + VK_INDEX_TYPE_UINT32 + ); + vkCmdDrawIndexed(g_vkCommandBuffer, mesh.m_pIndexBuffer->m_buffer.m_nSize/4, 1, 0, 0, 0); + } + else + { + vkCmdDraw(g_vkCommandBuffer, mesh.m_pVertexBuffer->m_buffer.m_nSize/12,1,0,0); + } + } + vkCmdEndRendering(g_vkCommandBuffer); + + barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccessMask = 0, + .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .image = g_swapchainImage, + .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} + }; + + vkCmdPipelineBarrier(g_vkCommandBuffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, 0, NULL, 0, NULL, 1, &barrier); + g_drawnMeshes = CUtlVector(); +} + + +IVertexBuffer *IBrushRenderer::CreateVertexBuffer( uint32_t uSize ) +{ + CVertexBuffer *pBuffer = new CVertexBuffer(); + pBuffer->m_buffer.Create(uSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + return pBuffer; +} + +IIndexBuffer *IBrushRenderer::CreateIndexBuffer( uint32_t uSize ) +{ + CIndexBuffer *pBuffer = new CIndexBuffer(); + pBuffer->m_buffer.Create(uSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + return pBuffer; +} + +IBrush *IBrushRenderer::CreateMesh() +{ + CBrush *mesh = new CBrush; + return mesh; +} + +void IBrushRenderer::Destroy( IBrush *pModel ) +{ + +} + +IMaterial *IBrushRenderer::LoadMaterial( const char *szMaterial ) +{ + FileHandle_t file = IFileSystem::Open(szMaterial, IFILE_READ); + CMaterial *pMaterial = new CMaterial; + if (!file) + { + return g_pDefaultMaterial; + } + + IFileSystem::Close(file); +} + +void IBrushRenderer::SetMaterial( IMaterial *pMaterial ) +{ + g_pCurrentMaterial = pMaterial; +} + + diff --git a/engine/vk_external_functions.cpp b/engine/vk_external_functions.cpp new file mode 100644 index 0000000..2309d57 --- /dev/null +++ b/engine/vk_external_functions.cpp @@ -0,0 +1,9 @@ +VK_DEVICE_FUNCTION(vkCmdSetPolygonModeEXT); +VK_DEVICE_FUNCTION(vkCmdSetRasterizationSamplesEXT); +VK_DEVICE_FUNCTION(vkCmdSetVertexInputEXT); +VK_DEVICE_FUNCTION(vkCmdSetSampleMaskEXT); +VK_DEVICE_FUNCTION(vkCmdSetAlphaToCoverageEnableEXT); +VK_DEVICE_FUNCTION(vkCmdSetViewportWithCount); +VK_DEVICE_FUNCTION(vkCmdSetColorBlendEnableEXT); +VK_DEVICE_FUNCTION(vkCmdSetColorBlendEquationEXT); +VK_DEVICE_FUNCTION(vkCmdSetColorWriteMaskEXT); diff --git a/engine/vk_helper.h b/engine/vk_helper.h new file mode 100644 index 0000000..597a773 --- /dev/null +++ b/engine/vk_helper.h @@ -0,0 +1,72 @@ +#include "filesystem.h" +#include "rendering.h" +#include "tier0/platform.h" +#include "tier1/utlvector.h" +#include "console.h" +#include "tier1/commandline.h" + +#include "X11/X.h" +#include "X11/Xlib.h" +#include "vulkan/vulkan.h" +#include "vulkan/vulkan_core.h" +#include "vulkan/vulkan_xlib.h" + +#define VULKAN_RENDERING_IMPL +#include "vk_video.h" + +#define VK_DEVICE_FUNCTION(name) extern PFN_##name _##name +#include "vk_external_functions.cpp" +#undef VK_DEVICE_FUNCTION + +#include "cglm/affine.h" +#include "cglm/cglm.h" + +extern Display* g_xdisplay; +extern int g_xscreen; +extern Window g_xroot; +extern Window g_xwin; + +extern VkInstance g_vkInstance; +extern VkPhysicalDevice g_vkPhysicalDevice; +extern VkDevice g_vkDevice; +extern uint32_t g_drawfamily; +extern VkQueue g_drawQueue; +extern uint32_t g_presentfamily; +extern VkQueue g_presentQueue; +extern VmaAllocator g_allocator; + +extern VkSurfaceKHR g_surface; +extern VkSwapchainKHR g_swapchain; + +extern VkCommandPool g_vkCommandPool; +extern VkCommandBuffer g_vkCommandBuffer; +extern VkImageView g_swapchainImageView; +extern VkImage g_swapchainImage; + +extern uint32_t g_nWindowWidth; +extern uint32_t g_nWindowHeight; + +class CVertexBuffer: public IVertexBuffer +{ +public: + void *Map() override; + void Unmap() override; + vk_buffer_t m_buffer; + void *m_pAllocated = NULL; +}; + +class CIndexBuffer: public IIndexBuffer +{ +public: + void *Map() override; + void Unmap() override; + vk_buffer_t m_buffer; + void *m_pAllocated; +}; + + +class CTexture: public ITexture +{ +public: + vk_image2d_t image; +}; diff --git a/engine/vk_video.cpp b/engine/vk_video.cpp new file mode 100644 index 0000000..77ea595 --- /dev/null +++ b/engine/vk_video.cpp @@ -0,0 +1,474 @@ +#include "filesystem.h" +#include "rendering.h" +#include "tier0/lib.h" +#include "tier1/utlvector.h" +#include "vk_helper.h" +#include "tier0/platform.h" +#include "vulkan/vulkan_core.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +VkSampler g_invalidTextureSampler; + +void IVulkan::Init() +{ + char invalidTexture[1024] = {}; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + int index = i * 16 + j; + if ((i + j) % 2 == 0) { + invalidTexture[index*4] = 255; + } + } + } + ITextureManager::LoadTexture(invalidTexture, 16, 16, 4); + VkPhysicalDeviceProperties properties{}; + vkGetPhysicalDeviceProperties(g_vkPhysicalDevice, &properties); + VkSamplerCreateInfo samplerInfo{}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_NEAREST; + samplerInfo.minFilter = VK_FILTER_NEAREST; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 0.0f; + vkCreateSampler(g_vkDevice, &samplerInfo, nullptr, &g_invalidTextureSampler); + IBrushRenderer::Init(); + +}; + +void IVulkan::Frame() +{ + IBrushRenderer::Frame(0); +}; + +void vk_shader_t::Create( const char *szPath, VkShaderStageFlagBits shaderStage ) +{ + FileHandle_t shader = IFileSystem::Open(szPath, IFILE_READ); + if (!shader) + Plat_FatalErrorFunc("Failed to open shader %s\n", szPath); + CUtlBuffer buffer(IFileSystem::Size(shader)); + IFileSystem::Read(shader, buffer.GetMemory(), buffer.GetSize()); + Create(buffer, shaderStage); + IFileSystem::Close(shader); +} + +void vk_shader_t::Create( CUtlBuffer &spirv, VkShaderStageFlagBits shaderStage ) +{ + if (m_shaderModule != NULL) + Plat_FatalErrorFunc("Shader already exists"); + VkShaderModuleCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = spirv.GetSize(); + createInfo.pCode = (uint32_t*)spirv.GetMemory(); + vkCreateShaderModule(g_vkDevice, &createInfo, NULL, &m_shaderModule); + m_stageCreateInfo = {}; + m_stageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + m_stageCreateInfo.module = m_shaderModule; + m_stageCreateInfo.stage = shaderStage; + m_stageCreateInfo.pName = "main"; +} + +void vk_shader_t::Destroy( void ) +{ + if (m_shaderModule == NULL) + Plat_FatalErrorFunc("Shader doesn't exist"); + vkDestroyShaderModule(g_vkDevice, m_shaderModule, NULL); +} + + +void vk_tripipeline_t::Create( + CUtlVector &shaders, + CUtlVector &bindings, + uint32_t pushConstantSize + ) +{ + VkPushConstantRange pushConstantRange = {}; + pushConstantRange.stageFlags = VK_SHADER_STAGE_ALL; + pushConstantRange.offset = 0; + pushConstantRange.size = pushConstantSize; + + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {}; + descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptorSetLayoutCreateInfo.bindingCount = bindings.GetSize(); + descriptorSetLayoutCreateInfo.pBindings = bindings.GetData(); + vkCreateDescriptorSetLayout(g_vkDevice, &descriptorSetLayoutCreateInfo, NULL, &m_descriptorSetLayout); + + + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; + pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutCreateInfo.setLayoutCount = 1; + pipelineLayoutCreateInfo.pSetLayouts = &m_descriptorSetLayout; + if (pushConstantSize != 0) + { + pipelineLayoutCreateInfo.pushConstantRangeCount = 1; + pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; + } + vkCreatePipelineLayout(g_vkDevice, &pipelineLayoutCreateInfo, NULL, &m_layout); + + VkDynamicState dynamicStates[] = { + /* pVertexInputState */ + VK_DYNAMIC_STATE_VERTEX_INPUT_EXT, + /* pInputAssemblyState */ + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, + /* pTessellationState */ + VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT, + /* pViewportState */ + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, + /* pRasterizationState */ + VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, + VK_DYNAMIC_STATE_POLYGON_MODE_EXT, + VK_DYNAMIC_STATE_CULL_MODE, + VK_DYNAMIC_STATE_FRONT_FACE, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, + VK_DYNAMIC_STATE_DEPTH_BIAS, + VK_DYNAMIC_STATE_LINE_WIDTH, + /* pMultisampleState */ + VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT, + VK_DYNAMIC_STATE_SAMPLE_MASK_EXT, + VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT, + /* pDepthStencilState */ + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_OP, + VK_DYNAMIC_STATE_DEPTH_BOUNDS, + /* pColorBlendState */ + VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT, + VK_DYNAMIC_STATE_LOGIC_OP_EXT, + VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, + VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, + VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, + VK_DYNAMIC_STATE_BLEND_CONSTANTS, + }; + + VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = sizeof(dynamicStates)/sizeof(VkDynamicState), + .pDynamicStates = dynamicStates, + }; + + VkPipelineInputAssemblyStateCreateInfo piasci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_TRUE, + }; + + + VkPipelineRenderingCreateInfo prci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .pNext = NULL, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = (VkFormat[]){ VK_FORMAT_B8G8R8A8_UNORM }, // <-- replace with your actual format + .depthAttachmentFormat = VK_FORMAT_D32_SFLOAT, + }; + + VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {}; + graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + graphicsPipelineCreateInfo.pInputAssemblyState = &piasci; + graphicsPipelineCreateInfo.layout = m_layout; + graphicsPipelineCreateInfo.pDynamicState = &pipelineDynamicStateCreateInfo; + graphicsPipelineCreateInfo.stageCount = shaders.GetSize(); + CUtlVector stages(graphicsPipelineCreateInfo.stageCount); + uint32_t i = 0; + for (auto &shader: shaders) + { + stages[i] = shader.m_stageCreateInfo; + i++; + } + graphicsPipelineCreateInfo.pStages = stages.GetData(); + graphicsPipelineCreateInfo.pNext = &prci; + vkCreateGraphicsPipelines(g_vkDevice, NULL, 1, &graphicsPipelineCreateInfo, NULL, &m_pipeline); +} +void vk_tripipeline_t::Destroy() +{ + +} + +void vk_buffer_t::Create(size_t size, VkBufferUsageFlags usage) +{ + VkBufferCreateInfo bufferCreateInfo = {}; + bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferCreateInfo.usage = usage; + bufferCreateInfo.size = size; + + + VmaAllocationCreateInfo allocInfo = {}; + allocInfo.usage = VMA_MEMORY_USAGE_AUTO; + allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + m_nSize = size; + vmaCreateBuffer(g_allocator, &bufferCreateInfo, &allocInfo, &m_buffer, &m_memory, NULL); +} + +void vk_buffer_t::Destroy() +{ + +} + +void *vk_buffer_t::Map(size_t offset, size_t size) +{ + void *pData; + vmaMapMemory(g_allocator, m_memory, &pData); + return pData; +} + +void vk_buffer_t::Unmap() +{ + vmaUnmapMemory(g_allocator, m_memory); +} + + +void vk_buffer_t::CopyTo(struct vk_image2d_t *image) +{ + +} + +void vk_buffer_t::CopyTo(struct vk_buffer_t *buffer) +{ + +} +void vk_image2d_t::Create(size_t x, size_t y, VkFormat format, VkImageUsageFlags usage) +{ + VkImageCreateInfo imageInfo={}; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent.width = x > 1 ? x : 1; + imageInfo.extent.height = y > 1 ? y : 1; + imageInfo.extent.depth = 1; + imageInfo.mipLevels = 1; + imageInfo.arrayLayers = 1; + imageInfo.usage = usage; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.format=format; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + + VmaAllocationCreateInfo alloc = {}; + alloc.usage=VMA_MEMORY_USAGE_AUTO; + vmaCreateImage(g_allocator, &imageInfo,&alloc, &m_image, &m_memory,0); + + m_X=imageInfo.extent.width; + m_Y=imageInfo.extent.width; + m_format=format; + + VkImageView imageView = 0; + VkImageViewCreateInfo imageViewCreateInfo={}; + imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageViewCreateInfo.format = format; + imageViewCreateInfo.image = m_image; + imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + if (format == VK_FORMAT_D32_SFLOAT) { + imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + } + imageViewCreateInfo.subresourceRange.baseMipLevel = 0; + imageViewCreateInfo.subresourceRange.levelCount = 1; + imageViewCreateInfo.subresourceRange.baseArrayLayer = 0; + imageViewCreateInfo.subresourceRange.layerCount = 1; + vkCreateImageView(g_vkDevice, &imageViewCreateInfo, 0, &m_imageView); +} +void vk_image2d_t::Destroy() +{ + vkDestroyImageView(g_vkDevice, m_imageView, NULL); + vmaDestroyImage(g_allocator, m_image, NULL); +} + +void CopyTo(struct vk_image2d_t *image); +void CopyTo(struct vk_buffer_t *buffer); + +void *CVertexBuffer::Map() +{ + if (!m_pAllocated) + m_pAllocated = m_buffer.Map(0, m_buffer.m_nSize); + return m_pAllocated; +}; +void CVertexBuffer::Unmap() +{ + if (!m_pAllocated) + return; + m_buffer.Unmap(); + m_pAllocated = 0; +}; + +void *CIndexBuffer::Map() +{ + if (!m_pAllocated) + m_pAllocated = m_buffer.Map(0, m_buffer.m_nSize); + return m_pAllocated; +}; +void CIndexBuffer::Unmap() +{ + if (!m_pAllocated) + return; + m_buffer.Unmap(); + m_pAllocated = 0; +}; + +CUtlVector g_textures; +CUtlVector g_newtextures; + +uint32_t ITextureManager::GetTexture(ITexture *pTexture) +{ + uint32_t i = 0; + for (ITexture *texture: g_textures) + { + if (texture == pTexture) + return i; + i++; + }; + return 0; +} + +ITexture *ITextureManager::LoadTexture( void *pData, uint32_t X, uint32_t Y, uint32_t numChannels ) +{ + CTexture *pTexture = new CTexture; + *pTexture = {}; + VkDeviceSize imageSize = X*Y*4; + vk_buffer_t gpu_buffer = {}; + gpu_buffer.Create(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + void *gpu_buffer_map = gpu_buffer.Map(0, 0); + V_memcpy(gpu_buffer_map, pData, imageSize); + gpu_buffer.Unmap(); + pTexture->image = {}; + pTexture->image.Create(X, Y, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + + VkCommandPool commandPool; + VkCommandBuffer commandBuffer; + + VkCommandPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + poolInfo.queueFamilyIndex = g_drawfamily; + poolInfo.flags = 0; + vkCreateCommandPool(g_vkDevice, &poolInfo, NULL, &commandPool); + + VkCommandBufferAllocateInfo cmdAllocInfo{}; + cmdAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmdAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmdAllocInfo.commandPool = commandPool; + cmdAllocInfo.commandBufferCount = 1; + vkAllocateCommandBuffers(g_vkDevice, &cmdAllocInfo, &commandBuffer); + + + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkBeginCommandBuffer(commandBuffer, &beginInfo); + + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = pTexture->image.m_image; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + vkCmdPipelineBarrier( + commandBuffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, NULL, + 0, NULL, + 1, &barrier + ); + + VkBufferImageCopy region{}; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageOffset = {0, 0, 0}; + region.imageExtent = {(uint32_t)X, (uint32_t)Y, 1}; + vkCmdCopyBufferToImage( + commandBuffer, + gpu_buffer.m_buffer, + pTexture->image.m_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ®ion + ); + + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + vkCmdPipelineBarrier( + commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + 0, + 0, NULL, + 0, NULL, + 1, &barrier + ); + + vkEndCommandBuffer(commandBuffer); + + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffer; + + vkQueueSubmit(g_drawQueue, 1, &submitInfo, VK_NULL_HANDLE); + vkQueueWaitIdle(g_drawQueue); + vkFreeCommandBuffers(g_vkDevice, commandPool, 1, &commandBuffer); + vkDestroyCommandPool(g_vkDevice, commandPool, NULL); + + g_newtextures.AppendTail(pTexture); + g_textures.AppendTail(pTexture); + return pTexture; +}; + +ITexture *ITextureManager::LoadTexture( const char *szName ) +{ + for (ITexture *texture: g_textures) + { + if (!texture->szName) + continue; + if (!V_strcmp(texture->szName, szName)) + return texture; + }; + FileHandle_t file = IFileSystem::Open(szName, IFILE_READ); + if (!file) + Plat_FatalErrorFunc("Failed to load %s\n", szName); + + CUtlBuffer buffer(IFileSystem::Size(file)); + IFileSystem::Read(file, buffer.GetMemory(), buffer.GetSize()); + int nImageX; + int nImageY; + int nImageChannels; + stbi_uc *pixels = stbi_load_from_memory((stbi_uc*)buffer.GetMemory(), buffer.GetSize(), &nImageX, &nImageY, &nImageChannels, STBI_rgb_alpha); + ITexture *pTexture = ITextureManager::LoadTexture(pixels, nImageX, nImageY, 4); + pTexture->szName = szName; + return pTexture; +}; diff --git a/engine/vk_videolinux.cpp b/engine/vk_videolinux.cpp new file mode 100644 index 0000000..0419b22 --- /dev/null +++ b/engine/vk_videolinux.cpp @@ -0,0 +1,449 @@ +#include "rendering.h" +#include "tier1/utlvector.h" +#include "console.h" +#include "tier1/commandline.h" + +#include "X11/X.h" +#include "X11/Xlib.h" +#include "vulkan/vulkan.h" +#include "vulkan/vulkan_core.h" +#include "vulkan/vulkan_xlib.h" + +#define VULKAN_RENDERING_IMPL +#include "vk_video.h" + +#define VMA_VULKAN_VERSION 1004000 +#define VMA_IMPLEMENTATION +#include "vk_mem_alloc.h" + +Display* g_xdisplay; +int g_xscreen; +Window g_xroot; +Window g_xwin; + +VkInstance g_vkInstance = NULL; +VkPhysicalDevice g_vkPhysicalDevice = NULL; +VkDevice g_vkDevice = NULL; +uint32_t g_drawfamily = 0; +VkQueue g_drawQueue; +uint32_t g_presentfamily = 0; +VkQueue g_presentQueue; +VmaAllocator g_allocator = NULL; + + +VkSurfaceKHR g_surface; +VkSwapchainKHR g_swapchain; + +ConVar vulkan_gpu("vk_gpu", "0", FCVAR_ARCHIVE); + + +VkCommandPool g_vkCommandPool; +/* more efficient */ +CUtlVector g_commandBuffers; +VkCommandBuffer g_vkCommandBuffer; +CUtlVector g_frameData; +CUtlVector g_swapchainImages; +CUtlVector g_swapchainImageViews; +VkImageView g_swapchainImageView; +VkImage g_swapchainImage; + +uint32_t g_nNumSwapchainImages = 0; + +void IVideo_SwapchainInit() +{ + + /* swapchain */ + + VkXlibSurfaceCreateInfoKHR surfaceCreateInfo = {}; + surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; + surfaceCreateInfo.dpy = g_xdisplay; + surfaceCreateInfo.window = g_xwin; + vkCreateXlibSurfaceKHR(g_vkInstance, &surfaceCreateInfo, NULL, &g_surface); + + + VkSurfaceCapabilitiesKHR surfaceCapatibilities = {}; + + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vkPhysicalDevice, g_surface, &surfaceCapatibilities); + + const VkFormat preferedSurfaceFormats[] = { + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_B8G8R8A8_UNORM, + }; + + uint32_t numSurfaceFormats = 0; + vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_surface, &numSurfaceFormats, NULL); + CUtlVector surfaceFormats(numSurfaceFormats); + vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_surface, &numSurfaceFormats, surfaceFormats.GetData()); + + VkSurfaceFormatKHR selectedFormat = surfaceFormats[0]; + for (auto &format: surfaceFormats) + { + for (int i = 0; i < sizeof(preferedSurfaceFormats)/sizeof(VkFormat); i++) + { + selectedFormat = surfaceFormats[i]; + } + } + + uint32_t numSurfacePresentModes = 0; + vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, g_surface, &numSurfacePresentModes, NULL); + CUtlVector surfacePresentModes(numSurfacePresentModes); + vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, g_surface, &numSurfacePresentModes, surfacePresentModes.GetData()); + + VkSwapchainCreateInfoKHR swapchainCreateInfo = {}; + swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchainCreateInfo.surface = g_surface; + swapchainCreateInfo.imageFormat = selectedFormat.format; + swapchainCreateInfo.imageColorSpace = selectedFormat.colorSpace; + swapchainCreateInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchainCreateInfo.preTransform = surfaceCapatibilities.currentTransform; + swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchainCreateInfo.imageArrayLayers = 1; + swapchainCreateInfo.imageExtent = surfaceCapatibilities.minImageExtent; + swapchainCreateInfo.minImageCount = surfaceCapatibilities.minImageCount; + vkCreateSwapchainKHR(g_vkDevice, &swapchainCreateInfo, NULL, &g_swapchain); + + vkGetSwapchainImagesKHR(g_vkDevice, g_swapchain, &g_nNumSwapchainImages, NULL); + g_swapchainImages = CUtlVector(g_nNumSwapchainImages); + g_swapchainImageViews = CUtlVector(g_nNumSwapchainImages); + g_commandBuffers = CUtlVector(g_nNumSwapchainImages); + g_frameData = CUtlVector(g_nNumSwapchainImages); + vkGetSwapchainImagesKHR(g_vkDevice, g_swapchain, &g_nNumSwapchainImages, g_swapchainImages.GetData()); + + for (int i = 0; i < g_nNumSwapchainImages; i++) + { + VkImageViewCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = g_swapchainImages[i]; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = selectedFormat.format; + createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + vkCreateImageView(g_vkDevice, &createInfo, NULL, &g_swapchainImageViews[i]); + } + + + /* command buffers */ + VkCommandPoolCreateInfo commandPoolCreateInfo = {}; + commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + commandPoolCreateInfo.queueFamilyIndex = g_drawfamily; + commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + vkCreateCommandPool(g_vkDevice, &commandPoolCreateInfo, NULL, &g_vkCommandPool); + + VkCommandBufferAllocateInfo commandBufferAllocInfo = {}; + commandBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + commandBufferAllocInfo.commandPool = g_vkCommandPool; + commandBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + commandBufferAllocInfo.commandBufferCount = g_nNumSwapchainImages; + vkAllocateCommandBuffers(g_vkDevice, &commandBufferAllocInfo, g_commandBuffers.GetData()); + + /* sync */ + + VkFenceCreateInfo fenceCreateInfo = {}; + fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + VkSemaphoreCreateInfo semaphoreCreateInfo = {}; + semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + for (int i = 0; i < g_nNumSwapchainImages; i++) + { + vkCreateFence(g_vkDevice,&fenceCreateInfo, NULL, &g_frameData[i].fence); + vkCreateSemaphore(g_vkDevice, &semaphoreCreateInfo, NULL, &g_frameData[i].draw); + vkCreateSemaphore(g_vkDevice, &semaphoreCreateInfo, NULL, &g_frameData[i].present); + } + +}; + +void IVideo_SwapchainDestroy() +{ + vkDestroySwapchainKHR(g_vkDevice, g_swapchain, NULL); + vkDestroySurfaceKHR(g_vkInstance, g_surface, NULL); + for (int i = 0; i < g_nNumSwapchainImages; i++) + { + vkDestroyImageView(g_vkDevice, g_swapchainImageViews[i], NULL); + vkDestroySemaphore(g_vkDevice, g_frameData[i].draw, NULL); + vkDestroySemaphore(g_vkDevice, g_frameData[i].present, NULL); + vkDestroyFence(g_vkDevice, g_frameData[i].fence, NULL); + } +}; + +#define VK_DEVICE_FUNCTION(name) PFN_##name _##name +#include "vk_external_functions.cpp" +#undef VK_DEVICE_FUNCTION + +void IVideo::Init() +{ + g_xdisplay = XOpenDisplay(NULL); + g_xscreen = DefaultScreen(g_xdisplay); + g_xroot = RootWindow(g_xdisplay, g_xscreen); + g_xwin = XCreateSimpleWindow(g_xdisplay, g_xroot, 0, 0, 1280, 720, 0, 0, 0); + XSelectInput(g_xdisplay, g_xwin, StructureNotifyMask); + + vulkan_gpu.SetValue(ICommandLine::ParamValue("-gpu")); + VkResult r = VK_SUCCESS; + uint32_t i = 0; + + /* Instance */ + VkApplicationInfo applicationInfo = {}; + applicationInfo.apiVersion = VK_API_VERSION_1_4; + + VkInstanceCreateInfo instanceCreateInfo = {}; + instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instanceCreateInfo.pApplicationInfo = &applicationInfo; + + const char *szEnabledExtensions[] = { + VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_XLIB_SURFACE_EXTENSION_NAME, + }; + instanceCreateInfo.enabledExtensionCount = 2; + instanceCreateInfo.ppEnabledExtensionNames = szEnabledExtensions; + r = vkCreateInstance(&instanceCreateInfo, NULL, &g_vkInstance); + if ( r != VK_SUCCESS ) + Plat_FatalErrorFunc("Failed to create VkInstance!"); + + + /* Physical Devices */ + uint32_t nNumPhysicalDevices = 0; + vkEnumeratePhysicalDevices(g_vkInstance, &nNumPhysicalDevices, NULL); + if ( nNumPhysicalDevices == 0 ) + Plat_FatalErrorFunc("No GPU drivers available!"); + CUtlVector PhysicalDevices(nNumPhysicalDevices); + + vkEnumeratePhysicalDevices(g_vkInstance, &nNumPhysicalDevices, PhysicalDevices.GetData()); + + /* enumerate them for the user */ + for (auto &device: PhysicalDevices) + { + VkPhysicalDeviceProperties Properties = {}; + vkGetPhysicalDeviceProperties(device, &Properties); + V_printf("GPU%i available: %s\n", i, Properties.deviceName); + i++; + } + + /* select one in vk_gpu */ + g_vkPhysicalDevice = PhysicalDevices[vulkan_gpu.GetInt()]; + + /* queue family */ + uint32_t nNumQueueFamilies = 0; + vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL); + CUtlVector queueFamilyProperties(nNumQueueFamilies); + vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, queueFamilyProperties.GetData()); + + i = 0; + for (auto &family: queueFamilyProperties) + { + if (family.queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + g_drawfamily = i; + g_presentfamily = i; + } + i++; + } + + /* create device */ + float queuePriority = 1.0f; + VkDeviceQueueCreateInfo queueCreateInfo = {}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = g_drawfamily; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + + VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT pdvidsfe = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT, + .vertexInputDynamicState = VK_TRUE, + }; + + VkPhysicalDeviceExtendedDynamicState3FeaturesEXT pdeds3fe = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT, + .pNext = &pdvidsfe, + .extendedDynamicState3DepthClampEnable = VK_TRUE, + .extendedDynamicState3PolygonMode = VK_TRUE, + .extendedDynamicState3RasterizationSamples = VK_TRUE, + .extendedDynamicState3SampleMask = VK_TRUE, + .extendedDynamicState3AlphaToCoverageEnable = VK_TRUE, + .extendedDynamicState3LogicOpEnable = VK_TRUE, + .extendedDynamicState3ColorBlendEnable = VK_TRUE, + .extendedDynamicState3ColorBlendEquation = VK_TRUE, + .extendedDynamicState3ColorWriteMask = VK_TRUE, + }; + + VkPhysicalDeviceExtendedDynamicState2FeaturesEXT pdeds2fe = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT, + .pNext = &pdeds3fe, + .extendedDynamicState2LogicOp = VK_TRUE, + .extendedDynamicState2PatchControlPoints = VK_TRUE, + }; + + VkPhysicalDeviceVulkan13Features pdv13f = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, + .pNext = &pdeds2fe, + .dynamicRendering = VK_TRUE, + }; + VkPhysicalDeviceVulkan12Features pdv12f = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, + .pNext = &pdv13f, + .runtimeDescriptorArray = VK_TRUE, + .bufferDeviceAddress = VK_TRUE, + }; + VkPhysicalDeviceVulkan11Features pdv11f = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, + .pNext = &pdv12f, + }; + + const char *szEnabledGPUExtensions[] = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME, + VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME, + }; + VkDeviceCreateInfo deviceCreateInfo = {}; + deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; + deviceCreateInfo.queueCreateInfoCount = 1; + deviceCreateInfo.enabledExtensionCount = sizeof(szEnabledGPUExtensions)/(sizeof(const char*)); + deviceCreateInfo.ppEnabledExtensionNames = szEnabledGPUExtensions; + deviceCreateInfo.pNext = &pdv11f; + + r = vkCreateDevice(g_vkPhysicalDevice, &deviceCreateInfo, NULL, &g_vkDevice); + if ( r != VK_SUCCESS ) + Plat_FatalErrorFunc("Failed to create VkDevice!"); + vkGetDeviceQueue(g_vkDevice, g_drawfamily, 0, &g_drawQueue); + vkGetDeviceQueue(g_vkDevice, g_presentfamily, 0, &g_presentQueue); + + VmaVulkanFunctions vulkanFunctions = {}; + vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr; + vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr; + + VmaAllocatorCreateInfo allocatorCreateInfo = {}; + allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_4; + allocatorCreateInfo.physicalDevice = g_vkPhysicalDevice; + allocatorCreateInfo.device = g_vkDevice; + allocatorCreateInfo.instance = g_vkInstance; + vmaCreateAllocator(&allocatorCreateInfo, &g_allocator); + + #define VK_DEVICE_FUNCTION(name) _##name = (PFN_##name)vkGetDeviceProcAddr(g_vkDevice, #name) + #include "vk_external_functions.cpp" + #undef VK_DEVICE_FUNCTION + + IVideo_SwapchainInit(); + + XMapWindow(g_xdisplay, g_xwin); + XFlush(g_xdisplay); + + IVulkan::Init(); + +} + +char g_bConfigNotify = 0; +uint32_t g_nWindowWidth = 1280; +uint32_t g_nWindowHeight = 720; + +void IVideo_HandleX11() +{ + XEvent event; + while(XPending(g_xdisplay)) + { + XNextEvent(g_xdisplay, &event); + switch (event.type) + { + case KeyPress: + case KeyRelease: + + break; + case MotionNotify: + break; + case ButtonPress: + break; + case ButtonRelease: + break; + + case CreateNotify: + break; + case ConfigureNotify: + g_nWindowWidth = event.xconfigure.width; + g_nWindowHeight = event.xconfigure.height; + g_bConfigNotify = 2; + break; + } + } +}; + + +void IVideo::Frame( float fDelta ) +{ + static uint32_t s_frameID = 0; + IVideo_HandleX11(); + + vk_framedata_t frame = g_frameData[s_frameID]; + vkDeviceWaitIdle(g_vkDevice); + + vkWaitForFences(g_vkDevice, 1, &frame.fence, VK_TRUE, UINT64_MAX); + + uint32_t imageIndex = 0; + VkResult r = vkAcquireNextImageKHR(g_vkDevice, g_swapchain, UINT64_MAX, frame.draw, VK_NULL_HANDLE, &imageIndex); + if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR || g_bConfigNotify == 2) + { + g_bConfigNotify=1; + vkDeviceWaitIdle(g_vkDevice); + IVideo_SwapchainDestroy(); + IVideo_SwapchainInit(); + return; + } + vk_framedata_t frameindex = g_frameData[imageIndex]; + + vkResetFences(g_vkDevice, 1, &frame.fence); + + g_vkCommandBuffer = g_commandBuffers[s_frameID]; + g_swapchainImageView = g_swapchainImageViews[imageIndex]; + g_swapchainImage = g_swapchainImages[imageIndex]; + vkResetCommandBuffer(g_vkCommandBuffer, 0); + + VkCommandBufferBeginInfo beginInfo = {}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkBeginCommandBuffer(g_vkCommandBuffer, &beginInfo); + IVulkan::Frame(); + vkEndCommandBuffer(g_vkCommandBuffer); + + VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = &frame.draw; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &g_vkCommandBuffer; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = &frameindex.present; + + vkQueueSubmit(g_drawQueue, 1, &submitInfo, frame.fence); + + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = &frameindex.present; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &g_swapchain; + presentInfo.pImageIndices = &imageIndex; + + + r = vkQueuePresentKHR(g_presentQueue, &presentInfo); + if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR) + { + vkDeviceWaitIdle(g_vkDevice); + IVideo_SwapchainDestroy(); + IVideo_SwapchainInit(); + return; + } + + g_bConfigNotify = 0; + s_frameID=(s_frameID+1)%g_nNumSwapchainImages; +}; diff --git a/external/Vulkan-Headers b/external/Vulkan-Headers new file mode 160000 index 0000000..75ad707 --- /dev/null +++ b/external/Vulkan-Headers @@ -0,0 +1 @@ +Subproject commit 75ad707a587e1469fb53a901b9b68fe9f6fbc11f diff --git a/external/VulkanMemoryAllocator b/external/VulkanMemoryAllocator new file mode 160000 index 0000000..f0969e9 --- /dev/null +++ b/external/VulkanMemoryAllocator @@ -0,0 +1 @@ +Subproject commit f0969e908b01104f66bec2f203103de2012354c9 diff --git a/external/cglm b/external/cglm new file mode 160000 index 0000000..a886d6e --- /dev/null +++ b/external/cglm @@ -0,0 +1 @@ +Subproject commit a886d6e170292a1d534a7a2c0471be5953b16455 diff --git a/external/stb b/external/stb new file mode 160000 index 0000000..802cd45 --- /dev/null +++ b/external/stb @@ -0,0 +1 @@ +Subproject commit 802cd454f25469d3123e678af41364153c132c2a diff --git a/fgui/__build.c b/fgui/__build.c new file mode 100644 index 0000000..57bce9e --- /dev/null +++ b/fgui/__build.c @@ -0,0 +1,37 @@ + + +char* fgui_lib = 0; +void fgui_build(struct build_data b) +{ + char* files[] = { + "fgui/fgui.cpp", + NULL, + }; + struct C_Macro macros[] = { + (struct C_Macro){"TIER0_IMPLEMENTATION","1"}, + NULL, + }; + + + struct project p = { + .b = &b, + .files = files, + .name = "fgui", + }; + + struct project o = C_compile(p, (struct C_settings){ + .generation_flags = C_GENERATION_FLAGS_PIC, + .compile_flags = C_COMPILE_FLAGS_WALL, + .include_dirs = include_dirs, + .macros = macros, + }); + char* libs[] = { + "c", + NULL, + }; + + fgui_lib = ld_link_project(o, (struct link_settings){ + .type = LINK_TYPE_STATIC, + .libs = libs, + }); +} \ No newline at end of file diff --git a/fgui/fgui.cpp b/fgui/fgui.cpp new file mode 100644 index 0000000..7f3e91c --- /dev/null +++ b/fgui/fgui.cpp @@ -0,0 +1 @@ +#include "fgui/fgui.h" \ No newline at end of file diff --git a/funnyassets/__build.c b/funnyassets/__build.c new file mode 100644 index 0000000..b5ce5a1 --- /dev/null +++ b/funnyassets/__build.c @@ -0,0 +1,36 @@ +#include "god/slang.h" +#include "god/utils.h" +#include "god/common.h" + +void build_shader(char *name, enum slang_stage stage) +{ + struct slang_settings shadercc = { + .entry = string_clone("funnyassets/gfx_shaders/%s.slang", name), + .stage = stage, + .output_type = SLANG_OUTPUT_SPIRV, + }; + char *file = slang_compile(shadercc); + mv(string_clone("funnyassets/_rtt/gfx/%s.spv",name),file); +}; + +void makepak(char *name) +{ + struct run_project rp = run_new("python"); + run_add_arg(&rp, "tools/makepak64.py"); + run_add_arg(&rp, string_clone("funnyassets/_%s",name)); + run_add_arg(&rp, string_clone("build/"GAME_NAME"/game/"GAME_NAME"/%s.pak", name)); + run_run(&rp); +}; + +void assets_build(struct build_data b) +{ + remove("funnyassets/_rtt"); + makedir("funnyassets/_rtt/gfx"); + build_shader("brush_frag", SLANG_STAGE_FRAGMENT); + build_shader("brush_vert", SLANG_STAGE_VERTEX); + mv("funnyassets/_rtt/","funnyassets/maps"); + mv("funnyassets/_rtt/","funnyassets/gfx"); + mv("funnyassets/_rtt/","funnyassets/textures"); + mv("funnyassets/_rtt/","funnyassets/materials"); + makepak("rtt"); +} diff --git a/funnyassets/_rtt/gfx/bricks.png b/funnyassets/_rtt/gfx/bricks.png new file mode 100644 index 0000000..93e734e Binary files /dev/null and b/funnyassets/_rtt/gfx/bricks.png differ diff --git a/funnyassets/_rtt/gfx/brush_frag.spv b/funnyassets/_rtt/gfx/brush_frag.spv new file mode 100644 index 0000000..95d7a20 Binary files /dev/null and b/funnyassets/_rtt/gfx/brush_frag.spv differ diff --git a/funnyassets/_rtt/gfx/brush_vert.spv b/funnyassets/_rtt/gfx/brush_vert.spv new file mode 100644 index 0000000..e9f6f1a Binary files /dev/null and b/funnyassets/_rtt/gfx/brush_vert.spv differ diff --git a/funnyassets/_rtt/maps/test_map.fmap b/funnyassets/_rtt/maps/test_map.fmap new file mode 100644 index 0000000..ea85176 Binary files /dev/null and b/funnyassets/_rtt/maps/test_map.fmap differ diff --git a/funnyassets/_rtt/materials/brick.fmat b/funnyassets/_rtt/materials/brick.fmat new file mode 100644 index 0000000..fa0f0da --- /dev/null +++ b/funnyassets/_rtt/materials/brick.fmat @@ -0,0 +1,2 @@ +parent rtt_simple_pbr +albedo textures/bricks.png diff --git a/funnyassets/_rtt/textures/bricks.png b/funnyassets/_rtt/textures/bricks.png new file mode 100644 index 0000000..620b6b1 Binary files /dev/null and b/funnyassets/_rtt/textures/bricks.png differ diff --git a/funnyassets/gfx_shaders/brush_frag.slang b/funnyassets/gfx_shaders/brush_frag.slang new file mode 100644 index 0000000..eacbf29 --- /dev/null +++ b/funnyassets/gfx_shaders/brush_frag.slang @@ -0,0 +1,27 @@ +uint32_t hash32(uint32_t x) { + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = (x >> 16) ^ x; + return x; +} + +[[vk::binding(1)]] +uniform Sampler2D textures[]; + + +struct VertexOutput +{ + float4 position: SV_Position; + float2 uv: TEXCOORD0; +}; + +float4 main( + VertexOutput input, + uint triid: SV_PrimitiveID, + uniform uint textureID, +) : SV_TARGET +{ + return float4(textures[textureID].Sample(input.uv).xyz, 1); + +} + diff --git a/funnyassets/gfx_shaders/brush_vert.slang b/funnyassets/gfx_shaders/brush_vert.slang new file mode 100644 index 0000000..8c8a4bd --- /dev/null +++ b/funnyassets/gfx_shaders/brush_vert.slang @@ -0,0 +1,27 @@ +struct VertexInput +{ + float3 position: POSITION; + float2 uv: TEXCOORD0; +}; + +struct VertexOutput +{ + float4 position: SV_Position; + float2 uv: TEXCOORD0; +}; + +[[vk::binding(0)]] +cbuffer CameraInfo +{ + float4x4 projection; +}; + +VertexOutput main( + VertexInput input, +) +{ + VertexOutput output; + output.position = mul(projection, float4(input.position,1)); + output.uv = input.uv; + return output; +} diff --git a/funnyassets/maps/test_map.fmap b/funnyassets/maps/test_map.fmap new file mode 100644 index 0000000..ea85176 Binary files /dev/null and b/funnyassets/maps/test_map.fmap differ diff --git a/funnyassets/materials/brick.fmat b/funnyassets/materials/brick.fmat new file mode 100644 index 0000000..fa0f0da --- /dev/null +++ b/funnyassets/materials/brick.fmat @@ -0,0 +1,2 @@ +parent rtt_simple_pbr +albedo textures/bricks.png diff --git a/funnyassets/raw_maps/dust.map b/funnyassets/raw_maps/dust.map new file mode 100644 index 0000000..354a5ee --- /dev/null +++ b/funnyassets/raw_maps/dust.map @@ -0,0 +1,106 @@ +{ +"classname" "worldspawn" +{ +(-4.000000 8.000000 -2.000000) (-8.000000 8.000000 -2.000000) (-8.000000 8.000000 -4.000000) (6.483328 1.451694) (6.483328 0.190320) (7.114015 0.190320) BRICK0 +(-4.000000 8.000000 -2.000000) (-8.000000 8.000000 -4.000000) (-4.000000 8.000000 -4.000000) (6.483328 1.451694) (7.114015 0.190320) (7.114015 1.451694) BRICK0 +(0.000000 12.000000 -2.000000) (0.000000 14.000000 -2.000000) (-0.300000 14.000000 -2.000000) (0.820848 2.713067) (0.190320 2.713067) (0.190320 2.618464) BRICK0 +(0.000000 12.000000 -2.000000) (-0.300000 14.000000 -2.000000) (-0.300000 12.000000 -2.000000) (0.820848 2.713067) (0.190320 2.618464) (0.820848 2.618464) BRICK0 +(0.000000 6.000000 -4.000000) (4.000000 6.000000 -4.000000) (4.000000 10.000000 -2.000000) (2.726604 2.713067) (2.726604 3.974441) (1.451375 3.974441) BRICK0 +(0.000000 6.000000 -4.000000) (4.000000 10.000000 -2.000000) (0.000000 10.000000 -2.000000) (2.726604 2.713067) (1.451375 3.974441) (1.451375 2.713067) BRICK0 +(0.000000 6.000000 -4.000000) (0.000000 10.000000 -2.000000) (0.000000 6.000000 -2.000000) (6.798353 5.902491) (6.167666 7.163865) (6.167666 5.902491) BRICK0 +(0.000000 12.000000 -2.000000) (4.000000 12.000000 -2.000000) (4.000000 14.000000 -2.000000) (0.820848 2.713067) (0.820848 3.974441) (0.190320 3.974441) BRICK0 +(0.000000 12.000000 -2.000000) (4.000000 14.000000 -2.000000) (0.000000 14.000000 -2.000000) (0.820848 2.713067) (0.190320 3.974441) (0.190320 2.713067) BRICK0 +(-0.300000 12.000000 -2.000000) (-0.300000 14.000000 -2.000000) (-3.700000 14.000000 -2.000000) (0.820848 2.618464) (0.190320 2.618464) (0.190320 1.546297) BRICK0 +(-0.300000 12.000000 -2.000000) (-3.700000 14.000000 -2.000000) (-3.700000 12.000000 -2.000000) (0.820848 2.618464) (0.190320 1.546297) (0.820848 1.546297) BRICK0 +(0.000000 2.000000 -4.000000) (4.000000 2.000000 -4.000000) (4.000000 6.000000 -4.000000) (3.987659 2.713067) (3.987659 3.974441) (2.726604 3.974441) BRICK0 +(0.000000 2.000000 -4.000000) (4.000000 6.000000 -4.000000) (0.000000 6.000000 -4.000000) (3.987659 2.713067) (2.726604 3.974441) (2.726604 2.713067) BRICK0 +(-0.300000 10.000000 -2.000000) (-3.700000 10.000000 -2.000000) (-3.700000 8.300000 -2.000000) (1.451375 2.618464) (1.451375 1.546297) (1.987324 1.546297) BRICK0 +(-0.300000 10.000000 -2.000000) (-3.700000 8.300000 -2.000000) (-0.300000 8.300000 -2.000000) (1.451375 2.618464) (1.987324 1.546297) (1.987324 2.618464) BRICK0 +(-4.000000 6.000000 -4.000000) (-4.000000 8.000000 -4.000000) (-8.000000 8.000000 -4.000000) (2.726604 1.451694) (2.096077 1.451694) (2.096077 0.190320) BRICK0 +(-4.000000 6.000000 -4.000000) (-8.000000 8.000000 -4.000000) (-8.000000 6.000000 -4.000000) (2.726604 1.451694) (2.096077 0.190320) (2.726604 0.190320) BRICK0 +(-4.000000 2.000000 -4.000000) (-4.000000 6.000000 -4.000000) (-8.000000 6.000000 -4.000000) (3.987659 1.451694) (2.726604 1.451694) (2.726604 0.190320) BRICK0 +(-4.000000 2.000000 -4.000000) (-8.000000 6.000000 -4.000000) (-8.000000 2.000000 -4.000000) (3.987659 1.451694) (2.726604 0.190320) (3.987659 0.190320) BRICK0 +(-4.000000 6.000000 -4.000000) (-4.000000 6.000000 -2.000000) (-4.000000 8.000000 -2.000000) (6.325656 2.620692) (6.325656 1.990005) (6.956343 1.990005) BRICK0 +(-4.000000 6.000000 -4.000000) (-4.000000 8.000000 -2.000000) (-4.000000 8.000000 -4.000000) (6.325656 2.620692) (6.956343 1.990005) (6.956343 2.620692) BRICK0 +(0.000000 6.000000 -4.000000) (0.000000 6.000000 -2.000000) (-4.000000 6.000000 -2.000000) (5.156658 7.258468) (4.525971 7.258468) (4.525971 5.997094) BRICK0 +(0.000000 6.000000 -4.000000) (-4.000000 6.000000 -2.000000) (-4.000000 6.000000 -4.000000) (5.156658 7.258468) (4.525971 5.997094) (5.156658 5.997094) BRICK0 +(0.000000 2.000000 -4.000000) (0.000000 6.000000 -4.000000) (-4.000000 6.000000 -4.000000) (3.987659 2.713067) (2.726604 2.713067) (2.726604 1.451694) BRICK0 +(0.000000 2.000000 -4.000000) (-4.000000 6.000000 -4.000000) (-4.000000 2.000000 -4.000000) (3.987659 2.713067) (2.726604 1.451694) (3.987659 1.451694) BRICK0 +(-0.300000 8.300000 -2.000000) (-3.700000 8.300000 -2.000000) (-3.700000 6.300000 -2.000000) (1.987324 2.618464) (1.987324 1.546297) (2.617851 1.546297) BRICK0 +(-0.300000 8.300000 -2.000000) (-3.700000 6.300000 -2.000000) (-0.300000 6.300000 -2.000000) (1.987324 2.618464) (2.617851 1.546297) (2.617851 2.618464) BRICK0 +(-3.700000 8.300000 -2.000000) (-3.700000 10.000000 -2.000000) (-8.000000 10.000000 -2.000000) (1.987324 1.546297) (1.451375 1.546297) (1.451375 0.190320) BRICK0 +(-3.700000 8.300000 -2.000000) (-8.000000 10.000000 -2.000000) (-8.000000 8.300000 -2.000000) (1.987324 1.546297) (1.451375 0.190320) (1.987324 0.190320) BRICK0 +(4.000000 6.000000 -4.000000) (4.000000 2.000000 -4.000000) (6.000000 2.000000 -4.000000) (2.726604 3.974441) (3.987659 3.974441) (3.987659 4.605128) BRICK0 +(4.000000 6.000000 -4.000000) (6.000000 2.000000 -4.000000) (6.000000 6.000000 -4.000000) (2.726604 3.974441) (3.987659 4.605128) (2.726604 4.605128) BRICK0 +(4.000000 6.000000 -4.000000) (6.000000 6.000000 -4.000000) (6.000000 6.000000 -2.000000) (1.451694 6.562484) (0.821007 6.562484) (0.821007 5.931798) BRICK0 +(4.000000 6.000000 -4.000000) (6.000000 6.000000 -2.000000) (4.000000 6.000000 -2.000000) (1.451694 6.562484) (0.821007 5.931798) (1.451694 5.931798) BRICK0 +(6.000000 6.000000 -4.000000) (6.000000 2.000000 -4.000000) (6.000000 2.000000 -2.000000) (7.809680 5.902491) (7.809680 7.163865) (7.178993 7.163865) BRICK0 +(6.000000 6.000000 -4.000000) (6.000000 2.000000 -2.000000) (6.000000 6.000000 -2.000000) (7.809680 5.902491) (7.178993 7.163865) (7.178992 5.902491) BRICK0 +(4.000000 6.000000 -4.000000) (4.000000 6.000000 -2.000000) (4.000000 10.000000 -2.000000) (5.945016 2.713067) (5.314330 2.713067) (5.314329 1.451694) BRICK0 +(-3.700000 10.000000 -2.000000) (-3.700000 12.000000 -2.000000) (-8.000000 12.000000 -2.000000) (1.451375 1.546297) (0.820848 1.546297) (0.820848 0.190320) BRICK0 +(-3.700000 10.000000 -2.000000) (-8.000000 12.000000 -2.000000) (-8.000000 10.000000 -2.000000) (1.451375 1.546297) (0.820848 0.190320) (1.451375 0.190320) BRICK0 +(-0.300000 10.000000 -2.000000) (-0.300000 12.000000 -2.000000) (-3.700000 12.000000 -2.000000) (1.451375 2.618464) (0.820848 2.618464) (0.820848 1.546297) BRICK0 +(-0.300000 10.000000 -2.000000) (-3.700000 12.000000 -2.000000) (-3.700000 10.000000 -2.000000) (1.451375 2.618464) (0.820848 1.546297) (1.451375 1.546297) BRICK0 +(0.000000 10.000000 -2.000000) (4.000000 10.000000 -2.000000) (4.000000 12.000000 -2.000000) (1.451375 2.713067) (1.451375 3.974441) (0.820848 3.974441) BRICK0 +(0.000000 10.000000 -2.000000) (4.000000 12.000000 -2.000000) (0.000000 12.000000 -2.000000) (1.451375 2.713067) (0.820848 3.974441) (0.820848 2.713067) BRICK0 +(0.000000 10.000000 -2.000000) (0.000000 12.000000 -2.000000) (-0.300000 12.000000 -2.000000) (1.451375 2.713067) (0.820848 2.713067) (0.820848 2.618464) BRICK0 +(0.000000 10.000000 -2.000000) (-0.300000 12.000000 -2.000000) (-0.300000 10.000000 -2.000000) (1.451375 2.713067) (0.820848 2.618464) (1.451375 2.618464) BRICK0 +(4.000000 6.000000 -2.000000) (6.000000 6.000000 -2.000000) (6.000000 6.000000 1.000000) (1.451694 5.931798) (0.821007 5.931798) (0.821007 4.985767) BRICK0 +(4.000000 6.000000 -2.000000) (6.000000 6.000000 1.000000) (4.000000 6.000000 1.000000) (1.451694 5.931798) (0.821007 4.985767) (1.451694 4.985767) BRICK0 +(4.000000 12.000000 -2.000000) (4.000000 10.000000 -2.000000) (4.000000 10.000000 1.000000) (5.314329 0.821007) (5.314329 1.451694) (4.368299 1.451694) BRICK0 +(4.000000 12.000000 -2.000000) (4.000000 10.000000 1.000000) (4.000000 12.000000 1.000000) (5.314329 0.821007) (4.368299 1.451694) (4.368299 0.821007) BRICK0 +(4.000000 10.000000 -2.000000) (4.000000 6.000000 -2.000000) (4.000000 6.000000 1.000000) (5.314329 1.451694) (5.314330 2.713067) (4.368299 2.713067) BRICK0 +(4.000000 10.000000 -2.000000) (4.000000 6.000000 1.000000) (4.000000 10.000000 1.000000) (5.314329 1.451694) (4.368299 2.713067) (4.368299 1.451694) BRICK0 +(-0.300000 14.000000 -2.000000) (0.000000 14.000000 -2.000000) (0.000000 14.000000 1.000000) (6.956025 4.165875) (6.956025 4.260478) (6.009995 4.260478) BRICK0 +(-0.300000 14.000000 -2.000000) (0.000000 14.000000 1.000000) (-0.300000 14.000000 1.000000) (6.956025 4.165875) (6.009995 4.260478) (6.009995 4.165875) BRICK0 +(0.000000 14.000000 -2.000000) (4.000000 14.000000 -2.000000) (4.000000 14.000000 1.000000) (6.956025 4.260478) (6.956025 5.521852) (6.009995 5.521852) BRICK0 +(0.000000 14.000000 -2.000000) (4.000000 14.000000 1.000000) (0.000000 14.000000 1.000000) (6.956025 4.260478) (6.009995 5.521852) (6.009995 4.260478) BRICK0 +(4.000000 14.000000 -2.000000) (4.000000 12.000000 -2.000000) (4.000000 12.000000 1.000000) (5.314329 0.190320) (5.314329 0.821007) (4.368299 0.821007) BRICK0 +(4.000000 14.000000 -2.000000) (4.000000 12.000000 1.000000) (4.000000 14.000000 1.000000) (5.314329 0.190320) (4.368299 0.821007) (4.368299 0.190320) BRICK0 +(-8.000000 12.000000 -2.000000) (-3.700000 12.000000 -2.000000) (-3.700000 12.000000 1.000000) (2.778364 4.985768) (2.778364 6.341744) (1.832334 6.341744) BRICK0 +(-8.000000 12.000000 -2.000000) (-3.700000 12.000000 1.000000) (-8.000000 12.000000 1.000000) (2.778364 4.985768) (1.832334 6.341744) (1.832334 4.985768) BRICK0 +(-3.700000 14.000000 -2.000000) (-0.300000 14.000000 -2.000000) (-0.300000 14.000000 1.000000) (6.956025 3.093707) (6.956025 4.165875) (6.009995 4.165875) BRICK0 +(-3.700000 14.000000 -2.000000) (-0.300000 14.000000 1.000000) (-3.700000 14.000000 1.000000) (6.956025 3.093707) (6.009995 4.165875) (6.009994 3.093707) BRICK0 +(-3.700000 12.000000 -2.000000) (-3.700000 14.000000 -2.000000) (-3.700000 14.000000 1.000000) (2.463020 7.668415) (1.832333 7.668415) (1.832333 6.722384) BRICK0 +(-3.700000 12.000000 -2.000000) (-3.700000 14.000000 1.000000) (-3.700000 12.000000 1.000000) (2.463020 7.668415) (1.832333 6.722384) (2.463020 6.722384) BRICK0 +(6.000000 6.000000 1.000000) (6.000000 6.000000 -2.000000) (8.000000 6.000000 -2.000000) (0.821007 4.985767) (0.821007 5.931798) (0.190320 5.931798) BRICK0 +(6.000000 6.000000 1.000000) (8.000000 6.000000 -2.000000) (8.000000 6.000000 1.000000) (0.821007 4.985767) (0.190320 5.931798) (0.190320 4.985767) BRICK0 +(-0.300000 8.300000 -2.000000) (-0.300000 6.300000 -2.000000) (-0.300000 6.300000 -1.500000) (3.854987 5.521851) (3.854987 6.152538) (3.697315 6.152538) BRICK0 +(-0.300000 8.300000 -2.000000) (-0.300000 6.300000 -1.500000) (-0.300000 8.300000 -1.500000) (3.854987 5.521851) (3.697315 6.152538) (3.697315 5.521851) BRICK0 +(-3.700000 8.300000 -2.000000) (-8.000000 8.300000 -2.000000) (-8.000000 8.300000 -1.500000) (3.316675 4.985768) (3.316675 6.341744) (3.159004 6.341744) BRICK0 +(-3.700000 8.300000 -2.000000) (-8.000000 8.300000 -1.500000) (-3.700000 8.300000 -1.500000) (3.316675 4.985768) (3.159004 6.341744) (3.159004 4.985768) BRICK0 +(-4.000000 8.000000 -2.000000) (-4.000000 6.000000 -2.000000) (-4.000000 6.000000 -1.500000) (6.956343 1.990005) (6.325656 1.990005) (6.325656 1.832333) BRICK0 +(-4.000000 8.000000 -2.000000) (-4.000000 6.000000 -1.500000) (-4.000000 8.000000 -1.500000) (6.956343 1.990005) (6.325656 1.832333) (6.956343 1.832333) BRICK0 +(0.000000 10.000000 -2.000000) (-0.300000 10.000000 -2.000000) (-0.300000 10.000000 -1.500000) (2.938263 6.880056) (2.843660 6.880056) (2.843660 6.722384) BRICK0 +(0.000000 10.000000 -2.000000) (-0.300000 10.000000 -1.500000) (0.000000 10.000000 -1.500000) (2.938263 6.880056) (2.843660 6.722384) (2.938263 6.722384) BRICK0 +(-0.300000 6.300000 -2.000000) (-3.700000 6.300000 -2.000000) (-3.700000 6.300000 -1.500000) (7.494336 3.093707) (7.494337 4.165875) (7.336665 4.165875) BRICK0 +(-0.300000 6.300000 -2.000000) (-3.700000 6.300000 -1.500000) (-0.300000 6.300000 -1.500000) (7.494336 3.093707) (7.336665 4.165875) (7.336665 3.093707) BRICK0 +(0.000000 6.000000 -2.000000) (0.000000 10.000000 -2.000000) (0.000000 10.000000 -1.500000) (6.167666 5.902491) (6.167666 7.163865) (6.009995 7.163865) BRICK0 +(0.000000 6.000000 -2.000000) (0.000000 10.000000 -1.500000) (0.000000 6.000000 -1.500000) (6.167666 5.902491) (6.009995 7.163865) (6.009995 5.902491) BRICK0 +(-4.000000 6.000000 -2.000000) (0.000000 6.000000 -2.000000) (0.000000 6.000000 -1.500000) (4.525971 5.997094) (4.525971 7.258468) (4.368299 7.258468) BRICK0 +(-4.000000 6.000000 -2.000000) (0.000000 6.000000 -1.500000) (-4.000000 6.000000 -1.500000) (4.525971 5.997094) (4.368299 7.258468) (4.368299 5.997094) BRICK0 +(-3.700000 6.300000 -2.000000) (-3.700000 8.300000 -2.000000) (-3.700000 8.300000 -1.500000) (3.854987 6.533178) (3.854987 7.163865) (3.697315 7.163865) BRICK0 +(-3.700000 6.300000 -2.000000) (-3.700000 8.300000 -1.500000) (-3.700000 6.300000 -1.500000) (3.854987 6.533178) (3.697315 7.163865) (3.697315 6.533178) BRICK0 +(-8.000000 8.000000 -2.000000) (-4.000000 8.000000 -2.000000) (-4.000000 8.000000 -1.500000) (6.483328 0.190320) (6.483328 1.451694) (6.325656 1.451694) BRICK0 +(-8.000000 8.000000 -2.000000) (-4.000000 8.000000 -1.500000) (-8.000000 8.000000 -1.500000) (6.483328 0.190320) (6.325656 1.451694) (6.325656 0.190320) BRICK0 +(-0.300000 10.000000 -2.000000) (-0.300000 8.300000 -2.000000) (-0.300000 8.300000 -1.500000) (3.854987 4.985767) (3.854987 5.521851) (3.697315 5.521851) BRICK0 +(-0.300000 10.000000 -2.000000) (-0.300000 8.300000 -1.500000) (-0.300000 10.000000 -1.500000) (3.854987 4.985767) (3.697315 5.521851) (3.697315 4.985767) BRICK0 +(-4.000000 8.000000 -1.500000) (-3.700000 8.300000 -1.500000) (-8.000000 8.300000 -1.500000) (4.998827 4.355081) (4.904248 4.449684) (4.904248 3.093707) BRICK0 +(-4.000000 8.000000 -1.500000) (-8.000000 8.300000 -1.500000) (-8.000000 8.000000 -1.500000) (4.998827 4.355081) (4.904248 3.093707) (4.998827 3.093707) BRICK0 +(-4.000000 6.000000 -1.500000) (-3.700000 6.300000 -1.500000) (-3.700000 8.300000 -1.500000) (5.629354 4.355081) (5.534775 4.449684) (4.904248 4.449684) BRICK0 +(-4.000000 6.000000 -1.500000) (-3.700000 8.300000 -1.500000) (-4.000000 8.000000 -1.500000) (5.629354 4.355081) (4.904248 4.449684) (4.998827 4.355081) BRICK0 +(0.000000 6.000000 -1.500000) (-0.300000 6.300000 -1.500000) (-3.700000 6.300000 -1.500000) (5.629354 5.616455) (5.534775 5.521852) (5.534775 4.449684) BRICK0 +(0.000000 6.000000 -1.500000) (-3.700000 6.300000 -1.500000) (-4.000000 6.000000 -1.500000) (5.629354 5.616455) (5.534775 4.449684) (5.629354 4.355081) BRICK0 +(-0.300000 8.300000 -1.500000) (-0.300000 6.300000 -1.500000) (0.000000 6.000000 -1.500000) (4.904248 5.521852) (5.534775 5.521852) (5.629354 5.616455) BRICK0 +(0.000000 6.000000 -1.500000) (0.000000 10.000000 -1.500000) (-0.300000 10.000000 -1.500000) (5.629354 5.616455) (4.368299 5.616455) (4.368299 5.521852) BRICK0 +(-0.300000 8.300000 -1.500000) (0.000000 6.000000 -1.500000) (-0.300000 10.000000 -1.500000) (4.904248 5.521852) (5.629354 5.616455) (4.368299 5.521852) BRICK0 +} +} +{ +"classname" "light" +"intensity" "4.0" +} +{ +"classname" "light" +"intensity" "4.0" +} diff --git a/funnyassets/raw_maps/test_map.map b/funnyassets/raw_maps/test_map.map new file mode 100644 index 0000000..25b3c97 --- /dev/null +++ b/funnyassets/raw_maps/test_map.map @@ -0,0 +1,11 @@ +{ + "classname" "worldspawn" + { + ( 0 0 0 ) ( 256 0 0 ) ( 256 256 0 ) ( 0 0 ) ( 1 0 ) ( 1 1 ) BRICK1 + } +} +{ + "classname" "light" + "origin" "128 128 96" + "light" "400" +} diff --git a/funnyassets/textures/bricks.png b/funnyassets/textures/bricks.png new file mode 100644 index 0000000..620b6b1 Binary files /dev/null and b/funnyassets/textures/bricks.png differ diff --git a/game/__build.c b/game/__build.c new file mode 100644 index 0000000..9415510 --- /dev/null +++ b/game/__build.c @@ -0,0 +1,41 @@ +#include "god/c.h" +#include "god/ld.h" + + +char* server_dll = 0; +void server_build(struct build_data b) +{ + char* files[] = { + "game/game.cpp", + "game/baseplayer.cpp", + NULL, + }; + struct C_Macro macros[] = { + (struct C_Macro){"TIER0_IMPLEMENTATION","1"}, + NULL, + }; + + + struct project p = { + .b = &b, + .files = files, + .name = "server", + }; + + struct project o = C_compile(p, (struct C_settings){ + .generation_flags = C_GENERATION_FLAGS_PIC, + .compile_flags = C_COMPILE_FLAGS_WALL, + .include_dirs = include_dirs, + .macros = macros, + }); + char* libs[] = { + "c", + NULL, + }; + + server_dll = ld_link_project(o, (struct link_settings){ + .type = LINK_TYPE_DYNAMIC, + .libs = libs, + }); + mv("build/"GAME_NAME"/game/"GAME_NAME"/bin/libserver.so",server_dll); +} diff --git a/game/baseplayer.cpp b/game/baseplayer.cpp new file mode 100644 index 0000000..34a087f --- /dev/null +++ b/game/baseplayer.cpp @@ -0,0 +1,32 @@ +#include "baseentity.h" + +class CBasePlayer: public CBaseEntity +{ +public: + virtual void Precache ( void ) override; + virtual void Spawn( void ) override; + virtual void Destroy( void ) override; + virtual void Think( float fDelta ) override; +}; + + +void CBasePlayer::Precache() +{ + +} + +void CBasePlayer::Spawn() +{ + +}; + +void CBasePlayer::Destroy() +{ + +} +void CBasePlayer::Think( float fDelta ) +{ + +}; + +DECLARE_ENTITY(player, CBasePlayer); diff --git a/game/game.cpp b/game/game.cpp new file mode 100644 index 0000000..ef0a776 --- /dev/null +++ b/game/game.cpp @@ -0,0 +1,11 @@ + +#include "tier0/platform.h" +#include "engine.h" +#include "level.h" + + +PLATFORM_INTERFACE void IGame_Load() +{ + ILevel::LoadLevel("maps/test_map"); + return; +}; diff --git a/launcher/__build.c b/launcher/__build.c new file mode 100644 index 0000000..83c4bb2 --- /dev/null +++ b/launcher/__build.c @@ -0,0 +1,35 @@ +#include "god/c.h" +#include "god/ld.h" +#include "god/utils.h" + +void launcher_build(struct build_data b) +{ + char* files[] = { + "launcher/launcher.cpp", + NULL, + }; + + + struct project p = { + .b = &b, + .files = files, + .name = "launcher", + }; + + struct project o = C_compile(p, (struct C_settings){ + .generation_flags = C_GENERATION_FLAGS_PIC, + .compile_flags = C_COMPILE_FLAGS_WALL, + .include_dirs = include_dirs, + }); + + char* libs[] = { + "c", + NULL, + }; + + char* launcher_dll = ld_link_project(o, (struct link_settings){ + .type = LINK_TYPE_EXECUTABLE, + .libs = libs, + }); + mv("build/"GAME_NAME"/game/bin/"GAME_NAME,launcher_dll); +} diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp new file mode 100644 index 0000000..3ecce0d --- /dev/null +++ b/launcher/launcher.cpp @@ -0,0 +1,46 @@ +#include "string.h" +#include "stdio.h" +#include "unistd.h" +#include "dlfcn.h" +#include "libgen.h" + +#define MAX_PATH 4096 + +static char szLauncherPath[MAX_PATH]; +static char szEnginePath[MAX_PATH]; +static char szTier0Path[MAX_PATH]; + +void *pEngineLib; +void *pTier0Lib; +typedef void (*EngineMainFn)(int argc, char** argv); +EngineMainFn pEngineMain; + +int main( int argc, char **argv ) { + readlink("/proc/self/exe",szLauncherPath, MAX_PATH); + dirname(szLauncherPath); + + snprintf(szEnginePath, MAX_PATH, "%s/libengine.so", szLauncherPath); + snprintf(szTier0Path, MAX_PATH, "%s/libtier0.so", szLauncherPath); + + pTier0Lib = dlopen(szTier0Path, RTLD_NOW | RTLD_GLOBAL); + if ( !pTier0Lib ) { + printf("Failed to open libtier0.so\n"); + printf("\t%s\n",dlerror()); + } + pEngineLib = dlopen(szEnginePath, RTLD_NOW | RTLD_GLOBAL); + if ( !pEngineLib ) { + printf("Failed to open libengine.so\n"); + printf("\t%s\n",dlerror()); + } + pEngineMain = (EngineMainFn)dlsym(pEngineLib, "FunnyMain"); + if ( !pEngineMain ) { + printf("Symbol not found: FunnyMain\n"); + } + + // chdir to right directory + dirname(szLauncherPath); + chdir(szLauncherPath); + + pEngineMain(argc, argv); + dlclose(pEngineLib); +}; \ No newline at end of file diff --git a/public/baseentity.h b/public/baseentity.h new file mode 100644 index 0000000..a0f5efd --- /dev/null +++ b/public/baseentity.h @@ -0,0 +1,87 @@ +#ifndef ENTITY_H +#define ENTITY_H + +#include "tier1/utlvector.h" + +class CBaseEntity; +class C_BaseEntity; + +struct Triangle_t +{ + float location[9]; + float uv[6]; + float normal[9]; + uint32_t texture; +}; + +/* server entities */ + +class CBaseEntity +{ +public: + C_BaseEntity *pClientEntity; + + virtual void Precache() = 0; + virtual void Spawn( void ) = 0; + virtual void Destroy( void ) = 0; + virtual void Think( float fDelta ) = 0; +}; + +extern CUtlSelfReferencingVector g_entities; + +typedef CBaseEntity*(*EntityRegistryFn)( void ); +typedef C_BaseEntity*(*ClientEntityRegistryFn)( void ); + +class CEntityRegistry +{ +public: + CEntityRegistry( const char *szName, const char *szClass, EntityRegistryFn pfn ); + + const char *m_szName; + const char *m_szClass; + EntityRegistryFn m_pfn; + ClientEntityRegistryFn m_pClientfn; +}; + +extern CUtlVector g_RegisteredEntities; + + +#define DECLARE_ENTITY(name, class) \ +CBaseEntity *__entity_alloc_##name() \ +{ \ + return new class; \ +}; \ +CEntityRegistry __entity_##name##_registry(#name, #class, __entity_alloc_##name); \ + +/* client entities */ + + +class C_BaseEntity +{ +public: + CBaseEntity *pEntity; + + virtual void Precache() = 0; + virtual void Spawn( void ) = 0; + virtual void Destroy( void ) = 0; + /* happens every frame instead of tick */ + virtual void Think( float fDelta ) = 0; +}; + +class C_EntityRegistry +{ +public: + C_EntityRegistry( const char *pName, ClientEntityRegistryFn pfn ); +}; + +#define LINK_CLIENT_ENTITY(client, server) \ +C_BaseEntity *__c_entity_alloc_##server() \ +{ \ + return new client; \ +}; \ +C_EntityRegistry __c_entity_##server##_registry(#server, __c_entity_alloc_##server); \ + + + + +#endif diff --git a/public/brush.h b/public/brush.h new file mode 100644 index 0000000..884a776 --- /dev/null +++ b/public/brush.h @@ -0,0 +1,34 @@ +#ifndef BRUSH_H +#define BRUSH_H + +#include "tier1/utlvector.h" +#include "rendering.h" +#include "baseentity.h" + +class CBrushEntity: public CBaseEntity +{ +public: + virtual void Precache ( void ) override; + virtual void Spawn( void ) override; + virtual void Destroy( void ) override; + virtual void Think( float fDelta ) override; + + CUtlVector m_mesh; +}; + +class C_BrushEntity: public C_BaseEntity +{ +public: + virtual void Precache ( void ) override; + virtual void Spawn( void ) override; + virtual void Destroy( void ) override; + virtual void Think( float fDelta ) override; +private: + IVertexBuffer *vertexBuffer; + IIndexBuffer *indexBuffer; + IBrush *mesh; + IMaterial material; + ITexture *pAlbedo; +}; + +#endif diff --git a/public/client.h b/public/client.h new file mode 100644 index 0000000..0c6c246 --- /dev/null +++ b/public/client.h @@ -0,0 +1,13 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include "tier0/platform.h" + +interface IClient +{ + void LoadGame( const char *psz ); + void Frame( float flDelta ); + void UnloadGame( const char *psz ); +}; + +#endif \ No newline at end of file diff --git a/public/console.h b/public/console.h new file mode 100644 index 0000000..ff7371e --- /dev/null +++ b/public/console.h @@ -0,0 +1,98 @@ +#ifndef CONSOLE_H +#define CONSOLE_H + +#include "tier0/platform.h" +#include "tier1/utlstring.h" + +class ConVar; +class ConCommand; + +typedef void(*ConCommandFn)(int argc, char **argv); + +interface IConsole +{ +public: + static void RegisterVar( ConVar *cvar ); + static void UnRegisterVar( ConVar *cvar ); + static ConVar *FindVar( const char *pName ); + + static void RegisterCommand( ConVar *cvar ); + static void UnRegisterCommand( ConVar *cvar ); + static ConCommand *FindCommand( const char *pName ); + + static void Execute( void ); + static void AddCommand( const char *psz ); + static void InsertCommand( const char *psz ); +}; + + +#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); +private: + char *m_szName; + char *m_szHelpString = NULL; + ConCommandFn m_callback; + + int m_flags; +}; + +void Msg( const char* message ); +void Warning( const char* message ); +void Error( const char* message ); + +#endif \ No newline at end of file diff --git a/public/engine.h b/public/engine.h new file mode 100644 index 0000000..d9ed617 --- /dev/null +++ b/public/engine.h @@ -0,0 +1,27 @@ +#ifndef ENGINE_H +#define ENGINE_H + +#include "tier0/platform.h" + +class CBaseEntity; + +interface IEngine +{ +public: + static void Init(); + static void Frame(float fDelta); + static void Shutdown(); +}; + + +interface IIEngine +{ +public: + static void PrecacheModel( const char *psz ); + static void PrecacheSound( const char *psz ); + + static CBaseEntity *SpawnEntity( const char *szName ); + static void DestroyEntity( CBaseEntity *pEntity ); +}; + +#endif diff --git a/public/fgui/fgui.h b/public/fgui/fgui.h new file mode 100644 index 0000000..4f6d236 --- /dev/null +++ b/public/fgui/fgui.h @@ -0,0 +1,27 @@ +#ifndef FGUI_H +#define FGUI_H + +#include "tier0/platform.h" + +abstract_class fgui +{ + struct Color_t + { + float r; + float g; + float b; + }; + + /* every position is resized to some degree of 1280x720 */ + struct Vector_t + { + float x; + float y; + }; + static void Init( void ); + static void Frame( void ); + static void Rectangle( Vector_t posPx, Vector_t posFl, Vector_t sizePx, Vector_t sizeFl ); + static void Text( const char *psz, uint32_t nSize, Vector_t pos, Vector_t color ); +}; + +#endif \ No newline at end of file diff --git a/public/filesystem.h b/public/filesystem.h new file mode 100644 index 0000000..6f1d9b6 --- /dev/null +++ b/public/filesystem.h @@ -0,0 +1,42 @@ +#ifndef FILESYSTEM_H +#define FILESYSTEM_H +#include "tier0/platform.h" +#include "tier1/utlbuffer.h" +#include "tier1/utlstring.h" + +enum EFileOptions +{ + IFILE_READ, + IFILE_WRITE, + IFILE_APPEND +}; + +typedef struct FileHandle_s +{ + FILE *file; + FILE *parent; + EFileOptions options; + size_t nSize; + size_t nOffset; + size_t nPtr; +} *FileHandle_t; + +interface IFileSystem +{ +public: + static void InitFilesystem( void ); + static void AddGameDirectory( const char *psz ); + static bool LoadPackFile( const char *szFilename ); + static void CreatePath( const char *szPath ); + static FileHandle_t Open( const char *szFilename, EFileOptions options ); + static void Close( FileHandle_t file ); + static size_t Size( FileHandle_t file ); + static size_t Read( FileHandle_t file, void *pOutput, size_t nSize); + static size_t ReadLine( FileHandle_t file, void *pOutput, size_t nSize); + static size_t Write( FileHandle_t file, void *pInput, size_t nSize); + static size_t Seek( FileHandle_t file, size_t nSize); + static size_t Tell( FileHandle_t file, size_t nSize); + static size_t fprintf( FileHandle_t file, const char *szFormat, ...); +}; + +#endif diff --git a/public/level.h b/public/level.h new file mode 100644 index 0000000..90b35f1 --- /dev/null +++ b/public/level.h @@ -0,0 +1,12 @@ +#ifndef LEVEL_H +#define LEVEL_H + +#include "tier0/platform.h" + +interface ILevel +{ +public: + static void LoadLevel( const char *szLevelName ); +}; + +#endif diff --git a/public/physics.h b/public/physics.h new file mode 100644 index 0000000..e69de29 diff --git a/public/rendering.h b/public/rendering.h new file mode 100644 index 0000000..77aadd2 --- /dev/null +++ b/public/rendering.h @@ -0,0 +1,116 @@ +#ifndef RENDERING_H +#define RENDERING_H + +#include "cglm/affine.h" +#include "cglm/cglm.h" +#include "tier0/platform.h" +#include "tier1/utlbuffer.h" +#include "baseentity.h" +#include "tier1/utlvector.h" + +interface IVideo +{ +public: + static void Init(); + static void Frame( float fDelta ); +}; + +abstract_class IVertexBuffer +{ +public: + virtual void *Map() = 0; + virtual void Unmap() = 0; +}; + +abstract_class IIndexBuffer +{ +public: + virtual void *Map() = 0; + virtual void Unmap() = 0; +}; + +abstract_class IBrush +{ +public: + virtual void SetPosition( vec3 position ) = 0; + virtual void SetRotationEuler( vec3 angle ) = 0; + virtual void SetRotationQuat( vec4 quaternion) = 0; + virtual void SetMatrix( mat3 matrix ) = 0; + virtual void SetScale( vec3 scale ) = 0; + + virtual void SetVertexBuffer( IVertexBuffer *pBuffer ) = 0; + virtual void SetIndexBuffer( IIndexBuffer *pBuffer ) = 0; + virtual void Draw() = 0; +}; + +enum EMaterialType +{ + IMATERIAL_ERROR = 0, + IMATERIAL_PBR = 1, + IMATERIAL_FULLBRIGHT = 2, +}; + +struct MaterialProperties_t +{ + + EMaterialType type; + + vec3 albedoColor; + + const char *szAlbedoTexture; + const char *szNormalsTexture; + const char *szRoughnessTexture; + const char *szMetalnessTexture; + + vec2 uvScaling; +}; + + +struct Material_t +{ + uint32_t shader; + uint32_t albedo; + uint32_t normal; + uint32_t roughness; + uint32_t metalness; + vec3 albedoColor; +}; + +abstract_class IMaterial +{ +public: + Material_t m; +}; + +interface IBrushRenderer +{ +public: + static void Init(); + static void Frame( float fDelta ); + + static IVertexBuffer *CreateVertexBuffer( uint32_t uSize ); + static IIndexBuffer *CreateIndexBuffer( uint32_t uSize ); + + static IBrush *CreateMesh(); + static void Destroy( IBrush *pModel ); + + static IMaterial *LoadMaterial( const char *szName ); + static void SetMaterial( IMaterial *pMaterial ); +}; + +abstract_class ITexture +{ +public: + const char *szName; + uint32_t id; +}; + +interface ITextureManager +{ +public: + static uint32_t GetTexture(ITexture *pTexture); + static ITexture *LoadTexture( void *pData, uint32_t X, uint32_t Y, uint32_t numChannels ); + static ITexture *LoadTexture( const char *szName ); +}; + +#endif diff --git a/public/server.h b/public/server.h new file mode 100644 index 0000000..293aba9 --- /dev/null +++ b/public/server.h @@ -0,0 +1,14 @@ +#ifndef SERVER_H +#define SERVER_H + +#include "tier0/platform.h" + +interface IServer +{ +public: + static void LoadGame( const char *psz ); + static void Think( float fDelta ); + static void UnloadGame( const char *psz ); +}; + +#endif \ No newline at end of file diff --git a/public/tier0/lib.h b/public/tier0/lib.h new file mode 100644 index 0000000..446a71a --- /dev/null +++ b/public/tier0/lib.h @@ -0,0 +1,96 @@ +#ifndef TIER0_STDLIB_H +#define TIER0_STDLIB_H + +#include "stdint.h" +#include "string.h" +#include "stdio.h" +#include "stdlib.h" + +// TODO: bad stuff, reimplement it + +//----------------------------------------------------------------------------- +// string.h +//----------------------------------------------------------------------------- +#define V_memcpy memcpy +#define V_memmove memmove +#define V_memchr memchr +#define V_memcmp memcmp +#define V_memset memset + +#define V_strcat strcat +#define V_strncat strncat +#define V_strchr strchr +#define V_strrchr strrchr +#define V_strcmp strcmp +#define V_strncmp strncmp +#define V_strcoll strcoll +#define V_strcpy strcpy +#define V_strncpy strncpy +#define V_strlen strlen +#define V_strnlen strnlen +#define V_strspn strspn +#define V_strcspn strcspn +#define V_strpbrk strpbrk +#define V_strstr strstr +#define V_strtok strtok +#define V_strxfrm strxfrm + +//----------------------------------------------------------------------------- +// stdio.h +//----------------------------------------------------------------------------- +#define V_fclose fclose +#define V_fopen fopen +#define V_freopen freopen +#define V_fdopen fdopen +#define V_remove remove +#define V_rename rename +#define V_rewind rewind +#define V_tmpfile tmpfile + +#define V_feof feof +#define V_ferror ferror +#define V_fflush fflush +#define V_fgetpos fgetpos +#define V_fgetc getc +#define V_fgets gets +#define V_fputc putc +#define V_fputs puts +#define V_ftell ftell +#define V_fseek fseek +#define V_fsetpos fsetpos +#define V_fread fread +#define V_fwrite fwrite +#define V_getc getc +#define V_getchar getchar +#define V_gets gets +#define V_printf printf +#define V_vprintf vprintf +#define V_fprintf fprintf +#define V_vfprintf vfprintf +#define V_sprintf sprintf +#define V_snprintf snprintf +#define V_vsprintf vsprintf +#define V_vsnprintf vsnprintf +#define V_perror perror +#define V_putc putc +#define V_putchar putchar +#define V_fputchar fputchar +#define V_scanf scanf +#define V_vscanf vscanf +#define V_fscanf fscanf +#define V_vfscanf vfscanf +#define V_vsscanf vsscanf +#define V_setbuf setbuf +#define V_setvbuf setvbuf +#define V_tmpnam tmpnam +#define V_ungetc ungetc +#define V_puts puts + + +//----------------------------------------------------------------------------- +// stdlib.h +//----------------------------------------------------------------------------- +#define V_atoi atoi +#define V_atof atof + +#endif diff --git a/public/tier0/mem.h b/public/tier0/mem.h new file mode 100644 index 0000000..973957a --- /dev/null +++ b/public/tier0/mem.h @@ -0,0 +1,10 @@ +#ifndef TIER0_MEM_H +#define TIER0_MEM_H + +#include "platform.h" +#include "lib.h" + +PLATFORM_INTERFACE void *V_malloc( int nSize ); +PLATFORM_INTERFACE void V_free( void *pMem ); +PLATFORM_INTERFACE void *V_realloc( void *pMem, int nSize ); +#endif \ No newline at end of file diff --git a/public/tier0/platform.h b/public/tier0/platform.h new file mode 100644 index 0000000..710fbd1 --- /dev/null +++ b/public/tier0/platform.h @@ -0,0 +1,51 @@ +#ifndef TIER0_PLATFORM_H +#define TIER0_PLATFORM_H + +#include "stdint.h" +#include "stddef.h" + +#define DLL_EXPORT extern "C" __attribute__ ((visibility("default"))) +#define DLL_IMPORT extern "C" + +#define DLL_CLASS_EXPORT __attribute__ ((visibility("default"))) +#define DLL_CLASS_IMPORT + +#define DLL_GLOBAL_EXPORT extern __attribute ((visibility("default"))) +#define DLL_GLOBAL_IMPORT extern + +#ifdef TIER0_STATIC + +#else + +#ifdef TIER0_IMPLEMENTATION +#define PLATFORM_INTERFACE DLL_EXPORT +#define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT +#define PLATFORM_CLASS DLL_CLASS_EXPORT +#else +#define PLATFORM_INTERFACE DLL_IMPORT +#define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT +#define PLATFORM_CLASS DLL_CLASS_IMPORT +#endif + +#endif + +#define interface class +#define abstract_class class + +PLATFORM_INTERFACE void Plat_FatalErrorFunc( const char *szFormat, ... ); + +typedef void( *ListDirCallbackFn )( const char *szPath ); +PLATFORM_INTERFACE void Plat_ListDirRecursive( const char *szPath, ListDirCallbackFn file, ListDirCallbackFn dir ); +PLATFORM_INTERFACE void Plat_ListDir( const char *szPath, ListDirCallbackFn file, ListDirCallbackFn dir ); +PLATFORM_INTERFACE char *Plat_GetExtension( const char *szPath ); +PLATFORM_INTERFACE void Plat_TrapSignals( void (*pfn)() ); +PLATFORM_INTERFACE void Plat_Backtrace( void ); + +PLATFORM_INTERFACE void *Plat_LoadLibrary( const char *psz ); +PLATFORM_INTERFACE void *Plat_GetProc( void *lib, const char *psz ); +PLATFORM_INTERFACE void Plat_UnloadLibrary( void *psz ); + +PLATFORM_INTERFACE double Plat_GetTime( void ); + + +#endif diff --git a/public/tier1/commandline.h b/public/tier1/commandline.h new file mode 100644 index 0000000..4e3773e --- /dev/null +++ b/public/tier1/commandline.h @@ -0,0 +1,17 @@ +#include "tier0/platform.h" + +interface ICommandLine +{ +public: + static void CreateCommandLine( int argc, char **argv ); + + static bool CheckParam( char *psz ); + static char *ParamValue( const char* psz ); + + static void AddParam( char *psz ); + static void RemoveParam( char *psz ); + + static int ParamCount(); + static int FindParam( const char *psz ); + static const char *GetParam(int nIndex); +}; \ No newline at end of file diff --git a/public/tier1/utlbuffer.h b/public/tier1/utlbuffer.h new file mode 100644 index 0000000..43c07e7 --- /dev/null +++ b/public/tier1/utlbuffer.h @@ -0,0 +1,350 @@ +#ifndef TIER1_UTL_BUFFER_H +#define TIER1_UTL_BUFFER_H + + +#include "tier0/mem.h" +#include "tier0/platform.h" +#include "tier0/lib.h" + +template +class CUtlBuffer; +template +class CUtlResizableBuffer; + +//----------------------------------------------------------------------------- +// This buffer contains static data allocated on heap. +//----------------------------------------------------------------------------- +template +class CUtlBuffer +{ +public: + CUtlBuffer( void ); + CUtlBuffer( size_t nSize ); + CUtlBuffer( const CUtlBuffer& buffer ); + CUtlBuffer( const CUtlResizableBuffer& buffer ); + + size_t GetSize( void ) const; + void* GetMemory(void) const; + + operator T*( void ) const; + T& operator []( const size_t nIndex ); + T operator []( const size_t nIndex ) const; + CUtlBuffer& operator=(const CUtlBuffer& other); +private: + T* m_pData; + size_t m_nSize; +}; + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlBuffer::CUtlBuffer() : m_nSize(0) +{ + m_pData = 0; +} + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlBuffer::CUtlBuffer( size_t nSize ) : m_nSize(nSize) +{ + if ( nSize == 0 ) + nSize = 1; + m_pData = (T*)V_malloc(sizeof(T)*nSize); + V_memset(m_pData, 0, sizeof(T)*nSize); +} + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlBuffer::CUtlBuffer( const CUtlBuffer& buffer ) : m_nSize(buffer.m_nSize) +{ + m_pData = (T*)V_malloc(sizeof(T)*buffer.m_nSize); + V_memcpy(m_pData,buffer.m_pData,sizeof(T)*buffer.m_nSize); +} + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlBuffer::CUtlBuffer( const CUtlResizableBuffer& buffer ) : m_nSize(buffer.m_nSize) +{ + m_pData = (T*)V_malloc(sizeof(T)*buffer.nSize); + V_memcpy(m_pData,buffer.pData,sizeof(T)*buffer.nSize); +} + +//----------------------------------------------------------------------------- +// Gets memory size. +//----------------------------------------------------------------------------- +template +size_t CUtlBuffer::GetSize( void ) const +{ + return m_nSize; +} + +//----------------------------------------------------------------------------- +// Gets memory address. +//----------------------------------------------------------------------------- +template +void* CUtlBuffer::GetMemory( void ) const +{ + return m_pData; +} + +//----------------------------------------------------------------------------- +// Gets memory address using casting. +//----------------------------------------------------------------------------- +template +CUtlBuffer::operator T*( void ) const +{ + return m_pData; +} + +//----------------------------------------------------------------------------- +// Indexes buffer for writing. +//----------------------------------------------------------------------------- +template +T& CUtlBuffer::operator []( const size_t nIndex ) +{ + if ( m_pData == 0) + Plat_FatalErrorFunc("Buffer was not initialized"); + + if ( nIndex >= m_nSize ) + Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu", m_nSize/sizeof(T), nIndex); + + return m_pData[nIndex]; +} + +//----------------------------------------------------------------------------- +// Indexes buffer for reading. +//----------------------------------------------------------------------------- +template +T CUtlBuffer::operator []( const size_t nIndex ) const +{ + if ( nIndex >= m_nSize ) + Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu",m_nSize, nIndex); + return m_pData[nIndex]; +} + +//----------------------------------------------------------------------------- +// Assigns buffer. +//----------------------------------------------------------------------------- +template +CUtlBuffer& CUtlBuffer::operator=(const CUtlBuffer& other) +{ + if ( this != &other ) + { + if ( m_pData != 0) + V_free(m_pData); + m_pData = (T*)V_malloc(sizeof(T)*other.m_nSize); + V_memcpy(m_pData, other.m_pData, sizeof(T)*other.m_nSize); + } + return this; +} + +//----------------------------------------------------------------------------- +// This buffer contains static data allocated on heap which can be resized. +//----------------------------------------------------------------------------- +template +class CUtlResizableBuffer +{ +public: + CUtlResizableBuffer( void ); + CUtlResizableBuffer( size_t nSize ); + CUtlResizableBuffer( const CUtlBuffer& buffer ); + CUtlResizableBuffer( const CUtlResizableBuffer& buffer ); + + size_t GetSize() const; + size_t GetRealSize() const; + void Resize( size_t nSize ); + void* GetMemory(void) const; + + operator T*( void ) const; + T& operator []( const size_t nIndex ); + T operator []( const size_t nIndex ) const; + CUtlResizableBuffer& operator=(const CUtlResizableBuffer& other); +private: + size_t CalculateMemorySize(size_t nSize); + T* m_pData; + size_t m_nSize; + size_t m_nAllocatedSize; +}; + + + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlResizableBuffer::CUtlResizableBuffer() : m_nSize(1) +{ + m_pData = (T*)V_malloc(1); + m_nAllocatedSize = 1; +} + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlResizableBuffer::CUtlResizableBuffer( size_t nSize ) : m_nSize(nSize) +{ + if ( nSize == 0 ) + nSize = 1; + size_t nAllocSize = CalculateMemorySize(sizeof(T)*nSize); + m_pData = (T*)V_malloc(nAllocSize); + m_nAllocatedSize = nAllocSize; + V_memset(m_pData, 0, sizeof(T)*nSize); +} + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlResizableBuffer::CUtlResizableBuffer( const CUtlBuffer& buffer ) : m_nSize(buffer.nSize) +{ + size_t nAllocSize = CalculateMemorySize(sizeof(T)*buffer.nSize); + m_pData = (T*)V_malloc(nAllocSize); + m_nAllocatedSize = nAllocSize; + V_memcpy(m_pData,buffer.m_pData,sizeof(T)*buffer.nSize); +} + +//----------------------------------------------------------------------------- +// Constructor. +//----------------------------------------------------------------------------- +template +CUtlResizableBuffer::CUtlResizableBuffer( const CUtlResizableBuffer& buffer ) : m_nSize(buffer.m_nSize) +{ + m_pData = (T*)V_malloc(sizeof(T)*buffer.m_nAllocatedSize); + m_nAllocatedSize = buffer.m_nAllocatedSize; + V_memcpy(m_pData,buffer.m_pData,sizeof(T)*buffer.m_nSize); +} + +//----------------------------------------------------------------------------- +// Gets memory size. +//----------------------------------------------------------------------------- +template +size_t CUtlResizableBuffer::GetSize( void ) const +{ + return m_nSize; +} + +//----------------------------------------------------------------------------- +// Gets memory size. +//----------------------------------------------------------------------------- +template +size_t CUtlResizableBuffer::GetRealSize( void ) const +{ + return m_nAllocatedSize; +} + +//----------------------------------------------------------------------------- +// Resizes memory. +//----------------------------------------------------------------------------- +template +void CUtlResizableBuffer::Resize( size_t nSize ) +{ + if ( nSize == 0 ) + nSize = 1; + + + if ( m_pData == 0 ) + m_pData = (T*)V_malloc(CalculateMemorySize(sizeof(T)*nSize)); + else + { + size_t nAllocSize = CalculateMemorySize(sizeof(T)*nSize); + if (nAllocSize!=m_nAllocatedSize) + { + // not ideal + T* pData = (T*)V_malloc(nAllocSize); + V_memcpy(pData, m_pData, m_nAllocatedSize>nAllocSize ? nAllocSize : m_nAllocatedSize ); + m_nAllocatedSize = nAllocSize; + V_free(m_pData); + m_pData = pData; + } + } + m_nSize = nSize; +} + +//----------------------------------------------------------------------------- +// Gets memory address. +//----------------------------------------------------------------------------- +template +void* CUtlResizableBuffer::GetMemory( void ) const +{ + return m_pData; +} + +//----------------------------------------------------------------------------- +// Gets memory address using casting. +//----------------------------------------------------------------------------- +template +CUtlResizableBuffer::operator T*( void ) const +{ + return m_pData; +} + +//----------------------------------------------------------------------------- +// Indexes buffer for writing. +//----------------------------------------------------------------------------- +template +T& CUtlResizableBuffer::operator []( const size_t nIndex ) +{ + if ( m_pData == 0) + Plat_FatalErrorFunc("Buffer was not initialized"); + + if ( nIndex >= m_nSize ) + Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu",m_nSize, nIndex); + + return m_pData[nIndex]; +} + +//----------------------------------------------------------------------------- +// Indexes buffer for reading. +//----------------------------------------------------------------------------- +template +T CUtlResizableBuffer::operator []( const size_t nIndex ) const +{ + if ( nIndex >= m_nSize ) + Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu",m_nSize, nIndex); + return m_pData[nIndex]; +} + +//----------------------------------------------------------------------------- +// Assigns buffer. +//----------------------------------------------------------------------------- +template +CUtlResizableBuffer& CUtlResizableBuffer::operator=(const CUtlResizableBuffer& other) +{ + if ( this != &other ) + { + V_free(m_pData); + m_pData = (T*)V_malloc(other.m_nAllocatedSize); + V_memcpy(m_pData, other.m_pData, sizeof(T)*other.m_nSize); + m_nAllocatedSize = other.m_nAllocatedSize; + m_nSize = other.m_nSize; + } + return *this; +} + +//----------------------------------------------------------------------------- +// Calculates memory size that is +//----------------------------------------------------------------------------- +template +size_t CUtlResizableBuffer::CalculateMemorySize(size_t nSize) +{ + size_t x = nSize; + if (x == 0) return 1; + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + return x + 1; +} + +#endif diff --git a/public/tier1/utlmap.h b/public/tier1/utlmap.h new file mode 100644 index 0000000..6b89f0f --- /dev/null +++ b/public/tier1/utlmap.h @@ -0,0 +1,6 @@ +#ifndef TIER1_UTL_STRING_H +#define TIER1_UTL_STRING_H + +#include "tier1/utlvector.h" + +#endif \ No newline at end of file diff --git a/public/tier1/utlstring.h b/public/tier1/utlstring.h new file mode 100644 index 0000000..d78d626 --- /dev/null +++ b/public/tier1/utlstring.h @@ -0,0 +1,30 @@ +#ifndef TIER1_UTL_STRING_H +#define TIER1_UTL_STRING_H + +#include "tier1/utlvector.h" + +class CUtlString { +public: + CUtlString( void ); + CUtlString( const char *psz, ... ); + + void AppendTail( const char *psz ); + void AppendHead( const char *psz ); + void AppendAt( size_t nPosition, const char *psz ); + + void RemoveTail( size_t nCount ); + void RemoveHead( size_t nCount ); + void RemoveAt( size_t nPosition, size_t nCount ); + + char *GetString( void ); + size_t GetLenght( void ); + operator char*( void ); + bool operator==(const char* psz); + bool operator!=(const char* psz); + bool operator==(CUtlString& string); + bool operator!=(CUtlString& string); +private: + CUtlVector m_data; +}; + +#endif \ No newline at end of file diff --git a/public/tier1/utlvector.h b/public/tier1/utlvector.h new file mode 100644 index 0000000..ac3c944 --- /dev/null +++ b/public/tier1/utlvector.h @@ -0,0 +1,323 @@ +#ifndef TIER1_UTL_VECTOR_H +#define TIER1_UTL_VECTOR_H + +#include "tier1/utlbuffer.h" +#include "tier0/lib.h" + + +//----------------------------------------------------------------------------- +// Basic vector implementation. There isn't much in them. +//----------------------------------------------------------------------------- +template +class CUtlVector +{ +public: + CUtlVector( void ); + CUtlVector( size_t nSize ); + + void AppendHead( const T &data ); + void AppendHead( const T *pData, size_t n ); + void AppendTail( const T &data ); + void AppendTail( const T *data, size_t n ); + void AppendAt( size_t nIndex, const T &data ); + void AppendAt( size_t nIndex, const T *data, size_t n ); + + void RemoveHead(); + void RemoveTail(); + void RemoveAt( size_t nIndex ); + + T *GetData( void ); + size_t GetSize( void ); + void Resize( size_t nSize ); + void Reserve( size_t nSize ); + + T &operator[]( size_t nIndex ); + T &operator[]( size_t nIndex ) const; + + // Iterator stuff + struct Iterator { + T *m_pCurrent; + Iterator( T *pCurrent ) : m_pCurrent(pCurrent) {} + T& operator*( void ) const { return *m_pCurrent;} + Iterator& operator++( void ) { + ++m_pCurrent; + return *this; + } + bool operator!=( const Iterator& other ) const + { + return m_pCurrent != other.m_pCurrent; + } + }; + + + Iterator begin( void ) const + { + return Iterator((T*)m_data.GetMemory()); + } + Iterator end( void ) const + { + return Iterator((T*)m_data.GetMemory()+m_nSize); + } + +private: + size_t m_nSize = 0; + CUtlResizableBuffer m_data; +}; + +//---------------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------------- +template +CUtlVector::CUtlVector( void ) +{ + m_data.Resize(0); +}; + +//---------------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------------- +template +CUtlVector::CUtlVector( size_t nSize ) +{ + m_data.Resize(nSize); + m_nSize = nSize; +}; + +template +void CUtlVector::AppendHead( const T &data ) +{ + AppendHead(&data,1); +} + +template +void CUtlVector::AppendHead( const T *pData, size_t n ) +{ + +} + +template +void CUtlVector::AppendTail( const T &data ) +{ + AppendTail(&data,1); +} + +template +void CUtlVector::AppendTail( const T *pData, size_t n ) +{ + m_data.Resize(m_data.GetSize()+n); + V_memcpy(m_data+m_nSize,pData,sizeof(T)*n); + m_nSize+=n; +} + +template +void CUtlVector::AppendAt( size_t nIndex, const T &data ) +{ + AppendAt(nIndex, &data, 1); +} + +template +void CUtlVector::AppendAt( size_t nIndex, const T *pData, size_t n ) +{ + +} + +template +void CUtlVector::RemoveHead() +{ + m_nSize--; +} +template +void CUtlVector::RemoveTail() +{ + m_nSize--; +} +template +void CUtlVector::RemoveAt( size_t nIndex ) +{ + m_nSize--; +} + +template +T *CUtlVector::GetData( void ) +{ + return (T*)m_data.GetMemory(); +} + +template +size_t CUtlVector::GetSize( void ) +{ + return m_nSize; +} + +template +void CUtlVector::Resize( size_t nSize ) +{ + m_nSize = nSize; +} +template +void CUtlVector::Reserve( size_t nSize ) +{ + m_data.Resize(nSize); +} + +template +T &CUtlVector::operator[]( size_t nIndex ) +{ + return m_data[nIndex]; +} + +template +T &CUtlVector::operator[]( size_t nIndex ) const +{ + return m_data[nIndex]; +} + + +//----------------------------------------------------------------------------- +// Self referencing arrays are quite cool. +// They allow to append stuff in head and tail of the array and use less memory +// copying. Downside is their indexing is O(n/2) +// +// Implements the same stuff as CUtlVector does. +//----------------------------------------------------------------------------- +template +class CUtlSelfReferencingVector +{ +private: + template + struct SelfData_t; +public: + CUtlSelfReferencingVector(); + ~CUtlSelfReferencingVector(); + + void AppendHead( const T& data ); + void AppendTail( const T& data ); + void AppendAt( size_t nIndex, const T& data ); + + void RemoveHead( void ); + void RemoveTail( void ); + void RemoveAt( size_t nIndex ); + + size_t GetSize(); + + T operator[]( size_t nIndex ); + T& operator[]( size_t nIndex ) const; + + + // Iterator stuff + struct Iterator { + SelfData_t *m_pCurrent; + Iterator( SelfData_t *pCurrent ) : m_pCurrent(pCurrent) {} + T& operator*( void ) const { return m_pCurrent->data;} + Iterator& operator++( void ) { + if (m_pCurrent) m_pCurrent = m_pCurrent->pNext; + return *this; + } + bool operator!=( const Iterator& other ) const + { + return m_pCurrent != other.m_pCurrent; + } + }; + + Iterator begin( void ) const + { + return Iterator(m_pHead); + } + Iterator end( void ) const + { + return Iterator(NULL); + } + +private: + size_t m_nSize = 0; + + template + struct SelfData_t + { + SelfData_t *pNext = NULL; + SelfData_t *pPrev = NULL; + A data; + }; + SelfData_t *m_pTail = NULL; + SelfData_t *m_pHead = NULL; +}; + + +//---------------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------------- +template +CUtlSelfReferencingVector::CUtlSelfReferencingVector() +{ + +}; + +//---------------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------------- +template +CUtlSelfReferencingVector::~CUtlSelfReferencingVector() +{ + SelfData_t *pNext = NULL; + for (SelfData_t *pCurrent = m_pHead; pCurrent; pCurrent=pNext) + { + pNext = pCurrent->pNext; + delete pCurrent; + } +}; + +//---------------------------------------------------------------------------- +// Inserts new element in the start of the vector. +//---------------------------------------------------------------------------- +template +void CUtlSelfReferencingVector::AppendHead( const T& data ) +{ + SelfData_t* pData = new SelfData_t; + pData->data = data; + pData->pNext = m_pHead; + if (m_pHead) + m_pHead->pPrev = pData; + pData->pPrev = 0; + m_pHead = pData; + if (m_pTail == 0) + m_pTail = m_pHead; + m_nSize++; +}; + +//---------------------------------------------------------------------------- +// Inserts new element in the end of the vector. +//---------------------------------------------------------------------------- +template +void CUtlSelfReferencingVector::AppendTail( const T& data ) +{ + SelfData_t* pData = new SelfData_t; + pData->data = data; + if (m_pTail) + m_pTail->pNext = pData; + pData->pPrev = m_pTail; + m_pTail = pData; + if (m_pHead == 0) + m_pHead = m_pTail; + + m_nSize++; +}; + +//---------------------------------------------------------------------------- +// Removes element in the start of the vector. +//---------------------------------------------------------------------------- +template +void CUtlSelfReferencingVector::RemoveHead( void ) +{ + if (m_pHead == m_pTail) + m_pHead = 0; +}; +//---------------------------------------------------------------------------- +// Removes element in the end of the vector. +//---------------------------------------------------------------------------- +template +void CUtlSelfReferencingVector::RemoveTail( void ) +{ + +} + +#endif \ No newline at end of file diff --git a/public/vk_video.h b/public/vk_video.h new file mode 100644 index 0000000..f52cd93 --- /dev/null +++ b/public/vk_video.h @@ -0,0 +1,95 @@ +#ifndef VK_VIDEO_H +#define VK_VIDEO_H + +#include "rendering.h" +#include "tier0/platform.h" +#include "tier1/utlvector.h" +#include "vulkan/vulkan.h" +#include "vulkan/vulkan_core.h" + +#ifndef VULKAN_RENDERING_IMPL +#error "Not a vulkan rendering implementation. Do not use this file!" +#endif + +#include "vk_mem_alloc.h" + +struct vk_framedata_t { + VkSemaphore draw; + VkSemaphore present; + VkFence fence; +}; + +struct vk_shader_t +{ + void Create( const char *szPath, VkShaderStageFlagBits shaderStage ); + void Create( CUtlBuffer &spirv, VkShaderStageFlagBits shaderStage ); + void Destroy( void ); + + VkShaderModule m_shaderModule = NULL; + VkPipelineShaderStageCreateInfo m_stageCreateInfo; +}; + +struct vk_tripipeline_t +{ + void Create( + CUtlVector &shaders, + CUtlVector &bindings, + uint32_t pushConstantsSize + /* the rest of the stuff is set by the dynamic state */ + /* literally */ + ); + void Destroy(); + CUtlVector m_shaders; + VkDescriptorSetLayout m_descriptorSetLayout; + VkPipelineLayout m_layout; + VkPipeline m_pipeline; +}; + +struct vk_comppipeline_t +{ + +}; + +struct vk_buffer_t +{ + void Create(size_t size, VkBufferUsageFlags usage); + void Destroy(); + void *Map(size_t offset, size_t size); + void Unmap(); + + void CopyTo(struct vk_image2d_t *image); + void CopyTo(struct vk_buffer_t *buffer); + + + size_t m_nSize; + VkBuffer m_buffer; + VmaAllocation m_memory; + VkDeviceAddress m_address; +}; + +struct vk_image2d_t +{ + void Create(size_t x, size_t y, VkFormat format, VkImageUsageFlags usage); + void Destroy(); + + void CopyTo(struct vk_image2d_t *image); + void CopyTo(struct vk_buffer_t *buffer); + + + uint32_t m_X; + uint32_t m_Y; + VkFormat m_format; + VkImage m_image; + VkImageView m_imageView; + VmaAllocation m_memory; +}; + +interface IVulkan +{ +public: + static void Init(); + static void Frame(); + static void Deinit(); +}; + +#endif diff --git a/public/window.h b/public/window.h new file mode 100644 index 0000000..e69de29 diff --git a/tier0/__build.c b/tier0/__build.c new file mode 100644 index 0000000..a52e972 --- /dev/null +++ b/tier0/__build.c @@ -0,0 +1,41 @@ +#include "god/c.h" +#include "god/ld.h" + +char* tier0_dll = 0; +void tier0_build(struct build_data b) +{ + char* files[] = { + "tier0/mem.cpp", + "tier0/platform.cpp", + "tier0/lib.cpp", + NULL, + }; + struct C_Macro macros[] = { + (struct C_Macro){"TIER0_IMPLEMENTATION","1"}, + NULL, + }; + + + struct project p = { + .b = &b, + .files = files, + .name = "tier0", + }; + + struct project o = C_compile(p, (struct C_settings){ + .generation_flags = C_GENERATION_FLAGS_PIC, + .compile_flags = C_COMPILE_FLAGS_WALL, + .include_dirs = include_dirs, + .macros = macros, + }); + char* libs[] = { + "c", + NULL, + }; + + tier0_dll = ld_link_project(o, (struct link_settings){ + .type = LINK_TYPE_DYNAMIC, + .libs = libs, + }); + mv("build/"GAME_NAME"/game/bin/libtier0.so",tier0_dll); +} \ No newline at end of file diff --git a/tier0/lib.cpp b/tier0/lib.cpp new file mode 100644 index 0000000..e69de29 diff --git a/tier0/mem.cpp b/tier0/mem.cpp new file mode 100644 index 0000000..5c5b8fa --- /dev/null +++ b/tier0/mem.cpp @@ -0,0 +1,21 @@ +#include "tier0/mem.h" +#include "stdlib.h" + +//----------------------------------------------------------------------------- +// These functions copy over libc memory functions +//----------------------------------------------------------------------------- + +void* V_malloc(int nSize) +{ + return malloc(nSize); +} + +void V_free(void *pMem) +{ + return free(pMem); +} + +void* V_realloc(void *pMem, int nSize) +{ + return realloc(pMem, nSize); +} diff --git a/tier0/platform.cpp b/tier0/platform.cpp new file mode 100644 index 0000000..d9caf61 --- /dev/null +++ b/tier0/platform.cpp @@ -0,0 +1,118 @@ +#include "tier0/platform.h" +#include "tier0/lib.h" +#include "stdarg.h" +#include "unistd.h" +#include "sys/stat.h" +#include "execinfo.h" +#include "dirent.h" +#include "dlfcn.h" +#include "time.h" + +PLATFORM_INTERFACE void Plat_FatalErrorFunc(const char* szFormat, ...) +{ + va_list list; + va_start(list, szFormat); + V_vprintf(szFormat, list); + va_end(list); + fflush(stdout); + _exit(1); +} + +PLATFORM_INTERFACE void Plat_ListDirRecursive(const char* szPath, ListDirCallbackFn file, ListDirCallbackFn dir) +{ + struct dirent *entry; + DIR *dp = opendir(szPath); + + if (!dp) { + return; + } + + while ((entry = readdir(dp)) != NULL) { + char full_path[1024]; + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + snprintf(full_path, sizeof(full_path), "%s/%s", szPath, entry->d_name); + + struct stat statbuf; + if (stat(full_path, &statbuf) == -1) { + continue; + } + + if (S_ISDIR(statbuf.st_mode)) { + if (dir) + dir(full_path); + Plat_ListDirRecursive(full_path, file, dir); + } else { + if (file) + file(full_path); + } + } + + closedir(dp); +} +PLATFORM_INTERFACE void Plat_ListDir(const char* szPath, ListDirCallbackFn file, ListDirCallbackFn dir) +{ + +} + +PLATFORM_INTERFACE char *Plat_GetExtension( const char *szPath ) +{ + char *last = (char*)szPath + V_strlen(szPath) - 1; + while (last != szPath) + { + if (*last=='.') + { + break; + }; + if (*last=='/') + { + return 0; + } + last--; + } + return last+1; +} + +PLATFORM_INTERFACE void Plat_Backtrace( void ) +{ + void *buffer[64]; + int nptrs = backtrace(buffer, 64); + char **symbols = backtrace_symbols(buffer, nptrs); + + if (symbols == NULL) { + V_printf("Backtrace failed\n"); + exit(EXIT_FAILURE); + } + + for (int i = 0; i < nptrs; i++) { + V_printf(" [%d] %s\n", i, symbols[i]); + } + + free(symbols); +}; + +PLATFORM_INTERFACE void *Plat_LoadLibrary( const char *psz ) +{ + void *lib = dlopen(psz, RTLD_GLOBAL | RTLD_NOW); + if (!lib) + V_printf("Failed to open %s\n\t%s\n", psz, dlerror()); + return lib; +} +PLATFORM_INTERFACE void *Plat_GetProc( void *lib, const char *psz ) +{ + return dlsym(lib, psz); +} +PLATFORM_INTERFACE void Plat_UnloadLibrary( void *lib ) +{ + dlclose(lib); +}; + +PLATFORM_INTERFACE double Plat_GetTime( void ) +{ + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC, &tp); + static time_t s_starttime = tp.tv_sec; + + return (tp.tv_sec-s_starttime)+tp.tv_nsec/1e9; +} diff --git a/tier1/__build.c b/tier1/__build.c new file mode 100644 index 0000000..a39dcfa --- /dev/null +++ b/tier1/__build.c @@ -0,0 +1,42 @@ +#include "god/c.h" +#include "god/ld.h" + +char* tier1_lib = 0; +void tier1_build(struct build_data b) +{ + char* files[] = { + "tier1/commandline.cpp", + "tier1/utlbuffer.cpp", + "tier1/utlmap.cpp", + "tier1/utlstring.cpp", + "tier1/utlvector.cpp", + NULL, + }; + struct C_Macro macros[] = { + (struct C_Macro){"TIER0_IMPLEMENTATION","1"}, + NULL, + }; + + + struct project p = { + .b = &b, + .files = files, + .name = "tier1", + }; + + struct project o = C_compile(p, (struct C_settings){ + .generation_flags = C_GENERATION_FLAGS_PIC, + .compile_flags = C_COMPILE_FLAGS_WALL, + .include_dirs = include_dirs, + .macros = macros, + }); + char* libs[] = { + "c", + NULL, + }; + + tier1_lib = ld_link_project(o, (struct link_settings){ + .type = LINK_TYPE_STATIC, + .libs = libs, + }); +} \ No newline at end of file diff --git a/tier1/commandline.cpp b/tier1/commandline.cpp new file mode 100644 index 0000000..55b917d --- /dev/null +++ b/tier1/commandline.cpp @@ -0,0 +1,61 @@ +#include "tier1/commandline.h" +#include "tier1/utlvector.h" + +CUtlVector cl_params; + +void ICommandLine::CreateCommandLine( int argc, char **argv ) +{ + cl_params.AppendTail(argv,argc); +} + +bool ICommandLine::CheckParam( char *psz ) +{ + for (auto szParam: cl_params) { + V_printf("%s\n",szParam); + } + return false; +} + +char *ICommandLine::ParamValue( const char *psz ) +{ + int i = 0; + for (auto szParam: cl_params) { + i++; + if (i>=cl_params.GetSize()) + { + return 0; + } + if (!V_strcmp(szParam, psz)) + return cl_params[i]; + } + return 0; +} + +void ICommandLine::AddParam( char *psz ) +{ +} + +void ICommandLine::RemoveParam( char *psz ) +{ + +} +int ICommandLine::ParamCount() +{ + return cl_params.GetSize(); +} +int ICommandLine::FindParam( const char *psz ) +{ + int i = 0; + for (auto szParam: cl_params) { + if (!V_strcmp(szParam, psz)) + return i; + i++; + } + return 0; +} +const char *ICommandLine::GetParam(int nIndex) +{ + return cl_params[nIndex]; +} + +static ICommandLine g_CommandLine; \ No newline at end of file diff --git a/tier1/utlbuffer.cpp b/tier1/utlbuffer.cpp new file mode 100644 index 0000000..4c24633 --- /dev/null +++ b/tier1/utlbuffer.cpp @@ -0,0 +1 @@ +#include "tier1/utlbuffer.h" \ No newline at end of file diff --git a/tier1/utlmap.cpp b/tier1/utlmap.cpp new file mode 100644 index 0000000..64d632c --- /dev/null +++ b/tier1/utlmap.cpp @@ -0,0 +1 @@ +#include "tier1/utlmap.h" \ No newline at end of file diff --git a/tier1/utlstring.cpp b/tier1/utlstring.cpp new file mode 100644 index 0000000..3ff4a21 --- /dev/null +++ b/tier1/utlstring.cpp @@ -0,0 +1,96 @@ +#include "tier1/utlstring.h" +#include "tier0/lib.h" +#include "stdarg.h" +CUtlString::CUtlString( void ) +{ + m_data.Reserve(1); + m_data[0]=0; +} + +CUtlString::CUtlString( const char *szFormat, ... ) +{ + if (szFormat == 0) + { + m_data.Reserve(1); + m_data[0]=0; + return; + } + va_list vlArgs; + va_start(vlArgs, szFormat); + va_list vlArgs2; + va_copy(vlArgs2, vlArgs); + size_t nSize = V_vsnprintf(NULL, 0, szFormat, vlArgs2); + m_data.Reserve(nSize + 1); + va_end(vlArgs2); + V_vsnprintf(m_data.GetData(), nSize + 1, szFormat, vlArgs); + m_data.Resize(nSize); + va_end(vlArgs); +} + +void CUtlString::AppendTail( const char *psz ) +{ + m_data.AppendTail(psz,V_strlen(psz)); + m_data.Reserve(m_data.GetSize()+1); + m_data[m_data.GetSize()] = 0; +} +void CUtlString::AppendHead( const char *psz ) +{ + +} +void CUtlString::AppendAt( size_t nPosition, const char *psz ) +{ + +} + +void CUtlString::RemoveTail( size_t nCount ) +{ + +} +void CUtlString::RemoveHead( size_t nCount ) +{ + +} +void CUtlString::RemoveAt( size_t nPosition, size_t nCount ) +{ + +} + +char *CUtlString::GetString( void ) +{ + return m_data.GetData(); +} + +CUtlString::operator char*( void ) +{ + return GetString(); +} + +bool CUtlString::operator==(const char* psz) +{ + if (psz==0) + psz = ""; + if (!V_strcmp(GetString(), psz)) + return true; + return false; +} +bool CUtlString::operator!=(const char* psz) +{ + if (psz==0) + psz = ""; + if (!V_strcmp(GetString(), psz)) + return false; + return true; +} + +bool CUtlString::operator==(CUtlString& string) +{ + if (!V_strcmp(GetString(), string.GetString())) + return true; + return false; +} +bool CUtlString::operator!=(CUtlString& string) +{ + if (!V_strcmp(GetString(), string.GetString())) + return false; + return true; +} diff --git a/tier1/utlvector.cpp b/tier1/utlvector.cpp new file mode 100644 index 0000000..5af842f --- /dev/null +++ b/tier1/utlvector.cpp @@ -0,0 +1 @@ +#include "tier1/utlvector.h" \ No newline at end of file diff --git a/tools/blender_mapping.py b/tools/blender_mapping.py new file mode 100644 index 0000000..38fbe86 --- /dev/null +++ b/tools/blender_mapping.py @@ -0,0 +1,80 @@ +import bpy +import os + +bl_info = { + "name": "Funnymap export", + "author": "kotofyt", + "version": (1, 0), + "blender": (4, 3, 0), + "location": "File > Export > Funnymap (.map)", + "description": "Export meshes as funnymaps", + "category": "Import-Export", + } + + +import bpy +import os +from bpy_extras.io_utils import ExportHelper +from bpy.types import Operator +from bpy.props import StringProperty + +class ExportFunnymap(Operator, ExportHelper): + """Export to Funnymap""" + bl_idname = "export_scene.fmap" + bl_label = "Export Funnymap" + filename_ext = ".map" + + filter_glob: StringProperty( + default="*.map", + options={'HIDDEN'}, + ) + + def execute(self, context): + return export_my_format(self.filepath) + +def export_my_format(filepath): + with open(filepath, 'w') as f: + f.write("{\n") + f.write("\"classname\" \"worldspawn\"\n") + f.write("{\n") + + for obj in bpy.context.scene.objects: + if obj.type == 'MESH': + mesh = obj.to_mesh() + mesh.calc_loop_triangles() + uv_layer = mesh.uv_layers.active.data if mesh.uv_layers.active else None + for tri in mesh.loop_triangles: + for loop_index in tri.loops: + vert = mesh.vertices[mesh.loops[loop_index].vertex_index] + world_pos = obj.matrix_world @ vert.co + f.write(f"({world_pos.x:.6f} {world_pos.y:.6f} {world_pos.z:.6f}) ") + for loop_index in tri.loops: + if uv_layer: + uv = uv_layer[loop_index].uv + f.write(f"({uv.x:.6f} {uv.y:.6f}) ") + f.write(f"BRICK0\n"); + f.write("}\n") + f.write("}\n") + for obj in bpy.context.scene.objects: + if obj.type == 'LIGHT': + light = obj.data + f.write("{\n") + f.write("\"classname\" \"light\"\n") + f.write(f"\"intensity\" \"{light.energy/128}\"\n") + f.write("}\n") + + return {'FINISHED'} + +def menu_func_export(self, context): + self.layout.operator(ExportFunnymap.bl_idname, text="Funnymap (.map)") + +def register(): + bpy.utils.register_class(ExportFunnymap) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) + +def unregister(): + bpy.utils.unregister_class(ExportFunnymap) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) + +if __name__ == "__main__": + register() diff --git a/tools/makepak64.py b/tools/makepak64.py new file mode 100644 index 0000000..4da0cbb --- /dev/null +++ b/tools/makepak64.py @@ -0,0 +1,53 @@ +# +# Copyright (C) 2013 The Tome of Preach +# Copyright (C) 2025 kotofyt +# +# This script implement generator of 64 bit version of pak. +# Basically all size 32 bit offsets and sizes replaced with 64 bit values +# +# Original source code is available at https://tomeofpreach.wordpress.com/2013/06/22/makepak-py/ +# + +import sys +import struct +import os + +#dummy class for stuffing the file headers into +class FileEntry: + pass + +#arguments are source directory, then target filename e.g. "pak1.pak" +rootdir = sys.argv[1] +pakfilename = sys.argv[2] + +pakfile = open(pakfilename,"wb") + +#write a dummy header to start with +pakfile.write(struct.Struct("<8s2q").pack(b"rttpacku",0,0)) + +#walk the directory recursively, add the files and record the file entries +offset = 24 +fileentries = [] +for root, subFolders, files in os.walk(rootdir): + for file in files: + entry = FileEntry() + impfilename = os.path.join(root,file) + entry.filename = os.path.relpath(impfilename,rootdir).replace("\\","/") + with open(impfilename, "rb") as importfile: + pakfile.write(importfile.read()) + entry.offset = offset + entry.length = importfile.tell() + offset = offset + entry.length + fileentries.append(entry) +tablesize = 0 + +#after all the file data, write the list of entries +for entry in fileentries: + pakfile.write(struct.Struct("<56s").pack(entry.filename.encode("ascii"))) + pakfile.write(struct.Struct("