no engine anymore
This commit is contained in:
@@ -5,37 +5,16 @@
|
||||
#include "tier1/commandline.h"
|
||||
|
||||
CUtlVector<CUtlString> engine_CompiledFiles = {
|
||||
"engine/interface.cpp",
|
||||
"engine/console.cpp",
|
||||
"engine/filesystem.cpp",
|
||||
"engine/server.cpp",
|
||||
"engine/engine.cpp",
|
||||
"engine/physics.cpp",
|
||||
"engine/gamemode.cpp",
|
||||
"engine/rendering.cpp",
|
||||
|
||||
/* io */
|
||||
"engine/input.cpp",
|
||||
"engine/networking.cpp",
|
||||
|
||||
/* audio */
|
||||
"engine/ma_audio.cpp",
|
||||
|
||||
"engine/mesh.cpp",
|
||||
|
||||
/* entities */
|
||||
"engine/baseentity.cpp",
|
||||
"engine/level.cpp",
|
||||
"engine/brush.cpp",
|
||||
/* server entities */
|
||||
"engine/sv_worldspawn.cpp",
|
||||
"engine/sv_light.cpp",
|
||||
"engine/sv_playerstart.cpp",
|
||||
|
||||
/* client entities */
|
||||
"engine/cl_worldspawn.cpp",
|
||||
"engine/cl_light.cpp",
|
||||
|
||||
"engine/engine.cpp",
|
||||
"engine/cvar.cpp",
|
||||
"engine/filesystem.cpp",
|
||||
"engine/filesystem_pak.cpp",
|
||||
"engine/filesystem_libc.cpp",
|
||||
|
||||
"engine/gamewindow_sdl.cpp",
|
||||
|
||||
"engine/sv_dll.cpp",
|
||||
"engine/cl_dll.cpp",
|
||||
};
|
||||
|
||||
CUtlVector<CUtlString> engine_Libraries = {
|
||||
@@ -43,56 +22,39 @@ CUtlVector<CUtlString> engine_Libraries = {
|
||||
"SDL3",
|
||||
};
|
||||
|
||||
int engine_build()
|
||||
{
|
||||
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS || Target_t::DefaultTarget().kernel == TARGET_KERNEL_DARWIN)
|
||||
{
|
||||
engine_CompiledFiles.AppendTail("engine/ml_videosdl.cpp");
|
||||
engine_CompiledFiles.AppendTail("engine/ml_video.cpp");
|
||||
engine_CompiledFiles.AppendTail("engine/ml_video.mm");
|
||||
} else {
|
||||
engine_CompiledFiles.AppendTail("engine/vk_videosdl.cpp");
|
||||
engine_CompiledFiles.AppendTail("engine/vk_video.cpp");
|
||||
}
|
||||
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_LINUX)
|
||||
{
|
||||
engine_Libraries.AppendTail("vulkan");
|
||||
}
|
||||
CCProject compileProject = {};
|
||||
CLDProject ldProject = {};
|
||||
DECLARE_BUILD_STAGE(engine)
|
||||
{
|
||||
CProject_t compileProject = {};
|
||||
LinkProject_t ldProject = {};
|
||||
|
||||
compileProject.m_szName = "engine";
|
||||
compileProject.files = engine_CompiledFiles;
|
||||
compileProject.includeDirectories = all_IncludeDirectories;
|
||||
compileProject.bFPIC = true;
|
||||
if (bStaticBuild)
|
||||
compileProject.macros.AppendTail((C_Macro_t){"STATIC_BUILD","1"});
|
||||
if (bSteam)
|
||||
compileProject.macros.AppendTail((C_Macro_t){"STEAM_ENABLED","1"});
|
||||
ldProject = compileProject.Compile();
|
||||
ldProject.libraries = engine_Libraries;
|
||||
ldProject = ccompiler->Compile(&compileProject);
|
||||
|
||||
if (bStaticBuild)
|
||||
ldProject.linkType = ELINK_STATIC_LIBRARY;
|
||||
else
|
||||
{
|
||||
ldProject.objects.AppendTail((CObject){tier1_lib});
|
||||
ldProject.objects.AppendTail((CObject){fgui_lib});
|
||||
ldProject.objects.AppendTail((CObject){rapier_lib});
|
||||
ldProject.objects.AppendTail((Object_t){tier1_lib});
|
||||
ldProject.objects.AppendTail((Object_t){rapier_lib});
|
||||
if (bSteam)
|
||||
ldProject.objects.AppendTail((CObject){steam_lib});
|
||||
ldProject.objects.AppendTail((Object_t){steam_lib});
|
||||
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
||||
}
|
||||
|
||||
CUtlString outputProject = ldProject.Link();
|
||||
|
||||
ldProject.libraries = engine_Libraries;
|
||||
CUtlString outputProject = linker->Link(&ldProject);
|
||||
|
||||
if (!bStaticBuild)
|
||||
{
|
||||
IFileSystem2::MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
|
||||
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), outputProject);
|
||||
filesystem2->MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
|
||||
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), outputProject);
|
||||
} else {
|
||||
engine_lib = outputProject;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
DECLARE_BUILD_STAGE(engine, engine_build);
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#include "baseentity.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/utlstring.h"
|
||||
|
||||
CBaseEntity::CBaseEntity()
|
||||
{
|
||||
glm_mat3_identity(m_matrix);
|
||||
glm_vec3_zero(m_position);
|
||||
glm_vec3_zero(m_scale);
|
||||
};
|
||||
void CBaseEntity::ReadParameter( const char *szName, const char *szValue )
|
||||
{
|
||||
CUtlString name = szName;
|
||||
if (name == "origin")
|
||||
V_sscanf(szValue, "%f %f %f", &m_position[0], &m_position[1], &m_position[2]);
|
||||
}
|
||||
|
||||
void CBaseEntity::SetPosition( vec3 position )
|
||||
{
|
||||
V_memcpy(m_position, position, sizeof(vec3));
|
||||
}
|
||||
|
||||
void CBaseEntity::SetRotationEuler( vec3 euler )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CBaseEntity::SetRotationQuat( vec4 quaternion )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CBaseEntity::SetRotationMatrix( mat3 matrix )
|
||||
{
|
||||
V_memcpy(m_matrix, matrix, sizeof(mat3));
|
||||
}
|
||||
|
||||
void CBaseEntity::SetScale( vec3 scale )
|
||||
{
|
||||
V_memcpy(m_scale, scale, sizeof(vec3));
|
||||
}
|
||||
|
||||
class CEntityManager: public IEntityManager
|
||||
{
|
||||
public:
|
||||
virtual void Init() override {}
|
||||
virtual void Frame() override {}
|
||||
virtual void Deinit() override {}
|
||||
};
|
||||
|
||||
DECLARE_ENGINE_INTERFACE(EntityManager, CEntityManager);
|
||||
|
||||
CEntityRegistryObject::CEntityRegistryObject(const char *szName, const char *szClass, EntityRegistryFn pfn) :
|
||||
m_szName(szName), m_szClass(szClass), m_pfn(pfn), m_pClientfn(0)
|
||||
{
|
||||
for (auto &entity: EntityManager()->m_RegisteredEntities)
|
||||
{
|
||||
if (!V_strcmp(entity->m_szClass, szClass))
|
||||
{
|
||||
entity->m_szName = szName;
|
||||
entity->m_pfn = pfn;
|
||||
return;
|
||||
}
|
||||
}
|
||||
EntityManager()->m_RegisteredEntities.AppendTail(this);
|
||||
};
|
||||
|
||||
|
||||
C_EntityRegistry::C_EntityRegistry( const char *szName, ClientEntityRegistryFn pfn )
|
||||
{
|
||||
for (auto &entity: EntityManager()->m_RegisteredEntities)
|
||||
{
|
||||
if (!V_strcmp(entity->m_szClass, szName))
|
||||
{
|
||||
entity->m_pClientfn = pfn;
|
||||
return;
|
||||
}
|
||||
}
|
||||
CEntityRegistryObject *pObject = new CEntityRegistryObject(0, szName, 0);
|
||||
pObject->m_pClientfn = pfn;
|
||||
}
|
||||
181
engine/brush.cpp
181
engine/brush.cpp
@@ -1,181 +0,0 @@
|
||||
#include "brush.h"
|
||||
#include "baseentity.h"
|
||||
#include "cglm/mat4.h"
|
||||
#include "physics.h"
|
||||
#include "rendering.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "math3d.h"
|
||||
|
||||
CUtlVector<IVertexBuffer*> g_BrushVertices;
|
||||
|
||||
void CBrushEntity::Precache()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CBrushEntity::Spawn()
|
||||
{
|
||||
/* physics don't support unindexed meshes, so generate indicies */
|
||||
CUtlBuffer<uint32_t> indicies(m_mesh.GetSize()*3);
|
||||
for (uint32_t i = 0;i<indicies.GetSize();i++)
|
||||
{
|
||||
indicies[i]=i;
|
||||
}
|
||||
/* copy over the triangles to a separate buffer, which will be used by physics */
|
||||
CUtlBuffer<Point<float>> triangles(m_mesh.GetSize()*3);
|
||||
uint32_t i = 0;
|
||||
for (auto tri: m_mesh)
|
||||
{
|
||||
V_memcpy(&triangles[i],tri.location,36);
|
||||
i+=3;
|
||||
}
|
||||
/* use them */
|
||||
px_collider_params params = {};
|
||||
params.friction = 0.0;
|
||||
m_collider = px_trimesh((Point<float>*)triangles.GetMemory(), triangles.GetSize(), (uint32_t(*)[3])indicies.GetMemory(), indicies.GetSize()/3 ,params);
|
||||
px_fixedbody(px, m_collider);
|
||||
};
|
||||
|
||||
void CBrushEntity::Destroy()
|
||||
{
|
||||
|
||||
}
|
||||
void CBrushEntity::Think( float fDelta )
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CBrushEntity::SendToServer()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CBrushEntity::RecieveFromServer( void *pData, uint32_t nDataSize )
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
void CBrushEntity::ReadParameter( const char *szName, const char *szValue )
|
||||
{
|
||||
CBaseEntity::ReadParameter(szName, szValue);
|
||||
};
|
||||
|
||||
|
||||
void C_BrushEntity::Precache()
|
||||
{
|
||||
CBrushEntity* pBrushEntity = dynamic_cast<CBrushEntity*>(pEntity);
|
||||
if (!pBrushEntity)
|
||||
Plat_FatalErrorFunc("pEntity is not a CBrushEntity");
|
||||
}
|
||||
|
||||
void C_BrushEntity::Spawn()
|
||||
{
|
||||
struct Vertex_t
|
||||
{
|
||||
float position[3];
|
||||
float uv[2];
|
||||
};
|
||||
|
||||
CBrushEntity* pBrushEntity = (CBrushEntity*)pEntity;
|
||||
uint32_t numVertices = pBrushEntity->m_mesh.GetSize();
|
||||
|
||||
vertexBuffer = Renderer()->CreateVertexBuffer(numVertices*60);
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
void C_BrushEntity::Destroy()
|
||||
{
|
||||
|
||||
}
|
||||
void C_BrushEntity::Think( float fDelta )
|
||||
{
|
||||
g_BrushVertices.AppendTail(vertexBuffer);
|
||||
};
|
||||
|
||||
|
||||
class CBrushRendering: public IRenderingPipelineStep
|
||||
{
|
||||
public:
|
||||
virtual void Init() override;
|
||||
virtual void Frame( float fDelta ) override;
|
||||
virtual void Deinit() override;
|
||||
private:
|
||||
};
|
||||
DECLARE_MESH_RENDERING_STAGE(CBrushRendering, brush_rasterizer);
|
||||
|
||||
|
||||
IGraphicsPipeline *g_BrushPipeline;
|
||||
ITexture *bricks;
|
||||
void CBrushRendering::Init()
|
||||
{
|
||||
g_BrushPipeline = Renderer()->CreateGraphicsPipeline(
|
||||
{
|
||||
{"gfx/mesh_vert.shader", SHADER_TYPE_VERTEX},
|
||||
{"gfx/mesh_frag.shader", SHADER_TYPE_FRAGMENT},
|
||||
},
|
||||
{
|
||||
{SHADER_INPUT_TYPE_UNIFORM_BUFFER,0},
|
||||
{SHADER_INPUT_TYPE_TEXTURES,1},
|
||||
},
|
||||
80,
|
||||
20,
|
||||
{{0,0,EVertexFormat::VERTEX_FORMAT_X32Y32Z32}, {12,1,EVertexFormat::VERTEX_FORMAT_X32Y32}},
|
||||
{EImageFormat::IMAGE_FORMAT_R8G8B8A8},
|
||||
true
|
||||
);
|
||||
bricks = ITextureManager::LoadTexture("textures/bricks.png");
|
||||
};
|
||||
|
||||
void CBrushRendering::Frame( float fDelta )
|
||||
{
|
||||
g_BrushPipeline->BindData(0, Renderer()->GetCameraMatrix(), 0);
|
||||
g_BrushPipeline->PushBindings();
|
||||
|
||||
Renderer()->ResetState();
|
||||
Renderer()->SetDepthMode(DEPTH_MODE_LESS);
|
||||
Renderer()->BindPipeline(g_BrushPipeline);
|
||||
struct {
|
||||
mat4 i;
|
||||
uint32_t a = ITextureManager::GetTextureID(bricks);
|
||||
uint32_t b = 0;
|
||||
uint32_t c = 0;
|
||||
} constants;
|
||||
glm_mat4_identity(constants.i);
|
||||
Renderer()->SetConstants(sizeof(constants), &constants);
|
||||
for (auto &v: g_BrushVertices)
|
||||
{
|
||||
Renderer()->Draw(v, 0);
|
||||
}
|
||||
g_BrushVertices = {};
|
||||
};
|
||||
|
||||
void CBrushRendering::Deinit()
|
||||
{
|
||||
|
||||
};
|
||||
1
engine/cl_dll.cpp
Normal file
1
engine/cl_dll.cpp
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "baseentity.h"
|
||||
#include "rendering.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)
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
#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()
|
||||
{
|
||||
C_BrushEntity::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)
|
||||
@@ -1 +0,0 @@
|
||||
#include "client.h"
|
||||
@@ -1,407 +0,0 @@
|
||||
#include "console.h"
|
||||
#include "fgui/rect.h"
|
||||
#include "fgui/widget.h"
|
||||
#include "fgui/label.h"
|
||||
#include "filesystem.h"
|
||||
#include "interface.h"
|
||||
#include "rendering.h"
|
||||
#include "tier1/utlstring.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "stdarg.h"
|
||||
|
||||
|
||||
enum EConsoleMessageType
|
||||
{
|
||||
CONSOLE_MESSAGE_TYPE_MESSAGE,
|
||||
CONSOLE_MESSAGE_TYPE_WARNING,
|
||||
CONSOLE_MESSAGE_TYPE_ERROR,
|
||||
};
|
||||
|
||||
struct ConsoleMessage_t
|
||||
{
|
||||
EConsoleMessageType type;
|
||||
CUtlString szMessage;
|
||||
};
|
||||
|
||||
void Msg( const char* message )
|
||||
{
|
||||
printf(message);
|
||||
|
||||
}
|
||||
|
||||
void Warning( const char* message )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Error( const char* message )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
interface CConsole: public IConsole
|
||||
{
|
||||
public:
|
||||
virtual void Init() override;
|
||||
virtual void Frame() override;
|
||||
virtual void Deinit() override;
|
||||
|
||||
// Variables
|
||||
virtual void RegisterVar( ConVar *cvar ) override;
|
||||
virtual void UnRegisterVar( ConVar *cvar ) override;
|
||||
virtual ConVar *FindVar( const char *pName ) override;
|
||||
|
||||
// Commands
|
||||
virtual void RegisterCommand( ConCommand *cvar ) override;
|
||||
virtual void UnRegisterCommand( ConCommand *cvar ) override;
|
||||
virtual ConCommand *FindCommand( const char *pName ) override;
|
||||
|
||||
// Command buffer
|
||||
virtual void Execute( void ) override;
|
||||
virtual void ExecuteArguments( CUtlVector<CUtlString> &args ) override;
|
||||
virtual CUtlVector<CUtlVector<CUtlString>> ParseCommandLine( CUtlString psz ) override;
|
||||
|
||||
virtual void AddCommand( const char *psz ) override;
|
||||
virtual void InsertCommand( const char *psz ) override;
|
||||
};
|
||||
|
||||
DECLARE_ENGINE_INTERFACE(Console, CConsole)
|
||||
|
||||
void CConsole::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void CConsole::Frame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CConsole::Deinit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CConsole::RegisterVar( ConVar *cvar )
|
||||
{
|
||||
m_convars.AppendTail(cvar);
|
||||
}
|
||||
void CConsole::UnRegisterVar( ConVar *cvar )
|
||||
{
|
||||
|
||||
}
|
||||
ConVar *CConsole::FindVar( const char *pName )
|
||||
{
|
||||
for (auto &var: m_convars)
|
||||
{
|
||||
if (!V_strcmp(var->GetName(), pName))
|
||||
return var;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CConsole::RegisterCommand( ConCommand *cvar )
|
||||
{
|
||||
m_commands.AppendTail(cvar);
|
||||
}
|
||||
void CConsole::UnRegisterCommand( ConCommand *cvar )
|
||||
{
|
||||
|
||||
}
|
||||
ConCommand *CConsole::FindCommand( const char *pName )
|
||||
{
|
||||
for (auto &var: m_commands)
|
||||
{
|
||||
if (!V_strcmp(var->GetName(), pName))
|
||||
return var;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
CUtlString g_commandBuffer;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Executes arguments from CConsole::Execute
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConsole::ExecuteArguments( CUtlVector<CUtlString> &args )
|
||||
{
|
||||
if (args.GetSize()<1)
|
||||
return;
|
||||
|
||||
ConCommand *cmd = CConsole::FindCommand(args[0]);
|
||||
if (!cmd)
|
||||
{
|
||||
V_printf("%s not found\n", args[0].GetString());
|
||||
return;
|
||||
}
|
||||
CUtlBuffer<char*> strbuffer(args.GetSize());
|
||||
for ( size_t i = 0; i < args.GetSize(); i++)
|
||||
{
|
||||
strbuffer[i] = args[i].GetString();
|
||||
};
|
||||
(cmd->GetCallback())(args.GetSize(), strbuffer);
|
||||
}
|
||||
|
||||
void CConsole::Execute( void )
|
||||
{
|
||||
CUtlVector<CUtlVector<CUtlString>> commands = ParseCommandLine(g_commandBuffer);
|
||||
g_commandBuffer = 0;
|
||||
for (auto &command: commands)
|
||||
{
|
||||
ExecuteArguments(command);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parses command buffer.
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlVector<CUtlVector<CUtlString>> CConsole::ParseCommandLine( CUtlString psz )
|
||||
{
|
||||
CUtlVector<CUtlString> arguments;
|
||||
CUtlVector<CUtlVector<CUtlString>> commands;
|
||||
CUtlString szArgument;
|
||||
bool bIsQuote = false;
|
||||
for ( auto &c: (CUtlVector<char>&)psz )
|
||||
{
|
||||
if ( c == '\"' )
|
||||
{
|
||||
bIsQuote = !bIsQuote;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( c == ';' || c == '\n' )
|
||||
{
|
||||
if (bIsQuote)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (szArgument != 0)
|
||||
arguments.AppendTail(szArgument);
|
||||
if ( arguments.GetSize() > 0 )
|
||||
commands.AppendTail(arguments);
|
||||
szArgument = 0;
|
||||
arguments = {};
|
||||
continue;
|
||||
}
|
||||
if ( c == '\t' || c == ' ' )
|
||||
{
|
||||
if (bIsQuote)
|
||||
{
|
||||
szArgument.AppendTail(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (szArgument != 0)
|
||||
arguments.AppendTail(szArgument);
|
||||
szArgument = 0;
|
||||
continue;
|
||||
}
|
||||
szArgument.AppendTail(c);
|
||||
};
|
||||
if (szArgument != 0)
|
||||
arguments.AppendTail(szArgument);
|
||||
if ( arguments.GetSize() > 0 )
|
||||
commands.AppendTail(arguments);
|
||||
return commands;
|
||||
}
|
||||
|
||||
void CConsole::AddCommand( const char *psz )
|
||||
{
|
||||
g_commandBuffer.AppendTail(psz);
|
||||
}
|
||||
|
||||
void CConsole::InsertCommand( const char *psz )
|
||||
{
|
||||
g_commandBuffer.AppendHead(psz);
|
||||
};
|
||||
|
||||
ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags )
|
||||
: ConVar(pName, pDefaultValue, flags, 0)
|
||||
{
|
||||
|
||||
}
|
||||
ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||
const char *pHelpString )
|
||||
: ConVar(pName, pDefaultValue, flags, pHelpString, 0)
|
||||
{
|
||||
}
|
||||
ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||
const char *pHelpString, ConCommandFn callback )
|
||||
{
|
||||
m_szName = pName;
|
||||
m_flags = flags;
|
||||
m_szValue = pDefaultValue;
|
||||
m_fValue = V_atof(pDefaultValue);
|
||||
m_nValue = V_atoi(pDefaultValue);
|
||||
Console()->RegisterVar(this);
|
||||
}
|
||||
|
||||
bool ConVar::IsFlagSet( int flag )
|
||||
{
|
||||
|
||||
}
|
||||
const char *ConVar::GetHelpText( void )
|
||||
{
|
||||
return m_szHelpString;
|
||||
}
|
||||
bool ConVar::IsRegistered( void )
|
||||
{
|
||||
|
||||
}
|
||||
const char *ConVar::GetName( void )
|
||||
{
|
||||
return m_szName;
|
||||
}
|
||||
void ConVar::AddFlags( int flags )
|
||||
{
|
||||
|
||||
}
|
||||
bool ConVar::IsCommand( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ConVar::InstallChangeCallback( ConCommandFn )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float ConVar::GetFloat( void )
|
||||
{
|
||||
return m_fValue;
|
||||
}
|
||||
int ConVar::GetInt( void )
|
||||
{
|
||||
return m_nValue;
|
||||
}
|
||||
bool ConVar::GetBool( void )
|
||||
{
|
||||
return m_nValue;
|
||||
}
|
||||
const char *ConVar::GetString( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ConVar::SetValue( const char *szValue )
|
||||
{
|
||||
if (!szValue)
|
||||
return;
|
||||
m_szValue = szValue;
|
||||
m_fValue = V_atof(szValue);
|
||||
m_nValue = V_atoi(szValue);
|
||||
}
|
||||
void ConVar::SetValue( float fValue )
|
||||
{
|
||||
m_fValue = fValue;
|
||||
m_nValue = fValue;
|
||||
m_szValue = CUtlString("%f\n",fValue);
|
||||
}
|
||||
void ConVar::SetValue( int iValue )
|
||||
{
|
||||
m_fValue = iValue;
|
||||
m_nValue = iValue;
|
||||
m_szValue = CUtlString("%i\n",iValue);
|
||||
}
|
||||
|
||||
ConCommand::ConCommand(const char *pName, ConCommandFn callback,
|
||||
const char *pHelpString, int flags)
|
||||
{
|
||||
m_szName = pName;
|
||||
m_callback = callback;
|
||||
m_flags = flags;
|
||||
Console()->RegisterCommand(this);
|
||||
};
|
||||
const char *ConCommand::GetHelpText( void )
|
||||
{
|
||||
return m_szHelpString;
|
||||
}
|
||||
const char *ConCommand::GetName( void )
|
||||
{
|
||||
return m_szName;
|
||||
}
|
||||
ConCommandFn ConCommand::GetCallback( void )
|
||||
{
|
||||
return m_callback;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void IConsole_Exec( int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
return;
|
||||
|
||||
FileHandle_t f = FileSystem()->Open(argv[1], IFILE_READ);
|
||||
if (!f)
|
||||
return;
|
||||
CUtlBuffer<char> b(FileSystem()->Size(f)+1);
|
||||
FileSystem()->Read(f, b, b.GetSize());
|
||||
b[FileSystem()->Size(f)] = 0;
|
||||
Console()->AddCommand(b);
|
||||
Console()->AddCommand(";");
|
||||
Console()->Execute();
|
||||
}
|
||||
|
||||
ConCommand IConsole_ExecCmd("exec", IConsole_Exec);
|
||||
|
||||
class CConsoleGUI: public CFGUI_Widget
|
||||
{
|
||||
public:
|
||||
CConsoleGUI();
|
||||
virtual void Event( FGUI_Event_t event ) override;
|
||||
virtual void Draw() override;
|
||||
virtual void Frame() override;
|
||||
private:
|
||||
CFGUI_Rect *m_pBackground = 0;
|
||||
CFGUI_Label *m_pLog = 0;
|
||||
};
|
||||
|
||||
bool console_bDrawUI = false;
|
||||
|
||||
CConsoleGUI::CConsoleGUI()
|
||||
{
|
||||
m_pBackground = new CFGUI_Rect();
|
||||
m_pBackground->SetBoxColor(0.13, 0.13, 0.13, 1);
|
||||
m_pBackground->SetSize(200, 200);
|
||||
m_pBackground->SetPosition(0, 0);
|
||||
m_pBackground->SetParent(this);
|
||||
|
||||
m_pLog = new CFGUI_Label();
|
||||
m_pLog->SetFont("fonts/IBMPlexMono-Regular");
|
||||
m_pLog->SetLabel("CONSOLE");
|
||||
m_pLog->SetPosition(0, 0);
|
||||
m_pLog->SetGlyphSize(24);
|
||||
m_pLog->SetParent(this);
|
||||
};
|
||||
|
||||
void CConsoleGUI::Event( FGUI_Event_t event )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CConsoleGUI::Draw()
|
||||
{
|
||||
SetPosition(20, 20);
|
||||
m_pBackground->SetSize(g_nWindowWidth-40, g_nWindowHeight-40);
|
||||
m_pBackground->SetSize(g_nWindowWidth-40, g_nWindowHeight-40);
|
||||
}
|
||||
|
||||
void CConsoleGUI::Frame()
|
||||
{
|
||||
SetVisibility(console_bDrawUI);
|
||||
}
|
||||
|
||||
void IConsoleUI::Init()
|
||||
{
|
||||
new CConsoleGUI;
|
||||
};
|
||||
|
||||
void IConsoleUI::SetVisibility( bool bIsVisisble )
|
||||
{
|
||||
console_bDrawUI = bIsVisisble;
|
||||
}
|
||||
|
||||
bool IConsoleUI::IsVisibile()
|
||||
{
|
||||
return console_bDrawUI;
|
||||
}
|
||||
@@ -1,281 +1,26 @@
|
||||
|
||||
#include "fgui/fgui.h"
|
||||
#include "input.h"
|
||||
#include "mainmenu.h"
|
||||
#include "networking.h"
|
||||
#include "steam/steam_api_common.h"
|
||||
#include "tier0/network.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "igamewindow.h"
|
||||
#include "tier1/interface.h"
|
||||
#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"
|
||||
#include "physics.h"
|
||||
#include "signal.h"
|
||||
#include "steam/steam_api.h"
|
||||
#include "steam/isteamgameserver.h"
|
||||
#include "steam/steam_gameserver.h"
|
||||
#include "networking.h"
|
||||
#include "tier0/mem.h"
|
||||
#include "sv_dll.h"
|
||||
|
||||
double fPrev = 0;
|
||||
double fCurrent = 0;
|
||||
|
||||
funnyphysics *px;
|
||||
|
||||
IIClient *g_localClient;
|
||||
|
||||
CUtlVector<IIClient*> g_clients = {};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 */
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Recieves signals from the system
|
||||
//-----------------------------------------------------------------------------
|
||||
void IEngine_Signal(int sig)
|
||||
extern "C" void FunnyMain( int argc, char **argv )
|
||||
{
|
||||
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();
|
||||
Plat_Exit(0);
|
||||
};
|
||||
CommandLine()->CreateCommandLine(argc, argv);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Initializes engine
|
||||
//-----------------------------------------------------------------------------
|
||||
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
|
||||
#ifdef __WIN32__
|
||||
signal(SIGINT, IEngine_Signal);
|
||||
signal(SIGILL, IEngine_Signal);
|
||||
signal(SIGFPE, IEngine_Signal);
|
||||
signal(SIGSEGV, IEngine_Signal);
|
||||
signal(SIGTERM, IEngine_Signal);
|
||||
#endif
|
||||
filesystem = (IFileSystem*)CreateInterface(FILESYSTEM_INTERFACE_NAME, NULL);
|
||||
filesystem->Init();
|
||||
|
||||
#ifdef STEAM_ENABLED
|
||||
if(SteamAPI_RestartAppIfNecessary(480))
|
||||
{
|
||||
Plat_Exit(0);
|
||||
}
|
||||
gamewindow = (IGameWindow*)CreateInterface(GAME_WINDOW_INTERFACE_NAME, NULL);
|
||||
gamewindow->Init();
|
||||
|
||||
SteamErrMsg err;
|
||||
if (SteamAPI_InitEx(&err) != k_ESteamAPIInitResult_OK)
|
||||
{
|
||||
Plat_FatalErrorFunc("Failed to init Steam: %s\n", err);
|
||||
}
|
||||
#endif
|
||||
ServerGameDLL()->Init();
|
||||
|
||||
FileSystem()->InitFilesystem();
|
||||
px = px_init();
|
||||
|
||||
if (!ICommandLine::CheckParam("-dedicated"))
|
||||
{
|
||||
// Run local client
|
||||
g_localClient = new IIClient();
|
||||
IIEngine::ConnectClient(g_localClient);
|
||||
|
||||
// Init IO
|
||||
IVideo::Init();
|
||||
Input()->Init();
|
||||
Input()->SetInputMode(INPUT_MODE_MENU);
|
||||
IFGUI::Init();
|
||||
for (;;) {
|
||||
gamewindow->UpdateWindow();
|
||||
};
|
||||
|
||||
INetworking::Init();
|
||||
|
||||
// load game
|
||||
IServer::LoadGame("funnygame");
|
||||
|
||||
// create pipelines for rendering
|
||||
if (!ICommandLine::CheckParam("-dedicated"))
|
||||
IVideo::CreatePipelines();
|
||||
|
||||
// execute default config
|
||||
Console()->AddCommand("exec default.cfg;");
|
||||
Console()->Execute();
|
||||
|
||||
if (INetworking::IsClient())
|
||||
{
|
||||
MainMenu()->Init();
|
||||
IConsoleUI::Init();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates every frame
|
||||
//-----------------------------------------------------------------------------
|
||||
void IEngine::Frame(float fDelta)
|
||||
{
|
||||
#ifdef STEAM_ENABLED
|
||||
SteamAPI_RunCallbacks();
|
||||
#endif
|
||||
IServer::Think(fDelta);
|
||||
|
||||
if (INetworking::IsClient())
|
||||
{
|
||||
MainMenu()->Frame();
|
||||
IFGUI::Frame();
|
||||
IVideo::Frame(fDelta);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Deinitializes engine
|
||||
//-----------------------------------------------------------------------------
|
||||
void IEngine::Shutdown()
|
||||
{
|
||||
if (INetworking::IsClient())
|
||||
MainMenu()->Deinit();
|
||||
INetworking::Deinit();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawns entity in the world
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uint64_t g_lastServerID = 1;
|
||||
uint64_t g_lastPredictedID = 1;
|
||||
CBaseEntity *IIEngine::SpawnEntity( const char *szName )
|
||||
{
|
||||
for (auto &entity: EntityManager()->m_RegisteredEntities)
|
||||
{
|
||||
if (!V_strcmp(entity->m_szName, szName))
|
||||
{
|
||||
CBaseEntity *pEnt = entity->m_pfn();
|
||||
pEnt->m_id = g_lastPredictedID+=1;
|
||||
EntityManager()->m_entities.AppendTail(pEnt);
|
||||
if (ICommandLine::CheckParam("-dedicated"))
|
||||
return pEnt;
|
||||
if (entity->m_pClientfn)
|
||||
{
|
||||
pEnt->pClientEntity = entity->m_pClientfn();
|
||||
pEnt->pClientEntity->pEntity = pEnt;
|
||||
}
|
||||
return pEnt;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawns entity without any parameters
|
||||
//-----------------------------------------------------------------------------
|
||||
void IIEngine::InitEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
if (!pEntity)
|
||||
return;
|
||||
pEntity->Spawn();
|
||||
if (pEntity->pClientEntity)
|
||||
pEntity->pClientEntity->Spawn();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destroys entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void IIEngine::DestroyEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
uint32_t i = 0;
|
||||
if (pEntity == NULL)
|
||||
return;
|
||||
for (auto &entity: EntityManager()->m_entities)
|
||||
{
|
||||
if (pEntity == entity)
|
||||
{
|
||||
pEntity->Destroy();
|
||||
if (pEntity->pClientEntity)
|
||||
pEntity->pClientEntity->Destroy();
|
||||
EntityManager()->m_entities.RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Connects client to the server
|
||||
//-----------------------------------------------------------------------------
|
||||
void IIEngine::ConnectClient( IIClient *pClient )
|
||||
{
|
||||
g_clients.AppendTail(pClient);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Disconnects client from the server
|
||||
//-----------------------------------------------------------------------------
|
||||
void IIEngine::DisconnectClient( IIClient *pClient )
|
||||
{
|
||||
DisconnectClient(pClient->playerID);
|
||||
}
|
||||
|
||||
void IIEngine::DisconnectClient( uint64_t playerID )
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
if (client->playerID == playerID)
|
||||
{
|
||||
g_clients.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
void IIEngine::DisconnectClientByHandle( uint32_t playerHandle )
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
if (client->playerHandle == playerHandle)
|
||||
{
|
||||
IIEngine::DestroyEntity((CBaseEntity*)client->pBasePlayer);
|
||||
g_clients.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,288 +1,86 @@
|
||||
#include "interface.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/commandline.h"
|
||||
#include "filesystem.h"
|
||||
#include "unistd.h"
|
||||
#include <cstdio>
|
||||
#include "ifilesystem.h"
|
||||
#include "tier1/interface.h"
|
||||
#include "tier0/lib.h"
|
||||
|
||||
#define BASEDIR "rtt"
|
||||
#define GAMEDIR "funnygame"
|
||||
|
||||
|
||||
struct PackHeader_t
|
||||
size_t IFileHandle::Write( const void *pData, size_t nDataSize )
|
||||
{
|
||||
char id[8];
|
||||
unsigned long long offset;
|
||||
unsigned long long size;
|
||||
};
|
||||
struct PackDirectory_t
|
||||
return m_pFileSystem->Write(this, pData, nDataSize);
|
||||
}
|
||||
|
||||
size_t IFileHandle::Read( void *pData, size_t nDataSize )
|
||||
{
|
||||
char name[56];
|
||||
unsigned long long offset;
|
||||
unsigned long long size;
|
||||
};
|
||||
struct Pack_t
|
||||
return m_pFileSystem->Read(this, pData, nDataSize);
|
||||
}
|
||||
|
||||
size_t IFileHandle::Seek( ESeekMode eSeekMode, size_t nOffset )
|
||||
{
|
||||
FILE* handle;
|
||||
PackHeader_t header;
|
||||
CUtlVector<PackDirectory_t> files;
|
||||
};
|
||||
struct FileDirectory_t
|
||||
return m_pFileSystem->Seek(this, eSeekMode, nOffset);
|
||||
}
|
||||
|
||||
size_t IFileHandle::Tell( void )
|
||||
{
|
||||
CUtlString path;
|
||||
Pack_t pack;
|
||||
};
|
||||
return m_pFileSystem->Tell(this);
|
||||
}
|
||||
|
||||
void IFileHandle::Close( void )
|
||||
{
|
||||
m_pFileSystem->Close(this);
|
||||
}
|
||||
|
||||
|
||||
CUtlString fs_basedir;
|
||||
CUtlString fs_gamedir;
|
||||
CUtlSelfReferencingVector<FileDirectory_t> fs_directories;
|
||||
|
||||
interface CFileSystem: public IFileSystem
|
||||
class CFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
virtual void Init() override {}
|
||||
virtual void Frame() override {}
|
||||
virtual void Deinit() override {}
|
||||
|
||||
virtual void InitFilesystem( void ) override;
|
||||
virtual void AddGameDirectory( const char *psz ) override;
|
||||
virtual bool LoadPackFile( const char *szFilename ) override;
|
||||
virtual void CreatePath( const char *szPath ) override;
|
||||
virtual FileHandle_t Open( const char *szFilename, EFileOptions options ) override;
|
||||
virtual void Close( FileHandle_t file ) override;
|
||||
virtual size_t Size( FileHandle_t file ) override;
|
||||
virtual size_t Read( FileHandle_t file, void *pOutput, size_t nSize) override;
|
||||
virtual size_t ReadLine( FileHandle_t file, void *pOutput, size_t nSize) override;
|
||||
virtual size_t Write( FileHandle_t file, void *pInput, size_t nSize) override;
|
||||
virtual size_t Seek( FileHandle_t file, size_t nSize) override;
|
||||
virtual size_t Tell( FileHandle_t file, size_t nSize) override;
|
||||
virtual size_t fprintf( FileHandle_t file, const char *szFormat, ...) override;
|
||||
|
||||
static void AddDirectory( const char *psz );
|
||||
static void AddFile( const char *psz );
|
||||
};
|
||||
|
||||
DECLARE_ENGINE_INTERFACE(FileSystem, CFileSystem);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFileSystem::InitFilesystem()
|
||||
{
|
||||
#ifdef STATIC_BUILD
|
||||
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);
|
||||
#endif
|
||||
AddGameDirectory(".");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFileSystem::AddFile( const char *psz )
|
||||
{
|
||||
CUtlString extension = Plat_GetExtension(psz);
|
||||
if (extension=="pak")
|
||||
{
|
||||
FileSystem()->LoadPackFile(psz);
|
||||
virtual void Init() override {
|
||||
filesystem_backend = (IFileSystem*)CreateInterface(FILESYSTEM_BACKEND_INTERFACE_NAME, NULL);
|
||||
filesystem_backend->Init();
|
||||
filesystem_pak = (IFileSystem*)CreateInterface(FILESYSTEM_PAK_INTERFACE_NAME, NULL);
|
||||
filesystem_pak->Init();
|
||||
};
|
||||
}
|
||||
virtual void Shutdown() override {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adds directory which can contain pack files
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFileSystem::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);
|
||||
};
|
||||
|
||||
virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override
|
||||
{
|
||||
IFileHandle *pHandle = NULL;
|
||||
|
||||
pHandle = filesystem_pak->Open(szFileName, eOpCode);
|
||||
if (pHandle) return pHandle;
|
||||
|
||||
pHandle = filesystem_backend->Open(szFileName, eOpCode);
|
||||
if (pHandle) return pHandle;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override
|
||||
{
|
||||
return pFile->Write(pData, nDataSize);
|
||||
}
|
||||
|
||||
virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override
|
||||
{
|
||||
return pFile->Read(pData, nDataSize);
|
||||
}
|
||||
|
||||
virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) override
|
||||
{
|
||||
return pFile->Seek(eSeekMode, nOffset);
|
||||
}
|
||||
|
||||
virtual size_t Tell( IFileHandle *pFile ) override
|
||||
{
|
||||
return pFile->Tell();
|
||||
}
|
||||
virtual void Close( IFileHandle *pFile ) override
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CFileSystem::LoadPackFile( const char *szFilename )
|
||||
{
|
||||
Pack_t pack = {};
|
||||
PackHeader_t header = {};
|
||||
unsigned long long nNumFiles = 0;
|
||||
PackDirectory_t *pDirs = NULL;
|
||||
|
||||
FILE* f = V_fopen(szFilename, "rb");
|
||||
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<PackDirectory_t>(nNumFiles);
|
||||
V_memcpy(pack.files.GetData(),pDirs, header.size);
|
||||
V_free(pDirs);
|
||||
|
||||
nNumFiles = header.size/sizeof(PackDirectory_t);
|
||||
|
||||
FileDirectory_t fd = {};
|
||||
fd.path = szFilename;
|
||||
fd.pack = pack;
|
||||
fs_directories.AppendTail(fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates path
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFileSystem::CreatePath( const char *szPath )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Opens file
|
||||
// If it is located in a pack then it can only be read
|
||||
//-----------------------------------------------------------------------------
|
||||
FileHandle_t CFileSystem::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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Closes file
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFileSystem::Close( FileHandle_t file )
|
||||
{
|
||||
/* close only fs files */
|
||||
if (file->file)
|
||||
{
|
||||
V_fclose(file->file);
|
||||
}
|
||||
delete file;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t CFileSystem::Size( FileHandle_t file )
|
||||
{
|
||||
return file->nSize;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Reads nSize bytes of file
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t CFileSystem::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 CFileSystem::ReadLine( FileHandle_t file, void *pOutput, size_t nSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t CFileSystem::Write( FileHandle_t file, void *pInput, size_t nSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t CFileSystem::Seek( FileHandle_t file, size_t nSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t CFileSystem::Tell( FileHandle_t file, size_t nSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t CFileSystem::fprintf( FileHandle_t file, const char *szFormat, ...)
|
||||
{
|
||||
|
||||
}
|
||||
IFileSystem *filesystem;
|
||||
IFileSystem *filesystem_backend;
|
||||
IFileSystem *filesystem_pak;
|
||||
|
||||
EXPOSE_INTERFACE(CFileSystem, IFileSystem, FILESYSTEM_INTERFACE_NAME);
|
||||
|
||||
94
engine/filesystem_libc.cpp
Normal file
94
engine/filesystem_libc.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "ifilesystem.h"
|
||||
#include "tier1/interface.h"
|
||||
#include "tier0/lib.h"
|
||||
|
||||
class CLIBCFileHandle : public IFileHandle
|
||||
{
|
||||
public:
|
||||
FILE *m_pFile;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class CLIBCFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
virtual void Init() override {};
|
||||
virtual void Shutdown() override {};
|
||||
|
||||
virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override
|
||||
{
|
||||
const char *szOperation;
|
||||
FILE *pFile;
|
||||
CLIBCFileHandle *pHandle = NULL;
|
||||
|
||||
switch (eOpCode)
|
||||
{
|
||||
case FILEMODE_READ:
|
||||
szOperation = "r";
|
||||
break;
|
||||
default:
|
||||
V_printf("Operation is not supported\n");
|
||||
break;
|
||||
}
|
||||
|
||||
pFile = V_fopen(szFileName, szOperation);
|
||||
if (!pFile)
|
||||
return NULL;
|
||||
|
||||
pHandle = new CLIBCFileHandle;
|
||||
pHandle->m_pFileSystem = this;
|
||||
pHandle->m_pFile = pFile;
|
||||
return pHandle;
|
||||
}
|
||||
virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override
|
||||
{
|
||||
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
|
||||
if (!pHandle)
|
||||
return 0;
|
||||
return V_fread( pData, 1, nDataSize, pHandle->m_pFile );
|
||||
}
|
||||
|
||||
virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) override
|
||||
{
|
||||
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
|
||||
int eLibcSeekMode = 0;
|
||||
switch (eSeekMode) {
|
||||
case SEEKMODE_SET:
|
||||
eLibcSeekMode = SEEK_SET;
|
||||
break;
|
||||
case SEEKMODE_RELATIVE_END:
|
||||
eLibcSeekMode = SEEK_END;
|
||||
break;
|
||||
case SEEKMODE_RELATIVE_START:
|
||||
eLibcSeekMode = SEEK_CUR;
|
||||
break;
|
||||
}
|
||||
if (!pHandle)
|
||||
return 0;
|
||||
return V_fseek( pHandle->m_pFile, eLibcSeekMode, nOffset );
|
||||
}
|
||||
|
||||
virtual size_t Tell( IFileHandle *pFile ) override
|
||||
{
|
||||
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
|
||||
if (!pHandle)
|
||||
return 0;
|
||||
return V_ftell(pHandle->m_pFile);
|
||||
}
|
||||
|
||||
virtual void Close( IFileHandle *pFile ) override
|
||||
{
|
||||
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
|
||||
if (!pHandle)
|
||||
return;
|
||||
V_fclose(pHandle->m_pFile);
|
||||
delete pHandle;
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_INTERFACE(CLIBCFileSystem, IFileSystem, FILESYSTEM_BACKEND_INTERFACE_NAME);
|
||||
81
engine/filesystem_pak.cpp
Normal file
81
engine/filesystem_pak.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "ifilesystem.h"
|
||||
#include "tier1/interface.h"
|
||||
#include "tier0/lib.h"
|
||||
|
||||
class CPAKFileHandle : public IFileHandle
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
class CPAKFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
virtual void Init() override {};
|
||||
virtual void Shutdown() override {};
|
||||
|
||||
virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override
|
||||
{
|
||||
const char *szOperation;
|
||||
switch (eOpCode)
|
||||
{
|
||||
case FILEMODE_READ:
|
||||
szOperation = "r";
|
||||
break;
|
||||
default:
|
||||
V_printf("Operation is not supported\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
CPAKFileHandle *pHandle = new CPAKFileHandle;
|
||||
return pHandle;
|
||||
}
|
||||
virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override
|
||||
{
|
||||
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
|
||||
if (!pHandle)
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) override
|
||||
{
|
||||
int eLibcSeekMode = 0;
|
||||
switch (eSeekMode) {
|
||||
case SEEKMODE_SET:
|
||||
eLibcSeekMode = SEEK_SET;
|
||||
break;
|
||||
case SEEKMODE_RELATIVE_END:
|
||||
eLibcSeekMode = SEEK_END;
|
||||
break;
|
||||
case SEEKMODE_RELATIVE_START:
|
||||
eLibcSeekMode = SEEK_CUR;
|
||||
break;
|
||||
}
|
||||
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
|
||||
if (!pHandle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t Tell( IFileHandle *pFile ) override
|
||||
{
|
||||
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
|
||||
if (!pHandle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void Close( IFileHandle *pFile ) override
|
||||
{
|
||||
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
|
||||
if (!pHandle)
|
||||
return;
|
||||
delete pHandle;
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_INTERFACE(CPAKFileSystem, IFileSystem, FILESYSTEM_PAK_INTERFACE_NAME);
|
||||
@@ -1,165 +0,0 @@
|
||||
#include "gamemode.h"
|
||||
#include "engine.h"
|
||||
#include "interface.h"
|
||||
#include "playerstart.h"
|
||||
#include "networking.h"
|
||||
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlstring.h"
|
||||
|
||||
CGameMode *pCurrentMode = NULL;
|
||||
CUtlString szCurrentModeName;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Round begin handler
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMode::RoundBegin( void )
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto &start: g_PlayerStarts)
|
||||
{
|
||||
start->RoundEnd();
|
||||
}
|
||||
for (auto &player: g_clients)
|
||||
{
|
||||
CPlayerStart *pSelectedStart = NULL;
|
||||
for (auto &start: g_PlayerStarts)
|
||||
{
|
||||
if (start->m_bIsRunning == false)
|
||||
pSelectedStart = start;
|
||||
};
|
||||
if (pSelectedStart)
|
||||
pSelectedStart->RoundStart(player);
|
||||
i++;
|
||||
}
|
||||
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
CSteamID steamID = CSteamID();
|
||||
if ( client->playerID == 0)
|
||||
V_printf("%s\t", SteamFriends()->GetPlayerNickname((uint64)client->playerID));
|
||||
else
|
||||
V_printf("%s\t", SteamFriends()->GetPersonaName());
|
||||
V_printf("%llu\t", client->playerID);
|
||||
V_printf("%u\n", client->playerHandle);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Round end handler
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMode::RoundEnd( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class CGameModeManager: public IGameModeManager
|
||||
{
|
||||
public:
|
||||
virtual void Init( void ) override;
|
||||
virtual void Frame( void ) override;
|
||||
virtual void Deinit( void ) override;
|
||||
|
||||
virtual void StartGameMode( const char *szName ) override;
|
||||
virtual const char *GetCurrentGameMode( void ) override;
|
||||
virtual CGameMode *GetCurrentGameModeClass( void ) override;
|
||||
virtual void RestartCurrentGameMode( void ) override;
|
||||
};
|
||||
|
||||
DECLARE_ENGINE_INTERFACE(GameModeManager, CGameModeManager);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameModeManager::Init( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameModeManager::Frame( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameModeManager::Deinit( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets gamemode
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameModeManager::StartGameMode( const char *szName )
|
||||
{
|
||||
if (pCurrentMode)
|
||||
{
|
||||
pCurrentMode->RoundEnd();
|
||||
delete pCurrentMode;
|
||||
}
|
||||
for (auto &mode: m_RegisteredGameModes)
|
||||
{
|
||||
if (!V_strcmp(mode->m_szName, szName))
|
||||
{
|
||||
pCurrentMode = mode->m_pfn();
|
||||
pCurrentMode->RoundBegin();
|
||||
szCurrentModeName = szName;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CGameModeManager::GetCurrentGameMode( void )
|
||||
{
|
||||
return szCurrentModeName;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameMode *CGameModeManager::GetCurrentGameModeClass( void )
|
||||
{
|
||||
return pCurrentMode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Restarts the gamemode
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameModeManager::RestartCurrentGameMode( void )
|
||||
{
|
||||
if (!pCurrentMode)
|
||||
return;
|
||||
|
||||
if (INetworking::IsServer())
|
||||
{
|
||||
PacketGameMode_t mode = {};
|
||||
mode.type = PACKET_TYPE_GAMEMODE_START;
|
||||
V_memcpy(mode.szName,szCurrentModeName, min(szCurrentModeName.GetLenght(), 255));
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
INetworking::SendData(&mode, sizeof(mode), client, MESSAGE_MODE_RELIABLE);
|
||||
};
|
||||
};
|
||||
pCurrentMode->RoundEnd();
|
||||
pCurrentMode->RoundBegin();
|
||||
}
|
||||
|
||||
|
||||
CGameModeRegistry::CGameModeRegistry(const char *szName, GameModeRegistryFn pfn) :
|
||||
m_szName(szName), m_pfn(pfn)
|
||||
{
|
||||
GameModeManager()->m_RegisteredGameModes.AppendTail(this);
|
||||
};
|
||||
|
||||
|
||||
60
engine/gamewindow_sdl.cpp
Normal file
60
engine/gamewindow_sdl.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "SDL3/SDL_error.h"
|
||||
#include "igamewindow.h"
|
||||
#include "tier1/interface.h"
|
||||
#include "tier0/lib.h"
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include "SDL3/SDL.h"
|
||||
#include "SDL3/SDL_init.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include "SDL3/SDL_vulkan.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
|
||||
SDL_Window *g_pWindow;
|
||||
IGameWindow *gamewindow;
|
||||
|
||||
class CSDLGameWindow: public IGameWindow
|
||||
{
|
||||
public:
|
||||
virtual void Init() override;
|
||||
virtual void Shutdown() override;
|
||||
virtual void UpdateWindow() override;
|
||||
};
|
||||
|
||||
|
||||
void CSDLGameWindow::Init()
|
||||
{
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD))
|
||||
Plat_FatalErrorFunc("SDL_Init: %s\n", SDL_GetError());
|
||||
|
||||
g_pWindow = SDL_CreateWindow("funnygame", 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
|
||||
if (!g_pWindow)
|
||||
Plat_FatalErrorFunc("SDL_Init: %s\n", SDL_GetError());
|
||||
}
|
||||
|
||||
void CSDLGameWindow::Shutdown()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CSDLGameWindow::UpdateWindow()
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_QUIT:
|
||||
SDL_Quit();
|
||||
Plat_Exit(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
EXPOSE_INTERFACE(CSDLGameWindow, IGameWindow, GAME_WINDOW_INTERFACE_NAME);
|
||||
301
engine/input.cpp
301
engine/input.cpp
@@ -1,301 +0,0 @@
|
||||
#include "input.h"
|
||||
#include "console.h"
|
||||
#include "interface.h"
|
||||
#include "mainmenu.h"
|
||||
#include "tier0/lib.h"
|
||||
#include "tier1/commandline.h"
|
||||
#include "math3d.h"
|
||||
|
||||
char g_PressedKeys[KEY_NUM_KEYS];
|
||||
float g_fAxisValues[AXIS_NUM_AXIS];
|
||||
float g_fAxisModifiers[AXIS_NUM_AXIS];
|
||||
CUtlString g_bindings[256];
|
||||
bool g_bController = false;
|
||||
|
||||
struct KeyName_t {
|
||||
const char *szName;
|
||||
EInputKey key;
|
||||
};
|
||||
|
||||
KeyName_t keys[] = {
|
||||
|
||||
{"ESCAPE",KEY_ESCAPE},
|
||||
{"ESC",KEY_ESCAPE},
|
||||
{"TAB",KEY_TAB},
|
||||
{"ENTER",KEY_ENTER},
|
||||
{"CTRL",KEY_CONTROL},
|
||||
{"CONTROL",KEY_CONTROL},
|
||||
{"SHIFT",KEY_SHIFT},
|
||||
{"ALT",KEY_ALT},
|
||||
{"SPACE",KEY_SPACE},
|
||||
|
||||
{"BACKSPACE",KEY_BACKSPACE},
|
||||
{"[",KEY_LBRACKET},
|
||||
{"]",KEY_RBRACKET},
|
||||
{"{",KEY_LBRACKET},
|
||||
{"}",KEY_RBRACKET},
|
||||
{"\\",KEY_BACKSLASH},
|
||||
{";",KEY_SEMICOLON},
|
||||
{":",KEY_SEMICOLON},
|
||||
{"\'",KEY_APOSTROPHE},
|
||||
{"\"",KEY_APOSTROPHE},
|
||||
|
||||
{"F1",KEY_F1},
|
||||
{"F2",KEY_F2},
|
||||
{"F3",KEY_F3},
|
||||
{"F4",KEY_F4},
|
||||
{"F5",KEY_F5},
|
||||
{"F6",KEY_F6},
|
||||
{"F7",KEY_F7},
|
||||
{"F8",KEY_F8},
|
||||
{"F9",KEY_F9},
|
||||
{"F10",KEY_F10},
|
||||
{"F11",KEY_F11},
|
||||
{"F12",KEY_F12},
|
||||
|
||||
{"1",KEY_1},
|
||||
{"2",KEY_2},
|
||||
{"3",KEY_3},
|
||||
{"4",KEY_4},
|
||||
{"5",KEY_5},
|
||||
{"6",KEY_6},
|
||||
{"7",KEY_7},
|
||||
{"8",KEY_8},
|
||||
{"9",KEY_9},
|
||||
{"0",KEY_0},
|
||||
|
||||
{"A",KEY_A},
|
||||
{"B",KEY_B},
|
||||
{"C",KEY_C},
|
||||
{"D",KEY_D},
|
||||
{"E",KEY_E},
|
||||
{"F",KEY_F},
|
||||
{"G",KEY_G},
|
||||
{"H",KEY_H},
|
||||
{"I",KEY_I},
|
||||
{"J",KEY_J},
|
||||
{"K",KEY_K},
|
||||
{"L",KEY_L},
|
||||
{"M",KEY_M},
|
||||
{"N",KEY_N},
|
||||
{"O",KEY_O},
|
||||
{"P",KEY_P},
|
||||
{"Q",KEY_Q},
|
||||
{"R",KEY_R},
|
||||
{"S",KEY_S},
|
||||
{"T",KEY_T},
|
||||
{"U",KEY_U},
|
||||
{"V",KEY_V},
|
||||
{"W",KEY_W},
|
||||
{"X",KEY_X},
|
||||
{"Y",KEY_Y},
|
||||
{"Z",KEY_Z},
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Converts string (eg. tab, mouse0, w, 0) to keycode
|
||||
//-----------------------------------------------------------------------------
|
||||
EInputKey IInput_StringToKey( char *psz )
|
||||
{
|
||||
for (uint32_t i = 0; i<sizeof(keys)/sizeof(KeyName_t); i++)
|
||||
{
|
||||
if (!V_stricmp(keys[i].szName, psz))
|
||||
return keys[i].key;
|
||||
};
|
||||
return KEY_NONE;
|
||||
};
|
||||
|
||||
|
||||
interface CInput: public IInput
|
||||
{
|
||||
public:
|
||||
virtual void Init() override;
|
||||
virtual void Frame() override;
|
||||
virtual void Deinit() override;
|
||||
virtual void KeyEvent( EInputKey key, EKeyEventType event ) override;
|
||||
virtual void AxisEvent( EInputAxis axis, float fValue ) override;
|
||||
};
|
||||
|
||||
DECLARE_ENGINE_INTERFACE(Input, CInput)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInput::Init( void )
|
||||
{
|
||||
}
|
||||
|
||||
CUtlVector<EInputMode> g_inputModeStack = {INPUT_MODE_GAME, INPUT_MODE_MENU};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Key event may have different different effects based on current input mode.
|
||||
//
|
||||
// GAME:
|
||||
// Generates command call when pressed the key. eg +forward; -left;
|
||||
// Just to be sure we put ; in the end of the command.
|
||||
// When user releases the key command event is not generated. But if the first
|
||||
// command contains + as first character ( in case of example +forward ), then
|
||||
// it fires -forward
|
||||
//
|
||||
// MENU:
|
||||
// Sends all event to FGUI. KEY_ESCAPE key makes leave the menu and get back to
|
||||
// the game.
|
||||
//
|
||||
// CONSOLE:
|
||||
// Works as permanent input field.
|
||||
//
|
||||
// INPUT FIELD:
|
||||
// Doesn't recieve any events except for KEY_ESCAPE and KEY_ENTER
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInput::KeyEvent( EInputKey key, EKeyEventType event )
|
||||
{
|
||||
if (event == KEY_EVENT_TYPE_DOWN && key == KEY_ESCAPE)
|
||||
{
|
||||
if (g_inputModeStack.GetSize() == 1)
|
||||
{
|
||||
g_inputModeStack.AppendTail(INPUT_MODE_MENU);
|
||||
IInput::SetInputMode(INPUT_MODE_MENU);
|
||||
MainMenu()->SetVisibility(true);
|
||||
return;
|
||||
}
|
||||
if (IConsoleUI::IsVisibile())
|
||||
IConsoleUI::SetVisibility(false);
|
||||
IInput::SetInputMode(g_inputModeStack[g_inputModeStack.GetSize()-2]);
|
||||
g_inputModeStack.RemoveTail();
|
||||
|
||||
if (g_inputModeStack[g_inputModeStack.GetSize()-1] != INPUT_MODE_MENU)
|
||||
{
|
||||
MainMenu()->SetVisibility(false);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
if (event == KEY_EVENT_TYPE_DOWN && key == KEY_TILDE)
|
||||
{
|
||||
if (IConsoleUI::IsVisibile())
|
||||
{
|
||||
IInput::SetInputMode(g_inputModeStack[g_inputModeStack.GetSize()-2]);
|
||||
g_inputModeStack.RemoveTail();
|
||||
IConsoleUI::SetVisibility(false);
|
||||
} else
|
||||
{
|
||||
g_inputModeStack.AppendTail(INPUT_MODE_CONSOLE);
|
||||
IInput::SetInputMode(INPUT_MODE_CONSOLE);
|
||||
IConsoleUI::SetVisibility(true);
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
if (event == KEY_EVENT_TYPE_DOWN && key == KEY_F11)
|
||||
{
|
||||
Console()->AddCommand("exit;");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (g_inputModeStack[g_inputModeStack.GetSize()-1] == INPUT_MODE_GAME)
|
||||
{
|
||||
if (event == KEY_EVENT_TYPE_DOWN) {
|
||||
Console()->AddCommand(g_bindings[key]);
|
||||
Console()->AddCommand(";");
|
||||
}
|
||||
if (event == KEY_EVENT_TYPE_UP)
|
||||
{
|
||||
auto binding = Console()->ParseCommandLine(g_bindings[key]);
|
||||
if (binding.GetSize()==0)
|
||||
return;
|
||||
if (binding[0].GetSize() == 0)
|
||||
return;
|
||||
if (binding[0][0].GetString()[0] == '+')
|
||||
{
|
||||
CUtlString command = binding[0][0];
|
||||
command.GetString()[0] = '-';
|
||||
Console()->AddCommand(command);
|
||||
Console()->AddCommand(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g_inputModeStack[g_inputModeStack.GetSize()-1] == INPUT_MODE_MENU)
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Axis events for the input devices such as mouse and controller.
|
||||
// Game needs to explicitly support all of the devices.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInput::AxisEvent( EInputAxis axis, float fValue )
|
||||
{
|
||||
if (g_inputModeStack[g_inputModeStack.GetSize()-1] == INPUT_MODE_GAME)
|
||||
{
|
||||
if (axis == AXIS_MOUSE_X || axis == AXIS_MOUSE_Y)
|
||||
{
|
||||
g_bController = false;
|
||||
g_fAxisValues[axis] += fValue*3.09;
|
||||
}
|
||||
if (axis == AXIS_CONTROLLER_PITCH || axis == AXIS_CONTROLLER_YAW)
|
||||
{
|
||||
g_bController = true;
|
||||
g_fAxisModifiers[axis] = fValue*3.09;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInput::Frame( void )
|
||||
{
|
||||
g_fAxisValues[AXIS_MOUSE_X] += g_fAxisModifiers[AXIS_CONTROLLER_PITCH];
|
||||
g_fAxisValues[AXIS_MOUSE_Y] += g_fAxisModifiers[AXIS_CONTROLLER_YAW];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInput::Deinit( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void IInput_Bind( int argc, char **argv )
|
||||
{
|
||||
if (argc == 1)
|
||||
return;
|
||||
if (argc == 2)
|
||||
return;
|
||||
EInputKey key = IInput_StringToKey(argv[1]);
|
||||
if (key == KEY_NONE)
|
||||
return;
|
||||
|
||||
g_bindings[key] = 0;
|
||||
for ( int i = 2; i<argc; i++ )
|
||||
{
|
||||
g_bindings[key].AppendTail(argv[i]);
|
||||
g_bindings[key].AppendTail(" ");
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void IInput_Unbind( int argc, char **argv )
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void IInput_UnbindAll( int argc, char **argv )
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
ConCommand BindCmd("bind", IInput_Bind, 0);
|
||||
ConCommand UnbindCmd("unbind", IInput_Unbind, 0);
|
||||
ConCommand UnbindAllcmd("unbindall", IInput_UnbindAll, 0);
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "interface.h"
|
||||
#include "tier0/lib.h"
|
||||
|
||||
|
||||
CInterfaceRegistry::CInterfaceRegistry( const char *szName, InterfaceRegistryFn pfn )
|
||||
{
|
||||
};
|
||||
@@ -1,92 +0,0 @@
|
||||
#include "level.h"
|
||||
#include "baseentity.h"
|
||||
#include "brush.h"
|
||||
#include "engine.h"
|
||||
#include "filesystem.h"
|
||||
#include "interface.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;
|
||||
};
|
||||
|
||||
interface CLevelManager: public ILevelManager
|
||||
{
|
||||
public:
|
||||
virtual void Init() override {}
|
||||
virtual void Frame() override {}
|
||||
virtual void Deinit() override {}
|
||||
|
||||
virtual void LoadLevel( const char *szLevelName ) override;
|
||||
};
|
||||
|
||||
DECLARE_ENGINE_INTERFACE(LevelManager, CLevelManager);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Loads level from file, deserializes it and creates entities.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CLevelManager::LoadLevel( const char *szLevelName )
|
||||
{
|
||||
FileHandle_t handle = FileSystem()->Open(CUtlString("%s.fmap",szLevelName), IFILE_READ);
|
||||
CUtlBuffer<char> mapdata(FileSystem()->Size(handle));
|
||||
FileSystem()->Read(handle, mapdata.GetMemory(), mapdata.GetSize());
|
||||
FileSystem()->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<char> szEntityType(V_strlen(pData)+1);
|
||||
V_strcpy(szEntityType, pData);
|
||||
pData+=szEntityType.GetSize();
|
||||
EntityHeader_t* pEntityHeader = (EntityHeader_t*)pData;
|
||||
pData+=sizeof(EntityHeader_t);
|
||||
|
||||
CBaseEntity *pEntity = IIEngine::SpawnEntity(szEntityType);
|
||||
if (!pEntity)
|
||||
continue;
|
||||
|
||||
for ( uint32_t j = 0; j<pEntityHeader->nProperties; j++ )
|
||||
{
|
||||
CUtlBuffer<char> szParamName(V_strlen(pData)+1);
|
||||
V_strcpy(szParamName, pData);
|
||||
pData+=szParamName.GetSize();
|
||||
|
||||
CUtlBuffer<char> szParamValue(V_strlen(pData)+1);
|
||||
V_strcpy(szParamValue, pData);
|
||||
pData+=szParamValue.GetSize();
|
||||
pEntity->ReadParameter(szParamName, szParamValue);
|
||||
};
|
||||
|
||||
CBrushEntity *pBrush = dynamic_cast<CBrushEntity*>(pEntity);
|
||||
if (!pBrush)
|
||||
{
|
||||
IIEngine::InitEntity(pEntity);
|
||||
continue;
|
||||
}
|
||||
|
||||
pBrush->m_mesh = CUtlVector<Triangle_t>(0);
|
||||
for ( uint32_t j = 0; j<pEntityHeader->nTriangles; 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<char> szTextureName(V_strlen(pData)+1);
|
||||
V_strcpy(szTextureName, pData);
|
||||
pData+=szTextureName.GetSize();
|
||||
pBrush->m_mesh.AppendTail(triangle);
|
||||
};
|
||||
IIEngine::InitEntity(pBrush);
|
||||
};
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "miniaudio.h"
|
||||
#include "audio.h"
|
||||
|
||||
class CMASound
|
||||
{
|
||||
};
|
||||
|
||||
class CMAAudioManager: public IAudioManager
|
||||
{
|
||||
virtual void Init() override;
|
||||
virtual void Frame() override;
|
||||
virtual void Deinit() override;
|
||||
|
||||
virtual ISound *CreateSound() override;
|
||||
virtual I3DSound *Create3DSound() override;
|
||||
};
|
||||
|
||||
DECLARE_ENGINE_INTERFACE(AudioManager, CMAAudioManager)
|
||||
|
||||
ma_engine ma_audioEngine;
|
||||
|
||||
void CMAAudioManager::Init()
|
||||
{
|
||||
ma_result r;
|
||||
r = ma_engine_init(NULL, &ma_audioEngine);
|
||||
}
|
||||
|
||||
void CMAAudioManager::Frame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMAAudioManager::Deinit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
ISound *CMAAudioManager::CreateSound()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
I3DSound *CMAAudioManager::Create3DSound()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "miniaudio.h"
|
||||
|
||||
|
||||
156
engine/mesh.cpp
156
engine/mesh.cpp
@@ -1,156 +0,0 @@
|
||||
#include "mesh.h"
|
||||
#include "cglm/mat4.h"
|
||||
#include "rendering.h"
|
||||
|
||||
|
||||
CUtlVector<IMeshInstance*> g_meshes;
|
||||
class CMeshInstance: public IMeshInstance
|
||||
{
|
||||
public:
|
||||
virtual void SetPosition( vec3 position ) override;
|
||||
virtual void SetRotationEuler( vec3 angle ) override;
|
||||
virtual void SetRotationQuat( vec4 quaternion) override;
|
||||
virtual void SetMatrix( mat4 matrix ) override;
|
||||
virtual void SetScale( vec3 scale ) override;
|
||||
|
||||
virtual void Draw() override;
|
||||
|
||||
mat4 m_matrix;
|
||||
vec3 m_position;
|
||||
|
||||
IVertexBuffer *m_pVertexBuffer;
|
||||
IIndexBuffer *m_pIndexBuffer;
|
||||
|
||||
};
|
||||
void CMeshInstance::SetPosition( vec3 position )
|
||||
{
|
||||
glm_vec3_copy(position, m_position);
|
||||
|
||||
}
|
||||
|
||||
void CMeshInstance::SetRotationEuler( vec3 angle )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMeshInstance::SetRotationQuat( vec4 quaternion)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMeshInstance::SetMatrix( mat4 matrix )
|
||||
{
|
||||
glm_mat4_copy(matrix, m_matrix);
|
||||
}
|
||||
|
||||
void CMeshInstance::SetScale( vec3 scale )
|
||||
{
|
||||
}
|
||||
|
||||
void CMeshInstance::Draw()
|
||||
{
|
||||
g_meshes.AppendTail(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CMesh: public IMesh
|
||||
{
|
||||
public:
|
||||
virtual void SetVertexBuffer( IVertexBuffer *pBuffer ) override;
|
||||
virtual void SetIndexBuffer( IIndexBuffer *pBuffer ) override;
|
||||
|
||||
virtual IMeshInstance *CreateInstance() override;
|
||||
|
||||
IVertexBuffer *m_pVertexBuffer = 0;
|
||||
IIndexBuffer *m_pIndexBuffer = 0;
|
||||
};
|
||||
|
||||
void CMesh::SetVertexBuffer( IVertexBuffer *pBuffer )
|
||||
{
|
||||
m_pVertexBuffer = pBuffer;
|
||||
}
|
||||
|
||||
void CMesh::SetIndexBuffer( IIndexBuffer *pBuffer )
|
||||
{
|
||||
m_pIndexBuffer = pBuffer;
|
||||
}
|
||||
|
||||
IMeshInstance *CMesh::CreateInstance()
|
||||
{
|
||||
CMeshInstance *pInstance = new CMeshInstance;
|
||||
pInstance->m_pVertexBuffer = m_pVertexBuffer;
|
||||
pInstance->m_pIndexBuffer = m_pIndexBuffer;
|
||||
return pInstance;
|
||||
};
|
||||
|
||||
|
||||
IGraphicsPipeline *g_MeshPipeline;
|
||||
class CMeshRendering: public IMeshRendering
|
||||
{
|
||||
virtual void Init() override;
|
||||
virtual void Frame( float fDelta ) override;
|
||||
virtual void Deinit() override;
|
||||
};
|
||||
|
||||
void CMeshRendering::Init()
|
||||
{
|
||||
g_MeshPipeline = Renderer()->CreateGraphicsPipeline(
|
||||
{
|
||||
{"gfx/mesh_vert.shader", SHADER_TYPE_VERTEX},
|
||||
{"gfx/mesh_frag.shader", SHADER_TYPE_FRAGMENT},
|
||||
},
|
||||
{
|
||||
{SHADER_INPUT_TYPE_UNIFORM_BUFFER,0},
|
||||
{SHADER_INPUT_TYPE_TEXTURES,1},
|
||||
},
|
||||
80,
|
||||
20,
|
||||
{{0,0,EVertexFormat::VERTEX_FORMAT_X32Y32Z32}, {12,1,EVertexFormat::VERTEX_FORMAT_X32Y32}},
|
||||
{EImageFormat::IMAGE_FORMAT_R8G8B8A8},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void CMeshRendering::Frame( float fDelta )
|
||||
{
|
||||
g_MeshPipeline->BindData(0, Renderer()->GetCameraMatrix(), 0);
|
||||
g_MeshPipeline->PushBindings();
|
||||
|
||||
Renderer()->ResetState();
|
||||
Renderer()->SetDepthMode(DEPTH_MODE_LESS);
|
||||
Renderer()->BindPipeline(g_MeshPipeline);
|
||||
for (auto &v: g_meshes)
|
||||
{
|
||||
CMeshInstance *pMesh = (CMeshInstance*)v;
|
||||
struct {
|
||||
mat4 i;
|
||||
uint32_t a = 0;
|
||||
uint32_t b = 0;
|
||||
uint32_t c = 0;
|
||||
} constants;
|
||||
glm_mat4_copy(pMesh->m_matrix,constants.i);
|
||||
constants.i[3][0] = pMesh->m_position[0];
|
||||
constants.i[3][1] = pMesh->m_position[1];
|
||||
constants.i[3][2] = pMesh->m_position[2];
|
||||
Renderer()->SetConstants(sizeof(constants), &constants);
|
||||
Renderer()->Draw(pMesh->m_pVertexBuffer, pMesh->m_pIndexBuffer);
|
||||
}
|
||||
g_meshes = {};
|
||||
}
|
||||
|
||||
void CMeshRendering::Deinit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IMesh *IMeshRendering::CreateMesh()
|
||||
{
|
||||
CMesh *pMesh = new CMesh;
|
||||
return pMesh;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DECLARE_MESH_RENDERING_STAGE(CMeshRendering, mesh_rendering)
|
||||
@@ -1,685 +0,0 @@
|
||||
#include "Metal/Metal.hpp"
|
||||
#include "math3d.h"
|
||||
#include "filesystem.h"
|
||||
#include "rendering.h"
|
||||
#include "tier0/lib.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "rendering.h"
|
||||
#include "ml_video.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include "TargetConditionals.h"
|
||||
#if TARGET_OS_IPHONE
|
||||
// iOS
|
||||
#define STBI_NO_THREAD_LOCALS
|
||||
#else
|
||||
// macOS
|
||||
#endif
|
||||
#else
|
||||
// Other platforms
|
||||
#endif
|
||||
#include "stb_image.h"
|
||||
|
||||
mat4 g_cameraView;
|
||||
IImage *g_meshDepth;
|
||||
IImage *g_meshDepthMSAA;
|
||||
IImage *g_meshColor;
|
||||
IImage *g_meshColorMSAA;
|
||||
|
||||
CUtlVector<ITexture*> g_textures;
|
||||
|
||||
IBuffer *g_cameraProperties;
|
||||
struct CameraProjection {
|
||||
mat4 viewprojection;
|
||||
};
|
||||
|
||||
CameraProjection *g_cameraDataMap;
|
||||
|
||||
static MTL::RenderPassDescriptor *s_pRenderPass;
|
||||
static MTL::RenderCommandEncoder *s_pEncoder;
|
||||
static uint32_t s_nNumAttachments;
|
||||
|
||||
CUtlVector<MTL::Texture*> g_destroyImageBuffer;
|
||||
CUtlVector<MTL::Buffer*> g_destroyBuffersBuffer;
|
||||
|
||||
extern MTL::PixelFormat g_swapchainFormat;
|
||||
|
||||
MTL::PixelFormat IRenderer_FormatToMl( EImageFormat format )
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case IMAGE_FORMAT_R8G8B8A8: return MTL::PixelFormatRGBA8Unorm;
|
||||
case IMAGE_FORMAT_R16G16B16A16: return MTL::PixelFormatRGBA16Unorm;
|
||||
case IMAGE_FORMAT_DEPTH: return MTL::PixelFormatDepth32Float;
|
||||
case IMAGE_FORMAT_WINDOW: return g_swapchainFormat;
|
||||
default: return MTL::PixelFormatRGBA8Unorm;
|
||||
}
|
||||
};
|
||||
|
||||
MTL::VertexFormat IRenderer_VertexToMl( EVertexFormat format )
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VERTEX_FORMAT_X16: return MTL::VertexFormatHalf;
|
||||
case VERTEX_FORMAT_X16Y16: return MTL::VertexFormatHalf2;
|
||||
case VERTEX_FORMAT_X16Y16Z16: return MTL::VertexFormatHalf3;
|
||||
case VERTEX_FORMAT_X16Y16Z16W16: return MTL::VertexFormatHalf4;
|
||||
case VERTEX_FORMAT_X32: return MTL::VertexFormatFloat;
|
||||
case VERTEX_FORMAT_X32Y32: return MTL::VertexFormatFloat2;
|
||||
case VERTEX_FORMAT_X32Y32Z32: return MTL::VertexFormatFloat3;
|
||||
case VERTEX_FORMAT_X32Y32Z32W32: return MTL::VertexFormatFloat4;
|
||||
default: return MTL::VertexFormatFloat3;
|
||||
}
|
||||
};
|
||||
|
||||
MTL::LoadAction IRenderer_LoadOpMl( EAttachmentLoadMode mode )
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case ATTACHMENT_LOAD_MODE_DONT_CARE: return MTL::LoadActionDontCare;
|
||||
case ATTACHMENT_LOAD_MODE_CLEAR: return MTL::LoadActionClear;
|
||||
case ATTACHMENT_LOAD_MODE_LOAD: return MTL::LoadActionLoad;
|
||||
default: return MTL::LoadActionDontCare;
|
||||
}
|
||||
}
|
||||
|
||||
MTL::StoreAction IRenderer_StoreOpMl( EAttachmentStoreMode mode )
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case ATTACHMENT_STORE_MODE_DONT_CARE: return MTL::StoreActionStore;
|
||||
case ATTACHMENT_STORE_MODE_STORE: return MTL::StoreActionStore;
|
||||
default: return MTL::StoreActionDontCare;
|
||||
}
|
||||
}
|
||||
|
||||
class CMlBuffer: public IBuffer
|
||||
{
|
||||
public:
|
||||
void *Map() override;
|
||||
void Unmap() override;
|
||||
MTL::Buffer *m_buffer;
|
||||
uint32_t m_nSize;
|
||||
};
|
||||
|
||||
|
||||
class CMlImage: public IImage
|
||||
{
|
||||
public:
|
||||
MTL::Texture *m_image;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void *CMlBuffer::Map()
|
||||
{
|
||||
return m_buffer->contents();
|
||||
}
|
||||
|
||||
void CMlBuffer::Unmap()
|
||||
{
|
||||
|
||||
}
|
||||
struct MLShader_t {
|
||||
EShaderType shaderType;
|
||||
MTL::Library *library;
|
||||
MTL::Function *function;
|
||||
NS::String *szMain;
|
||||
};
|
||||
class CMlGraphicsPipeline: public IGraphicsPipeline
|
||||
{
|
||||
public:
|
||||
CUtlVector<MLShader_t> m_shaders;
|
||||
MTL::RenderPipelineState *m_pipeline;
|
||||
CUtlVector<ShaderInput_t> m_inputs;
|
||||
uint32_t m_nVertexSize;
|
||||
};
|
||||
|
||||
class CMlTexture: public ITexture
|
||||
{
|
||||
public:
|
||||
MTL::Texture *m_texture;
|
||||
};
|
||||
|
||||
IStorageBuffer *IRenderer::CreateStorageBuffer( uint32_t uSize )
|
||||
{
|
||||
CMlBuffer *pBuffer = new CMlBuffer;
|
||||
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
|
||||
pBuffer->m_nSize = uSize;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
IUniformBuffer *IRenderer::CreateUniformBuffer( uint32_t uSize )
|
||||
{
|
||||
CMlBuffer *pBuffer = new CMlBuffer;
|
||||
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
|
||||
pBuffer->m_nSize = uSize;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
|
||||
IVertexBuffer *IRenderer::CreateVertexBuffer( uint32_t uSize )
|
||||
{
|
||||
CMlBuffer *pBuffer = new CMlBuffer;
|
||||
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
|
||||
pBuffer->m_nSize = uSize;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
IIndexBuffer *IRenderer::CreateIndexBuffer( uint32_t uSize )
|
||||
{
|
||||
CMlBuffer *pBuffer = new CMlBuffer;
|
||||
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
|
||||
pBuffer->m_nSize = uSize;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
|
||||
IImage *IRenderer::CreateImage( EImageFormat format, uint32_t usage, uint32_t nWidth, uint32_t nHeight, uint32_t nSamples )
|
||||
{
|
||||
CMlImage *pImage = new CMlImage;
|
||||
|
||||
MTL::TextureDescriptor *pCreateInfo = MTL::TextureDescriptor::alloc()->init();
|
||||
pCreateInfo->setPixelFormat(IRenderer_FormatToMl(format));
|
||||
pCreateInfo->setWidth(nWidth);
|
||||
pCreateInfo->setHeight(nHeight);
|
||||
|
||||
MTL::TextureUsage mlusage = 0;
|
||||
if (usage&IMAGE_USAGE_COLOR_ATTACHMENT) mlusage |= MTL::TextureUsageRenderTarget;
|
||||
if (usage&IMAGE_USAGE_DEPTH_ATTACHMENT) mlusage |= MTL::TextureUsageRenderTarget;
|
||||
mlusage |= MTL::TextureUsageShaderRead;
|
||||
mlusage |= MTL::TextureUsageShaderWrite;
|
||||
pCreateInfo->setUsage(mlusage);
|
||||
|
||||
pImage->m_image = g_mlDevice->newTexture(pCreateInfo);
|
||||
|
||||
pCreateInfo->release();
|
||||
|
||||
return pImage;
|
||||
};
|
||||
|
||||
void IRenderer::DestroyBuffer( IBuffer *pBuffer )
|
||||
{
|
||||
if (!pBuffer)
|
||||
return;
|
||||
CMlBuffer *pMlBuffer = (CMlBuffer*)pBuffer;
|
||||
g_destroyBuffersBuffer.AppendTail(pMlBuffer->m_buffer);
|
||||
delete (pMlBuffer);
|
||||
}
|
||||
|
||||
void IRenderer::DestroyImage( IImage *pImage )
|
||||
{
|
||||
if (!pImage)
|
||||
return;
|
||||
CMlImage *pMlImage = (CMlImage*)pImage;
|
||||
g_destroyImageBuffer.AppendTail(pMlImage->m_image);
|
||||
delete (pMlImage);
|
||||
}
|
||||
|
||||
IPipeline *g_pCurrentPipeline;
|
||||
|
||||
|
||||
void IRenderer::SetConstants( uint32_t nSize, void *pData )
|
||||
{
|
||||
|
||||
if (!g_pCurrentPipeline)
|
||||
return;
|
||||
uint32_t nRoundedSize = nSize/8*8;
|
||||
void *pTemporaryBuffer = V_malloc(nRoundedSize);
|
||||
V_memcpy(pTemporaryBuffer, pData, nSize);
|
||||
if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION)
|
||||
{
|
||||
CMlGraphicsPipeline *pMlPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
|
||||
s_pEncoder->setVertexBytes(pTemporaryBuffer, nRoundedSize, 29);
|
||||
s_pEncoder->setFragmentBytes(pTemporaryBuffer, nRoundedSize, 29);
|
||||
}
|
||||
V_free(pTemporaryBuffer);
|
||||
}
|
||||
|
||||
void IRenderer::Barrier( uint32_t stageIn, uint32_t stageOut, CUtlVector<BufferBarrier_t> buffers, CUtlVector<ImageBarrier_t> images )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IRenderer::BindData( uint32_t binding, IBuffer *pBuffer, IImage* pImage)
|
||||
{
|
||||
if (!g_pCurrentPipeline)
|
||||
return;
|
||||
if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION)
|
||||
{
|
||||
CMlBuffer *pMlBuffer = (CMlBuffer*)pBuffer;
|
||||
CMlGraphicsPipeline *pMlPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
|
||||
for (auto &input: pMlPipeline->m_inputs)
|
||||
{
|
||||
if (input.binding != binding)
|
||||
continue;
|
||||
|
||||
switch (input.type)
|
||||
{
|
||||
case SHADER_INPUT_TYPE_STORAGE_BUFFER:
|
||||
case SHADER_INPUT_TYPE_UNIFORM_BUFFER:
|
||||
if (!pBuffer)
|
||||
Plat_FatalErrorFunc("pBuffer is NULL\n");
|
||||
s_pEncoder->setVertexBuffer(pMlBuffer->m_buffer, 0, binding);
|
||||
s_pEncoder->setFragmentBuffer(pMlBuffer->m_buffer, 0, binding);
|
||||
break;
|
||||
case SHADER_INPUT_TYPE_IMAGE:
|
||||
break;
|
||||
case SHADER_INPUT_TYPE_TLAS:
|
||||
break;
|
||||
case SHADER_INPUT_TYPE_TEXTURES:
|
||||
break;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void IRenderer::BindPipeline( IPipeline *pPipeline )
|
||||
{
|
||||
if (!pPipeline)
|
||||
return;
|
||||
if (pPipeline->type == PIPELINE_TYPE_RASTERIZATION)
|
||||
{
|
||||
CMlGraphicsPipeline *pVkPipeline = (CMlGraphicsPipeline*)pPipeline;
|
||||
|
||||
s_pEncoder->setRenderPipelineState(pVkPipeline->m_pipeline);
|
||||
}
|
||||
g_pCurrentPipeline = pPipeline;
|
||||
}
|
||||
|
||||
void IRenderer::PushBindings()
|
||||
{
|
||||
if (!g_pCurrentPipeline)
|
||||
return;
|
||||
if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION)
|
||||
{
|
||||
CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
|
||||
bool bHasTextures = false;
|
||||
for ( int i = 0; i < pPipeline->m_inputs.GetSize(); i++ )
|
||||
{
|
||||
if (pPipeline->m_inputs[i].type == SHADER_INPUT_TYPE_TEXTURES)
|
||||
{
|
||||
bHasTextures = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bHasTextures)
|
||||
return;
|
||||
|
||||
MTL::ArgumentEncoder *argumentEncoder = 0;
|
||||
for (auto &shader: pPipeline->m_shaders)
|
||||
{
|
||||
if (shader.shaderType == SHADER_TYPE_FRAGMENT)
|
||||
{
|
||||
argumentEncoder = shader.function->newArgumentEncoder(21);
|
||||
break;
|
||||
};
|
||||
}
|
||||
MTL::Buffer *argumentBuffer = g_mlDevice->newBuffer(argumentEncoder->encodedLength(), MTL::ResourceStorageModeShared);
|
||||
argumentEncoder->setArgumentBuffer(argumentBuffer, 0);
|
||||
for ( uint32_t i = 0; i < g_textures.GetSize(); i++ )
|
||||
{
|
||||
CMlTexture *texture = (CMlTexture*)g_textures[i];
|
||||
argumentEncoder->setTexture(texture->m_texture, i);
|
||||
s_pEncoder->useResource(texture->m_texture, MTL::ResourceUsageRead);
|
||||
}
|
||||
s_pEncoder->useResource(argumentBuffer, MTL::ResourceUsageRead);
|
||||
s_pEncoder->setFragmentBuffer(argumentBuffer, 0, 21);
|
||||
g_destroyBuffersBuffer.AppendTail(argumentBuffer);
|
||||
argumentEncoder->release();
|
||||
}
|
||||
}
|
||||
|
||||
void IRenderer::Begin( uint32_t nWidth, uint32_t nHeight, CUtlVector<RenderingColorAttachment_t> attachments, RenderingDepthAttachment_t depth )
|
||||
{
|
||||
s_pRenderPass = MTL::RenderPassDescriptor::alloc()->init();
|
||||
uint32_t i = 0;
|
||||
for (auto &attachment: attachments)
|
||||
{
|
||||
CMlImage *pImage = (CMlImage*)attachment.pOutput;
|
||||
CMlImage *pTemporary = (CMlImage*)attachment.pTemporary;
|
||||
auto mlattachment = s_pRenderPass->colorAttachments()->object(i);
|
||||
mlattachment->setTexture(pImage->m_image);
|
||||
mlattachment->setLoadAction(IRenderer_LoadOpMl(attachment.loadMode));
|
||||
mlattachment->setStoreAction(IRenderer_StoreOpMl(attachment.storeMode));
|
||||
mlattachment->setClearColor(MTL::ClearColor(attachment.clearColor[0],attachment.clearColor[1],attachment.clearColor[2],attachment.clearColor[3]));
|
||||
i++;
|
||||
};
|
||||
if (depth.pOutput)
|
||||
{
|
||||
CMlImage *pImage = (CMlImage*)depth.pOutput;
|
||||
CMlImage *pTemporary = (CMlImage*)depth.pTemporary;
|
||||
s_pRenderPass->depthAttachment()->setClearDepth(depth.clearValue);
|
||||
s_pRenderPass->depthAttachment()->setTexture(pImage->m_image);
|
||||
s_pRenderPass->depthAttachment()->setLoadAction(IRenderer_LoadOpMl(depth.loadMode));
|
||||
s_pRenderPass->depthAttachment()->setStoreAction(IRenderer_StoreOpMl(depth.storeMode));
|
||||
}
|
||||
|
||||
s_pEncoder = g_mlCommandBuffer->renderCommandEncoder(s_pRenderPass);
|
||||
}
|
||||
|
||||
void IRenderer::ResetState()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IRenderer::SetDepthMode( EDepthMode mode )
|
||||
{
|
||||
MTL::DepthStencilDescriptor* depthStencilDesc = MTL::DepthStencilDescriptor::alloc()->init();
|
||||
if (mode == DEPTH_MODE_DISABLED)
|
||||
{
|
||||
depthStencilDesc->setDepthWriteEnabled(false);
|
||||
} else {
|
||||
depthStencilDesc->setDepthWriteEnabled(true);
|
||||
switch (mode)
|
||||
{
|
||||
case DEPTH_MODE_LESS:
|
||||
depthStencilDesc->setDepthCompareFunction(MTL::CompareFunctionLess); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto depthStencilState = g_mlDevice->newDepthStencilState(depthStencilDesc);
|
||||
s_pEncoder->setDepthStencilState(depthStencilState);
|
||||
depthStencilDesc->release();
|
||||
}
|
||||
|
||||
void IRenderer::Draw( IVertexBuffer *pVertex, IIndexBuffer *pIndex )
|
||||
{
|
||||
CMlBuffer *pMlVertex = (CMlBuffer*)pVertex;
|
||||
CMlBuffer *pMlIndex = (CMlBuffer*)pIndex;
|
||||
if (pMlIndex)
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
|
||||
s_pEncoder->setVertexBuffer(pMlVertex->m_buffer, 0, 30);
|
||||
s_pEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(pMlVertex->m_nSize/pPipeline->m_nVertexSize));
|
||||
}
|
||||
}
|
||||
|
||||
void IRenderer::End()
|
||||
{
|
||||
s_pEncoder->endEncoding();
|
||||
}
|
||||
|
||||
IBuffer *IRenderer::GetCameraMatrix()
|
||||
{
|
||||
return g_cameraProperties;
|
||||
}
|
||||
|
||||
static CMlImage *pOutputImage = new CMlImage;
|
||||
IImage *IRenderer::GetOutputImage()
|
||||
{
|
||||
pOutputImage->m_image = g_mlDrawableTexture;
|
||||
return pOutputImage;
|
||||
}
|
||||
|
||||
IGraphicsPipeline *IRenderer::CreateGraphicsPipeline(
|
||||
CUtlVector<Shader_t> shaders,
|
||||
CUtlVector<ShaderInput_t> inputs,
|
||||
uint32_t nConstantsSize,
|
||||
uint32_t nVertexSize,
|
||||
CUtlVector<VertexAttribute_t> vertexFormat,
|
||||
CUtlVector<EImageFormat> outputFormats,
|
||||
bool bDepth
|
||||
)
|
||||
{
|
||||
CMlGraphicsPipeline *pPipeline = new CMlGraphicsPipeline;
|
||||
|
||||
|
||||
CUtlVector<MLShader_t> mlshaders;
|
||||
MTL::RenderPipelineDescriptor *pCreateInfo = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||
MTL::VertexDescriptor *vertexDescriptor = MTL::VertexDescriptor::alloc()->init();
|
||||
uint32_t i = 0;
|
||||
for ( auto &vertex: vertexFormat )
|
||||
{
|
||||
vertexDescriptor->attributes()->object(i)->setFormat(IRenderer_VertexToMl(vertex.format));
|
||||
vertexDescriptor->attributes()->object(i)->setOffset(vertex.offset);
|
||||
vertexDescriptor->attributes()->object(i)->setBufferIndex(30);
|
||||
i++;
|
||||
}
|
||||
vertexDescriptor->layouts()->object(30)->setStride(nVertexSize);
|
||||
vertexDescriptor->layouts()->object(30)->setStepRate(1);
|
||||
vertexDescriptor->layouts()->object(30)->setStepFunction(MTL::VertexStepFunctionPerVertex);
|
||||
|
||||
NS::Error *error = NULL;
|
||||
for ( auto &shader: shaders )
|
||||
{
|
||||
MLShader_t mlshader = {};
|
||||
FileHandle_t f = FileSystem()->Open(shader.szPath, IFILE_READ);
|
||||
if (!f)
|
||||
Plat_FatalErrorFunc("Failed to open shader %s\n", shader.szPath.GetString());
|
||||
CUtlBuffer<uint8_t> buffer(FileSystem()->Size(f)+1);
|
||||
FileSystem()->Read(f, buffer.GetMemory(), buffer.GetSize());
|
||||
buffer[FileSystem()->Size(f)] = 0;
|
||||
FileSystem()->Close(f);
|
||||
NS::String *szSourceCode = NS::String::string((const char*)buffer.GetMemory(), NS::StringEncoding::UTF8StringEncoding);
|
||||
MTL::CompileOptions *options = NULL;
|
||||
mlshader.library = g_mlDevice->newLibrary(szSourceCode, options, &error);
|
||||
if (error)
|
||||
Plat_FatalErrorFunc("%s\n",error->localizedDescription()->utf8String());
|
||||
mlshader.szMain = NS::String::string("_main", NS::StringEncoding::UTF8StringEncoding);
|
||||
mlshader.function = mlshader.library->newFunction(mlshader.szMain);
|
||||
|
||||
if (shader.type == SHADER_TYPE_FRAGMENT)
|
||||
pCreateInfo->setFragmentFunction(mlshader.function);
|
||||
if (shader.type == SHADER_TYPE_VERTEX)
|
||||
pCreateInfo->setVertexFunction(mlshader.function);
|
||||
mlshader.shaderType = shader.type;
|
||||
mlshaders.AppendTail(mlshader);
|
||||
}
|
||||
for ( i = 0; i < outputFormats.GetSize(); i++ )
|
||||
{
|
||||
pCreateInfo->colorAttachments()->object(i)->setPixelFormat(IRenderer_FormatToMl(outputFormats[i]));
|
||||
};
|
||||
if (bDepth)
|
||||
pCreateInfo->setDepthAttachmentPixelFormat(MTL::PixelFormatDepth32Float);
|
||||
pCreateInfo->setVertexDescriptor(vertexDescriptor);
|
||||
pPipeline->type = PIPELINE_TYPE_RASTERIZATION;
|
||||
pPipeline->m_pipeline = g_mlDevice->newRenderPipelineState(pCreateInfo, &error);
|
||||
pPipeline->m_nVertexSize = nVertexSize;
|
||||
pPipeline->m_inputs = inputs;
|
||||
pPipeline->m_shaders = mlshaders;
|
||||
if (error)
|
||||
Plat_FatalErrorFunc("%s\n",error->localizedDescription()->utf8String());
|
||||
return pPipeline;
|
||||
};
|
||||
|
||||
uint32_t ITextureManager::GetTextureID(ITexture *pTexture)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (auto &t: g_textures)
|
||||
{
|
||||
if (pTexture == t)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ITexture *ITextureManager::LoadTexture( void *pData, uint32_t X, uint32_t Y, uint32_t numChannels )
|
||||
{
|
||||
CMlTexture *pTexture = new CMlTexture;
|
||||
*pTexture = {};
|
||||
pTexture->x = X;
|
||||
pTexture->y = Y;
|
||||
|
||||
MTL::TextureDescriptor *pCreateInfo = MTL::TextureDescriptor::alloc()->init();
|
||||
pCreateInfo->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB);
|
||||
pCreateInfo->setWidth(X);
|
||||
pCreateInfo->setHeight(Y);
|
||||
pCreateInfo->setUsage(MTL::TextureUsageShaderRead);
|
||||
|
||||
pTexture->m_texture = g_mlDevice->newTexture(pCreateInfo);
|
||||
|
||||
MTL::Region region = MTL::Region(0, 0, 0, X, Y, 1);
|
||||
NS::UInteger bytesPerRow = 4 * X;
|
||||
|
||||
pTexture->m_texture->replaceRegion(region, 0, pData, bytesPerRow);
|
||||
|
||||
pCreateInfo->release();
|
||||
|
||||
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 = FileSystem()->Open(szName, IFILE_READ);
|
||||
if (!file)
|
||||
Plat_FatalErrorFunc("Failed to load %s\n", szName);
|
||||
|
||||
CUtlBuffer<stbi_uc> buffer(FileSystem()->Size(file));
|
||||
FileSystem()->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;
|
||||
};
|
||||
|
||||
void IMetal::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_cameraProperties = IRenderer::CreateUniformBuffer(sizeof(CameraProjection));
|
||||
g_cameraDataMap = (CameraProjection*)g_cameraProperties->Map();
|
||||
ITextureManager::LoadTexture(invalidTexture, 16, 16, 4);
|
||||
|
||||
g_meshDepth = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, 1280, 720, 1);
|
||||
g_meshDepthMSAA = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, 1280, 720, 4);
|
||||
g_meshColor = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, 1280, 720, 1);
|
||||
g_meshColorMSAA = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, 1280, 720, 4);
|
||||
glm_mat4_identity(g_cameraView);
|
||||
}
|
||||
|
||||
static MTL::RenderPipelineState* s_fullScreenDraw;
|
||||
void IMetal::CreatePipelines()
|
||||
{
|
||||
for (auto &step: Renderer()->m_StepPrepass)
|
||||
step.pPipeline->Init();
|
||||
for (auto &step: Renderer()->m_StepMeshRendering)
|
||||
step.pPipeline->Init();
|
||||
for (auto &step: Renderer()->m_StepShading)
|
||||
step.pPipeline->Init();
|
||||
for (auto &step: Renderer()->m_StepPostProcessing)
|
||||
step.pPipeline->Init();
|
||||
for (auto &step: Renderer()->m_StepUI)
|
||||
step.pPipeline->Init();
|
||||
|
||||
NS::Error *error = 0;
|
||||
FileHandle_t f = FileSystem()->Open("gfx/ml_quad.metal", IFILE_READ);
|
||||
CUtlBuffer<uint8_t> buffer(FileSystem()->Size(f)+1);
|
||||
FileSystem()->Read(f, buffer.GetMemory(), buffer.GetSize());
|
||||
buffer[FileSystem()->Size(f)] = 0;
|
||||
FileSystem()->Close(f);
|
||||
NS::String *szSourceCode = NS::String::string((const char*)buffer.GetMemory(), NS::StringEncoding::UTF8StringEncoding);
|
||||
MTL::CompileOptions *options = NULL;
|
||||
MTL::Library *library = g_mlDevice->newLibrary(szSourceCode, options, &error);
|
||||
MTL::Function *vertexFunc = library->newFunction(NS::String::string("vertex_main", NS::UTF8StringEncoding));
|
||||
MTL::Function *fragmentFunc = library->newFunction(NS::String::string("fragment_main", NS::UTF8StringEncoding));
|
||||
|
||||
MTL::RenderPipelineDescriptor *pipelineDesc = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||
pipelineDesc->setVertexFunction(vertexFunc);
|
||||
pipelineDesc->setFragmentFunction(fragmentFunc);
|
||||
pipelineDesc->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatBGRA8Unorm);
|
||||
|
||||
s_fullScreenDraw = g_mlDevice->newRenderPipelineState(pipelineDesc, &error);
|
||||
}
|
||||
|
||||
void IMetal::Frame()
|
||||
{
|
||||
mat4 perspective;
|
||||
glm_mat4_inv(g_cameraView, g_cameraDataMap->viewprojection);
|
||||
glm_perspective(glm_rad(68),(float)g_nWindowWidth/g_nWindowHeight, 0.01, 10000, perspective);
|
||||
glm_rotate(perspective, glm_rad(90), (vec4){1,0,0,0});
|
||||
glm_scale(perspective, (vec4){1,-1,1,1});
|
||||
glm_rotate(perspective, glm_rad(90), (vec4){0,0,1,0});
|
||||
glm_mat4_mul(perspective,g_cameraDataMap->viewprojection,g_cameraDataMap->viewprojection);
|
||||
|
||||
if (g_bConfigNotify)
|
||||
{
|
||||
IRenderer::DestroyImage(g_meshDepth);
|
||||
IRenderer::DestroyImage(g_meshDepthMSAA);
|
||||
IRenderer::DestroyImage(g_meshColor);
|
||||
IRenderer::DestroyImage(g_meshColorMSAA);
|
||||
g_meshDepth = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 1);
|
||||
g_meshDepthMSAA = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 4);
|
||||
g_meshColor = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 1);
|
||||
g_meshColorMSAA = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 4);
|
||||
}
|
||||
|
||||
for (auto &step: g_StepPrepass)
|
||||
step.pPipeline->Frame(0);
|
||||
IRenderer::Begin(g_nWindowWidth, g_nWindowHeight,
|
||||
{
|
||||
{
|
||||
g_meshColor,
|
||||
0,
|
||||
ATTACHMENT_LOAD_MODE_CLEAR,
|
||||
ATTACHMENT_STORE_MODE_STORE,
|
||||
}
|
||||
},
|
||||
{
|
||||
g_meshDepth,
|
||||
0,
|
||||
ATTACHMENT_LOAD_MODE_CLEAR,
|
||||
ATTACHMENT_STORE_MODE_STORE,
|
||||
1,
|
||||
});
|
||||
for (auto &step: g_StepMeshRendering)
|
||||
step.pPipeline->Frame(0);
|
||||
IRenderer::End();
|
||||
|
||||
CMlImage *pInImage = (CMlImage*)g_meshColor;
|
||||
MTL::RenderPassDescriptor *renderPassDesc = MTL::RenderPassDescriptor::renderPassDescriptor();
|
||||
renderPassDesc->colorAttachments()->object(0)->setTexture(g_mlDrawableTexture);
|
||||
renderPassDesc->colorAttachments()->object(0)->setLoadAction(MTL::LoadActionClear);
|
||||
renderPassDesc->colorAttachments()->object(0)->setStoreAction(MTL::StoreActionStore);
|
||||
renderPassDesc->colorAttachments()->object(0)->setClearColor(MTL::ClearColor(0.1, 0.1, 0.1, 1.0));
|
||||
|
||||
MTL::RenderCommandEncoder *encoder = g_mlCommandBuffer->renderCommandEncoder(renderPassDesc);
|
||||
|
||||
encoder->setRenderPipelineState(s_fullScreenDraw);
|
||||
encoder->setFragmentTexture(pInImage->m_image, 0);
|
||||
|
||||
encoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4));
|
||||
|
||||
encoder->endEncoding();
|
||||
|
||||
for (auto &step: g_StepShading)
|
||||
step.pPipeline->Frame(0);
|
||||
for (auto &step: g_StepPostProcessing)
|
||||
step.pPipeline->Frame(0);
|
||||
for (auto &step: g_StepUI)
|
||||
step.pPipeline->Frame(0);
|
||||
}
|
||||
|
||||
void IMetal::Deinit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef ML_VIDEO_H
|
||||
#define ML_VIDEO_H
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "Metal/Metal.hpp"
|
||||
#include "QuartzCore/QuartzCore.hpp"
|
||||
|
||||
extern CA::MetalLayer *g_mlLayer;
|
||||
extern MTL::Device *g_mlDevice;
|
||||
extern MTL::CommandQueue *g_mlCommandQueue;
|
||||
extern MTL::CommandBuffer *g_mlCommandBuffer;
|
||||
extern NS::AutoreleasePool *g_mlPool;
|
||||
|
||||
extern char g_bConfigNotify;
|
||||
extern uint32_t g_nWindowWidth;
|
||||
extern uint32_t g_nWindowHeight;
|
||||
|
||||
extern CUtlVector<MTL::Texture*> g_destroyImageBuffer;
|
||||
extern CUtlVector<MTL::Buffer*> g_destroyBuffersBuffer;
|
||||
extern MTL::Texture *g_mlDrawableTexture;
|
||||
|
||||
interface IMetal
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void CreatePipelines();
|
||||
static void Frame();
|
||||
static void Deinit();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace CA {
|
||||
class MetalLayer;
|
||||
}
|
||||
|
||||
void APPLE_ConfigureLayer(CA::MetalLayer* pMetalLayer)
|
||||
{
|
||||
if (!pMetalLayer) return;
|
||||
|
||||
CAMetalLayer* nsLayer = (__bridge CAMetalLayer*)pMetalLayer;
|
||||
};
|
||||
@@ -1,266 +0,0 @@
|
||||
#include "rendering.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "console.h"
|
||||
#include "tier1/commandline.h"
|
||||
#include "input.h"
|
||||
|
||||
#define NS_PRIVATE_IMPLEMENTATION
|
||||
#define MTL_PRIVATE_IMPLEMENTATION
|
||||
#define MTK_PRIVATE_IMPLEMENTATION
|
||||
#define CA_PRIVATE_IMPLEMENTATION
|
||||
|
||||
#include "tier0/minmax_off.h"
|
||||
#include "QuartzCore/CAMetalLayer.hpp"
|
||||
#include "Metal/Metal.hpp"
|
||||
|
||||
#include "SDL3/SDL.h"
|
||||
#include "SDL3/SDL_keycode.h"
|
||||
#include "SDL3/SDL_metal.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
#include "tier0/minmax.h"
|
||||
#include "ml_video.h"
|
||||
|
||||
char g_bConfigNotify = 0;
|
||||
uint32_t g_nWindowWidth = 1280;
|
||||
uint32_t g_nWindowHeight = 720;
|
||||
|
||||
SDL_Window *g_window;
|
||||
SDL_MetalView g_mlView;
|
||||
CA::MetalLayer *g_mlLayer;
|
||||
MTL::Device *g_mlDevice;
|
||||
MTL::CommandQueue *g_mlCommandQueue;
|
||||
MTL::CommandBuffer *g_mlCommandBuffer;
|
||||
NS::AutoreleasePool *g_mlPool;
|
||||
MTL::Texture *g_mlDrawableTexture;
|
||||
|
||||
MTL::PixelFormat g_swapchainFormat;
|
||||
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include "TargetConditionals.h"
|
||||
#if TARGET_OS_IPHONE
|
||||
// iOS
|
||||
#define SDL_METAL_VIEW UI::View
|
||||
#define STBI_NO_THREAD_LOCALS
|
||||
#else
|
||||
// macOS
|
||||
#define SDL_METAL_VIEW NS::View
|
||||
#endif
|
||||
#else
|
||||
// Other platforms
|
||||
#endif
|
||||
|
||||
void IInput::SetInputMode( EInputMode mode )
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case INPUT_MODE_GAME:
|
||||
g_currentInputMode = INPUT_MODE_GAME;
|
||||
SDL_SetWindowRelativeMouseMode(g_window, true);
|
||||
return;
|
||||
default:
|
||||
g_currentInputMode = INPUT_MODE_MENU;
|
||||
SDL_SetWindowRelativeMouseMode(g_window, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EInputKey ISDL_KeyName(SDL_Keycode key)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case SDLK_ESCAPE: return KEY_ESCAPE;
|
||||
case SDLK_TAB: return KEY_TAB;
|
||||
case SDLK_RETURN: return KEY_ENTER;
|
||||
case SDLK_RCTRL: return KEY_CONTROL;
|
||||
case SDLK_LCTRL: return KEY_CONTROL;
|
||||
case SDLK_RSHIFT: return KEY_SHIFT;
|
||||
case SDLK_LSHIFT: return KEY_SHIFT;
|
||||
case SDLK_RALT: return KEY_ALT;
|
||||
case SDLK_LALT: return KEY_ALT;
|
||||
case SDLK_SPACE: return KEY_SPACE;
|
||||
|
||||
case SDLK_F1: return KEY_F1;
|
||||
case SDLK_F2: return KEY_F2;
|
||||
case SDLK_F3: return KEY_F3;
|
||||
case SDLK_F4: return KEY_F4;
|
||||
case SDLK_F5: return KEY_F5;
|
||||
case SDLK_F6: return KEY_F6;
|
||||
case SDLK_F7: return KEY_F7;
|
||||
case SDLK_F8: return KEY_F8;
|
||||
case SDLK_F9: return KEY_F9;
|
||||
case SDLK_F10: return KEY_F10;
|
||||
case SDLK_F11: return KEY_F11;
|
||||
case SDLK_F12: return KEY_F12;
|
||||
|
||||
case SDLK_1: return KEY_1;
|
||||
case SDLK_2: return KEY_2;
|
||||
case SDLK_3: return KEY_3;
|
||||
case SDLK_4: return KEY_4;
|
||||
case SDLK_5: return KEY_5;
|
||||
case SDLK_6: return KEY_6;
|
||||
case SDLK_7: return KEY_7;
|
||||
case SDLK_8: return KEY_8;
|
||||
case SDLK_9: return KEY_9;
|
||||
case SDLK_0: return KEY_0;
|
||||
|
||||
case SDLK_A: return KEY_A;
|
||||
case SDLK_B: return KEY_B;
|
||||
case SDLK_C: return KEY_C;
|
||||
case SDLK_D: return KEY_D;
|
||||
case SDLK_E: return KEY_E;
|
||||
case SDLK_F: return KEY_F;
|
||||
case SDLK_G: return KEY_G;
|
||||
case SDLK_H: return KEY_H;
|
||||
case SDLK_I: return KEY_I;
|
||||
case SDLK_J: return KEY_J;
|
||||
case SDLK_K: return KEY_K;
|
||||
case SDLK_L: return KEY_L;
|
||||
case SDLK_M: return KEY_M;
|
||||
case SDLK_N: return KEY_N;
|
||||
case SDLK_O: return KEY_O;
|
||||
case SDLK_P: return KEY_P;
|
||||
case SDLK_Q: return KEY_Q;
|
||||
case SDLK_R: return KEY_R;
|
||||
case SDLK_S: return KEY_S;
|
||||
case SDLK_T: return KEY_T;
|
||||
case SDLK_U: return KEY_U;
|
||||
case SDLK_V: return KEY_V;
|
||||
case SDLK_W: return KEY_W;
|
||||
case SDLK_X: return KEY_X;
|
||||
case SDLK_Y: return KEY_Y;
|
||||
case SDLK_Z: return KEY_Z;
|
||||
}
|
||||
return KEY_NONE;
|
||||
};
|
||||
|
||||
void IVideo_HandleEvents()
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
SDL_KeyboardEvent *key = &event.key;
|
||||
SDL_MouseMotionEvent *motion = &event.motion;
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
g_nWindowWidth = event.window.data1;
|
||||
g_nWindowHeight = event.window.data2;
|
||||
g_bConfigNotify = 2;
|
||||
break;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (!key->repeat)
|
||||
IInput::KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_DOWN);
|
||||
break;
|
||||
case SDL_EVENT_KEY_UP:
|
||||
key = &event.key;
|
||||
if (!key->repeat)
|
||||
IInput::KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_UP);
|
||||
break;
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
IInput::AxisEvent(AXIS_MOUSE_X, motion->yrel*0.022);
|
||||
IInput::AxisEvent(AXIS_MOUSE_Y, -motion->xrel*0.022);
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
{
|
||||
SDL_GamepadAxis axis = (SDL_GamepadAxis)event.gaxis.axis;
|
||||
float value = event.gaxis.value / 32768.0f;
|
||||
if (abs(event.gaxis.value)<1000)
|
||||
value = 0;
|
||||
SDL_JoystickID id = event.gaxis.which;
|
||||
|
||||
if (axis == SDL_GAMEPAD_AXIS_RIGHTY)
|
||||
{
|
||||
IInput::AxisEvent(AXIS_CONTROLLER_PITCH, value);
|
||||
}
|
||||
if (axis == SDL_GAMEPAD_AXIS_RIGHTX)
|
||||
{
|
||||
IInput::AxisEvent(AXIS_CONTROLLER_YAW, -value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
break;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void APPLE_ConfigureLayer(CA::MetalLayer* pMetalLayer);
|
||||
void IVideo::Init()
|
||||
{
|
||||
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0");
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD);
|
||||
g_window = SDL_CreateWindow("rtt", 1280, 720, SDL_WINDOW_METAL | SDL_WINDOW_HIGH_PIXEL_DENSITY);
|
||||
|
||||
int nNumGamepads = 0;
|
||||
SDL_JoystickID *pGamepads = SDL_GetGamepads(&nNumGamepads);
|
||||
for ( uint32_t i = 0; i < nNumGamepads; i++ )
|
||||
{
|
||||
SDL_OpenGamepad(pGamepads[i]);
|
||||
}
|
||||
|
||||
g_mlView = SDL_Metal_CreateView(g_window);
|
||||
g_mlLayer = (CA::MetalLayer*)SDL_Metal_GetLayer(g_mlView);
|
||||
|
||||
|
||||
|
||||
g_mlDevice = MTL::CreateSystemDefaultDevice();
|
||||
|
||||
g_mlLayer->setDevice(g_mlDevice);
|
||||
g_mlLayer->setPixelFormat(MTL::PixelFormatBGRA8Unorm);
|
||||
g_swapchainFormat = MTL::PixelFormatBGRA8Unorm;
|
||||
|
||||
g_mlCommandQueue = g_mlDevice->newCommandQueue();
|
||||
|
||||
g_mlLayer->setDrawableSize(CGSizeMake(1280, 720));
|
||||
g_mlLayer->setFramebufferOnly(false);
|
||||
|
||||
IMetal::Init();
|
||||
|
||||
}
|
||||
|
||||
void IVideo::Frame( float fDelta )
|
||||
{
|
||||
IVideo_HandleEvents();
|
||||
|
||||
NS::AutoreleasePool *pool = NS::AutoreleasePool::alloc()->init();
|
||||
g_mlLayer->setDrawableSize(CGSizeMake(g_nWindowWidth, g_nWindowHeight));
|
||||
|
||||
CA::MetalDrawable *drawable = g_mlLayer->nextDrawable();
|
||||
if (!drawable)
|
||||
return;
|
||||
g_mlDrawableTexture = drawable->texture();
|
||||
|
||||
g_mlCommandBuffer = g_mlCommandQueue->commandBuffer();
|
||||
IMetal::Frame();
|
||||
|
||||
g_mlCommandBuffer->presentDrawable(drawable);
|
||||
g_mlCommandBuffer->commit();
|
||||
g_mlCommandBuffer->waitUntilCompleted();
|
||||
for (auto &image: g_destroyImageBuffer)
|
||||
{
|
||||
image->release();
|
||||
}
|
||||
for (auto &buffer: g_destroyBuffersBuffer)
|
||||
{
|
||||
buffer->release();
|
||||
}
|
||||
g_destroyImageBuffer = {};
|
||||
g_destroyBuffersBuffer = {};
|
||||
pool->release();
|
||||
g_bConfigNotify = 0;
|
||||
}
|
||||
|
||||
void IVideo::Deinit()
|
||||
{
|
||||
g_mlCommandQueue->release();
|
||||
g_mlDevice->release();
|
||||
};
|
||||
|
||||
void IVideo::CreatePipelines( )
|
||||
{
|
||||
IMetal::CreatePipelines();
|
||||
}
|
||||
@@ -1,448 +0,0 @@
|
||||
#include "networking.h"
|
||||
#include "console.h"
|
||||
#include "engine.h"
|
||||
#include "gamemode.h"
|
||||
#include "server.h"
|
||||
#include "steam/isteamfriends.h"
|
||||
#include "steam/isteamnetworking.h"
|
||||
#include "steam/isteamnetworkingsockets.h"
|
||||
#include "steam/steam_api_common.h"
|
||||
#include "steam/steamnetworkingtypes.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier0/lib.h"
|
||||
#include "tier1/commandline.h"
|
||||
#include "tier0/network.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "baseplayer.h"
|
||||
|
||||
#include "steam/steam_api.h"
|
||||
#include "steam/steam_gameserver.h"
|
||||
#include "steam/steamnetworkingsockets.h"
|
||||
#include "steam/isteamgameserver.h"
|
||||
#include "steam/isteamnetworkingutils.h"
|
||||
#ifndef STEAMNETWORKINGSOCKETS_OPENSOURCE
|
||||
#include "steam/steam_api.h"
|
||||
#endif
|
||||
|
||||
HSteamNetConnection net_connection = 0;
|
||||
HSteamNetConnection net_server = 0;
|
||||
HSteamListenSocket net_listenSocket = -1;
|
||||
CUtlVector<IIClient*> net_clients;
|
||||
|
||||
bool net_bIsServer = false;
|
||||
static int net_nMaxPlayers = 0;
|
||||
static uint64_t net_nLastSteamID = 90071992547409920;
|
||||
|
||||
class CClientNetworkingCallbacks
|
||||
{
|
||||
STEAM_CALLBACK(CClientNetworkingCallbacks, RelayNetworkStatusChanged, SteamRelayNetworkStatus_t);
|
||||
};
|
||||
void CClientNetworkingCallbacks::RelayNetworkStatusChanged( SteamRelayNetworkStatus_t *pCallback )
|
||||
{
|
||||
};
|
||||
|
||||
class CServerNetworkingCallbacks
|
||||
{
|
||||
STEAM_GAMESERVER_CALLBACK(CServerNetworkingCallbacks, ClientConnected, SteamNetConnectionStatusChangedCallback_t);
|
||||
STEAM_GAMESERVER_CALLBACK(CServerNetworkingCallbacks, SteamNetAuthenticated, SteamNetAuthenticationStatus_t);
|
||||
};
|
||||
|
||||
void CServerNetworkingCallbacks::ClientConnected( SteamNetConnectionStatusChangedCallback_t *pCallback )
|
||||
{
|
||||
INetworking::ClientConnectedCallback(pCallback);
|
||||
};
|
||||
void CServerNetworkingCallbacks::SteamNetAuthenticated( SteamNetAuthenticationStatus_t *pCallback )
|
||||
{
|
||||
if (net_nLastSteamID == SteamGameServer()->GetSteamID().ConvertToUint64())
|
||||
return;
|
||||
net_nLastSteamID = SteamGameServer()->GetSteamID().ConvertToUint64();
|
||||
V_printf("-------------- SERVER INFO ----------------\n");
|
||||
V_printf(" STEAMID64:\t%llu\n", net_nLastSteamID);
|
||||
V_printf(" MAX PLAYERS:\t%i\n", net_nMaxPlayers);
|
||||
V_printf("-------------- TIPS -----------------------\n");
|
||||
V_printf(" players can join by using connect <STEAMID64>\n");
|
||||
V_printf("-------------------------------------------\n");
|
||||
};
|
||||
|
||||
static CServerNetworkingCallbacks *net_pServerCallbacks;
|
||||
static CClientNetworkingCallbacks *net_pClientCallbacks;
|
||||
|
||||
void INetworking::Init()
|
||||
{
|
||||
|
||||
Net_Init();
|
||||
|
||||
#ifdef STEAMNETWORKINGSOCKETS_OPENSOURCE
|
||||
GameNetworkingSockets_Init(NULL, &errMsg)
|
||||
#endif
|
||||
V_printf("Cool\n");
|
||||
if (ICommandLine::CheckParam("-steamdebug"))
|
||||
{
|
||||
SteamNetworkingUtils()->SetDebugOutputFunction(k_ESteamNetworkingSocketsDebugOutputType_Msg,
|
||||
[](ESteamNetworkingSocketsDebugOutputType severity, const char *szMessage) {
|
||||
V_printf("Steam: %s\n", szMessage);
|
||||
});
|
||||
}
|
||||
|
||||
if (ICommandLine::CheckParam("-dedicated"))
|
||||
{
|
||||
net_pServerCallbacks = new CServerNetworkingCallbacks;
|
||||
|
||||
// Run dedicated server with steam
|
||||
SteamGameServer_Init(0, 27015, 27016, eServerModeAuthentication, "0.0.0.0");
|
||||
SteamGameServer()->SetProduct("funnygame");
|
||||
SteamGameServer()->SetGameDescription("not that funny but ok");
|
||||
SteamGameServer()->SetModDir("funnygame");
|
||||
SteamGameServer()->SetDedicatedServer(true);
|
||||
|
||||
SteamGameServer()->LogOnAnonymous();
|
||||
|
||||
|
||||
net_nMaxPlayers = atoi(ICommandLine::ParamValue("-maxplayers", "128"));
|
||||
SteamGameServer()->SetMaxPlayerCount(net_nMaxPlayers);
|
||||
SteamGameServer()->SetAdvertiseServerActive(true);
|
||||
} else {
|
||||
net_pClientCallbacks = new CClientNetworkingCallbacks;
|
||||
}
|
||||
|
||||
SteamDatagramErrMsg errMsg = {};
|
||||
|
||||
SteamNetworkingUtils()->InitRelayNetworkAccess();
|
||||
|
||||
if (ICommandLine::CheckParam("-dedicated"))
|
||||
{
|
||||
net_listenSocket = SteamGameServerNetworkingSockets()->CreateListenSocketP2P(0, 0, NULL);
|
||||
net_bIsServer = true;
|
||||
} else {
|
||||
if (ICommandLine::ParamValue("-connect"))
|
||||
{
|
||||
Console()->AddCommand(CUtlString("connect %s;", ICommandLine::ParamValue("-connect")));
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
void INetworking::Deinit()
|
||||
{
|
||||
if (net_listenSocket == -1)
|
||||
return;
|
||||
if (ICommandLine::CheckParam("-dedicated"))
|
||||
SteamGameServerNetworkingSockets()->CloseListenSocket(net_listenSocket);
|
||||
else
|
||||
SteamNetworkingSockets()->CloseConnection(net_listenSocket, 0, NULL, false);
|
||||
}
|
||||
|
||||
bool INetworking::IsServer()
|
||||
{
|
||||
return net_bIsServer;
|
||||
}
|
||||
|
||||
bool INetworking::IsClient()
|
||||
{
|
||||
return !net_bIsServer;
|
||||
}
|
||||
|
||||
bool INetworking::IsConnected()
|
||||
{
|
||||
return (bool)net_server;
|
||||
}
|
||||
|
||||
void INetworking::Frame()
|
||||
{
|
||||
if (IsServer())
|
||||
{
|
||||
SteamGameServer_RunCallbacks();
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
SteamNetworkingMessage_t *pMessages[64];
|
||||
while (true)
|
||||
{
|
||||
int nMessages = SteamGameServerNetworkingSockets()->ReceiveMessagesOnConnection(client->playerHandle, pMessages, 64);
|
||||
if ( nMessages <= 0 )
|
||||
break;
|
||||
for ( int i = 0; i < nMessages; i++ )
|
||||
{
|
||||
ProcessPacket((void*)pMessages[i]->GetData(), pMessages[i]->GetSize(), client);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SteamNetworkingMessage_t *pMessages[64];
|
||||
while (true)
|
||||
{
|
||||
int nMessages = SteamNetworkingSockets()->ReceiveMessagesOnConnection(net_connection, pMessages, 64);
|
||||
if ( nMessages <= 0 )
|
||||
break;
|
||||
for ( int i = 0; i < nMessages; i++ )
|
||||
{
|
||||
ProcessPacket((void*)pMessages[i]->GetData(), pMessages[i]->GetSize(), NULL);
|
||||
pMessages[i]->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void INetworking::SendData( void *pData, uint32_t nSize, IIClient *pClient, EMessageMode messageMode )
|
||||
{
|
||||
if (!IsConnected() && IsClient())
|
||||
return;
|
||||
int nSendFlags = 0;
|
||||
switch ( messageMode )
|
||||
{
|
||||
case MESSAGE_MODE_UNRELIABLE:
|
||||
nSendFlags |= k_nSteamNetworkingSend_Unreliable;
|
||||
break;
|
||||
case MESSAGE_MODE_RELIABLE:
|
||||
nSendFlags |= k_nSteamNetworkingSend_Reliable;
|
||||
break;
|
||||
};
|
||||
/* Send to server if client is NULL */
|
||||
EResult r = k_EResultNone;
|
||||
if (pClient == NULL)
|
||||
r = SteamNetworkingSockets()->SendMessageToConnection(net_server, pData, nSize, nSendFlags, NULL);
|
||||
else
|
||||
r = SteamGameServerNetworkingSockets()->SendMessageToConnection(pClient->playerHandle, pData, nSize, nSendFlags, NULL);
|
||||
}
|
||||
void INetworking::SendDataEverybody( void *pData, uint32_t nSize, EMessageMode messageMode )
|
||||
{
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
SendData(pData, nSize, client, messageMode);
|
||||
}
|
||||
}
|
||||
|
||||
void INetworking::SendDataEverybodyExcept( void *pData, uint32_t nSize, IIClient *pClient, EMessageMode messageMode )
|
||||
{
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
if (client == pClient)
|
||||
continue;
|
||||
SendData(pData, nSize, client, messageMode);
|
||||
}
|
||||
}
|
||||
|
||||
void INetworking::SendDataEverybodyExcept( void *pData, uint32_t nSize, CBasePlayer *pPlayer, EMessageMode messageMode )
|
||||
{
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
if (client->pBasePlayer == pPlayer)
|
||||
continue;
|
||||
SendData(pData, nSize, client, messageMode);
|
||||
}
|
||||
}
|
||||
|
||||
void INetworking::ProcessPacket( void *pData, uint32_t nSize, IIClient *pClient )
|
||||
{
|
||||
Packet_t *pPacketHeader = (Packet_t*)pData;
|
||||
if (IsServer() && pPacketHeader->type != PACKET_TYPE_PLAYER_MOVEMENT)
|
||||
return;
|
||||
if (nSize < sizeof(Packet_t))
|
||||
return;
|
||||
PacketPlayer_t *pPlayerPacket = (PacketPlayer_t*)pData;
|
||||
PacketGameMode_t *pGameModePacket = (PacketGameMode_t*)pData;
|
||||
IIClient *pNewClient;
|
||||
|
||||
switch(pPacketHeader->type)
|
||||
{
|
||||
case PACKET_TYPE_PLAYER_MOVEMENT:
|
||||
if (nSize < sizeof(PacketPlayer_t))
|
||||
return;
|
||||
if (IsServer())
|
||||
{
|
||||
if (pClient->pBasePlayer)
|
||||
pClient->pBasePlayer->RecieveFromServer(pData, nSize);
|
||||
}
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
if (client->playerHandle == pPlayerPacket->playerHandle)
|
||||
{
|
||||
if (!client->pBasePlayer)
|
||||
return;
|
||||
client->pBasePlayer->RecieveFromServer(pData, nSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case PACKET_TYPE_PLAYER_JOIN:
|
||||
if (nSize != sizeof(PacketPlayer_t))
|
||||
return;
|
||||
// Player join and leave can be processed only by the clients
|
||||
pNewClient = new IIClient;
|
||||
*pNewClient = {
|
||||
.playerID = pPlayerPacket->playerID,
|
||||
.playerHandle = pPlayerPacket->playerHandle,
|
||||
};
|
||||
V_printf("%i\n",g_clients.GetSize());
|
||||
IIEngine::ConnectClient(pNewClient);
|
||||
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
CSteamID steamID = CSteamID();
|
||||
if ( client->playerID == 0)
|
||||
V_printf("%s\t", SteamFriends()->GetPlayerNickname((uint64)client->playerID));
|
||||
else
|
||||
V_printf("%s\t", SteamFriends()->GetPersonaName());
|
||||
V_printf("%llu\t", client->playerID);
|
||||
V_printf("%u\n", client->playerHandle);
|
||||
if (client->playerHandle == 0)
|
||||
g_localClient = client;
|
||||
}
|
||||
return;
|
||||
case PACKET_TYPE_PLAYER_LEAVE:
|
||||
IIEngine::DisconnectClientByHandle(pPlayerPacket->playerHandle);
|
||||
return;
|
||||
case PACKET_TYPE_GAMEMODE_START:
|
||||
V_printf("PacketGameMode\n");
|
||||
if (nSize != sizeof(PacketGameMode_t))
|
||||
return;
|
||||
GameModeManager()->StartGameMode(pGameModePacket->szName);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void INetworking::GetServerInfo()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t INetworking_IPv4ToUint(const char *szIP) {
|
||||
if (CUtlString(szIP) == "localhost")
|
||||
return 0x7F000001;
|
||||
|
||||
struct in_addr ipAdress;
|
||||
if (inet_pton(AF_INET, szIP, &ipAdress) != 1) {
|
||||
V_printf("Invalid IPv4 address: %s\n", szIP);
|
||||
return 0;
|
||||
}
|
||||
return ntohl(ipAdress.s_addr);
|
||||
}
|
||||
|
||||
void INetworking::JoinServer( const char *szIP )
|
||||
{
|
||||
g_clients = {};
|
||||
if (net_connection)
|
||||
{
|
||||
SteamNetworkingSockets()->CloseConnection(net_connection, 0, NULL, false);
|
||||
}
|
||||
SteamNetworkingIPAddr localAddress = {};
|
||||
localAddress.Clear();
|
||||
localAddress.SetIPv4(INetworking_IPv4ToUint(szIP), 27015);
|
||||
net_connection = SteamNetworkingSockets()->ConnectByIPAddress(localAddress, 0, NULL);
|
||||
net_server = net_connection;
|
||||
}
|
||||
|
||||
void INetworking::JoinServer( uint64_t nSteamID )
|
||||
{
|
||||
g_clients = {};
|
||||
if (net_connection)
|
||||
{
|
||||
SteamNetworkingSockets()->CloseConnection(net_connection, 0, NULL, false);
|
||||
}
|
||||
SteamNetworkingIdentity remoteIdentity = {};
|
||||
remoteIdentity.Clear();
|
||||
remoteIdentity.SetSteamID64(nSteamID);
|
||||
|
||||
net_connection = SteamNetworkingSockets()->ConnectP2P(remoteIdentity, 0, 0, 0);
|
||||
net_server = net_connection;
|
||||
}
|
||||
|
||||
void INetworking::ClientConnectedCallback( SteamNetConnectionStatusChangedCallback_t *pCallback )
|
||||
{
|
||||
IIClient *pClient = new IIClient;
|
||||
switch (pCallback->m_info.m_eState)
|
||||
{
|
||||
case k_ESteamNetworkingConnectionState_Connecting:
|
||||
V_printf("Awaiting connection: %llu\n",pCallback->m_info.m_identityRemote.GetSteamID64());
|
||||
SteamNetworkingSockets()->AcceptConnection(pCallback->m_hConn);
|
||||
break;
|
||||
case k_ESteamNetworkingConnectionState_Connected:
|
||||
V_printf("Connected: %llu %u\n",pCallback->m_info.m_identityRemote.GetSteamID64(), pCallback->m_hConn);
|
||||
*pClient = {
|
||||
.playerID = pCallback->m_info.m_identityRemote.GetSteamID64(),
|
||||
.playerHandle = pCallback->m_hConn,
|
||||
};
|
||||
// send out to all clients
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
PacketPlayer_t packet = {
|
||||
.playerID = pClient->playerID,
|
||||
.playerHandle = pClient->playerHandle,
|
||||
};
|
||||
packet.type = PACKET_TYPE_PLAYER_JOIN;
|
||||
SendData(&packet, sizeof(packet), client, MESSAGE_MODE_RELIABLE);
|
||||
};
|
||||
IIEngine::ConnectClient(pClient);
|
||||
// register all clients on connected one
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
PacketPlayer_t packet = {
|
||||
.playerID = client->playerID,
|
||||
.playerHandle = client->playerHandle,
|
||||
};
|
||||
if (client == pClient)
|
||||
{
|
||||
packet.playerID = 0;
|
||||
packet.playerHandle = 0;
|
||||
}
|
||||
packet.type = PACKET_TYPE_PLAYER_JOIN;
|
||||
SendData(&packet, sizeof(packet), pClient, MESSAGE_MODE_RELIABLE);
|
||||
};
|
||||
|
||||
|
||||
GameModeManager()->RestartCurrentGameMode();
|
||||
break;
|
||||
case k_ESteamNetworkingConnectionState_ClosedByPeer:
|
||||
case k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
|
||||
SteamNetworkingSockets()->CloseConnection(pCallback->m_hConn, 0, NULL, false);
|
||||
|
||||
V_printf("Disconnected: %llu %u\n",pCallback->m_info.m_identityRemote.GetSteamID64(), pCallback->m_hConn);
|
||||
IIEngine::DisconnectClientByHandle(pCallback->m_hConn);
|
||||
|
||||
// send out to all clients
|
||||
for (auto &client: g_clients)
|
||||
{
|
||||
PacketPlayer_t packet = {
|
||||
.playerID = pCallback->m_info.m_identityRemote.GetSteamID64(),
|
||||
.playerHandle = pCallback->m_hConn,
|
||||
};
|
||||
packet.type = PACKET_TYPE_PLAYER_LEAVE;
|
||||
SendData(&packet, sizeof(packet), client, MESSAGE_MODE_RELIABLE);
|
||||
};
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void INetworking_Connect( int argc, char **argv )
|
||||
{
|
||||
if (ICommandLine::CheckParam("-dedicated"))
|
||||
return;
|
||||
if (argc != 2)
|
||||
{
|
||||
V_printf("connect <IPv4>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
INetworking::JoinServer(argv[1]);
|
||||
};
|
||||
|
||||
void INetworking_ConnectFriend( int argc, char **argv )
|
||||
{
|
||||
if (ICommandLine::CheckParam("-dedicated"))
|
||||
return;
|
||||
if (argc != 2)
|
||||
{
|
||||
V_printf("connect_friend <steamid>\n");
|
||||
return;
|
||||
}
|
||||
uint64_t nFriendID = 0;
|
||||
V_sscanf(argv[1], "%llu\n", &nFriendID);
|
||||
V_printf("Connecting to %llu\n",nFriendID);
|
||||
|
||||
INetworking::JoinServer(nFriendID);
|
||||
};
|
||||
|
||||
ConCommand ConnectCmd("connect", INetworking_ConnectFriend);
|
||||
@@ -1,160 +0,0 @@
|
||||
#include "physics.h"
|
||||
#include "math3d.h"
|
||||
|
||||
PxCastResult_t IPxWorld::BoxCast( vec3 size, vec3 origin, vec3 destination, vec3 rotation )
|
||||
{
|
||||
vec3 velocity;
|
||||
PxCastResult_t result = {};
|
||||
px_cast_result r = {};
|
||||
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
velocity[i] = destination[i] - origin[i];
|
||||
|
||||
r = px_box_cast(px, size[0], size[1], size[2], PX_GLM_VEC3(origin), PX_GLM_VEC3(rotation), PX_GLM_VEC3(velocity), 1);
|
||||
|
||||
|
||||
result.bHit = r.hit;
|
||||
result.fTime = r.time;
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
{
|
||||
result.position[i] = origin[i] + velocity[i] * result.fTime;
|
||||
result.normal[i] = r.normal1.m[i];
|
||||
result.normal2[i] = r.normal2.m[i];
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CPxCollider::Spawn( float fFriction )
|
||||
{
|
||||
|
||||
};
|
||||
void CPxCollider::Destroy()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPxBallMesh::Spawn( float fFriction )
|
||||
{
|
||||
m_pCollider = px_ball(m_fRadius, {.friction = fFriction});
|
||||
};
|
||||
|
||||
void CPxBallMesh::Destroy()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPxBoxMesh::Spawn( float fFriction )
|
||||
{
|
||||
m_pCollider = px_box(m_fRadius[0], m_fRadius[1], m_fRadius[2], {.friction = fFriction});
|
||||
};
|
||||
|
||||
void CPxBoxMesh::Destroy()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPxTriangleMesh::Spawn( float fFriction )
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPxTriangleMesh::Destroy()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPxRigidKinematicPosition::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
|
||||
{
|
||||
m_pRigidBody = px_kinematic_position_body(px, pCollider->m_pCollider, matrix, params);
|
||||
};
|
||||
|
||||
void CPxRigidKinematicPosition::SetPosition( px_vec3 position )
|
||||
{
|
||||
px_setposition(px, m_pRigidBody, position);
|
||||
};
|
||||
px_vec3 CPxRigidKinematicPosition::GetPosition( void )
|
||||
{
|
||||
return px_getposition(px, m_pRigidBody);
|
||||
};
|
||||
px_matrix CPxRigidKinematicPosition::GetMatrix ( void )
|
||||
{
|
||||
return px_getmatrix(px, m_pRigidBody);
|
||||
};
|
||||
|
||||
void CPxRigidKinematicPosition::Destroy()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPxRigidBody::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
|
||||
{
|
||||
m_pRigidBody = px_rigidbody(px, pCollider->m_pCollider, matrix, params);
|
||||
};
|
||||
void CPxRigidBody::SetPosition( px_vec3 position )
|
||||
{
|
||||
px_setposition(px, m_pRigidBody, position);
|
||||
}
|
||||
|
||||
void CPxRigidBody::SetVelocity( px_vec3 velocity )
|
||||
{
|
||||
px_setvelocity(px, m_pRigidBody, velocity);
|
||||
}
|
||||
|
||||
px_vec3 CPxRigidBody::GetPosition( void )
|
||||
{
|
||||
return px_getposition(px, m_pRigidBody);
|
||||
};
|
||||
|
||||
px_vec3 CPxRigidBody::GetVelocity( void )
|
||||
{
|
||||
return px_getvelocity(px, m_pRigidBody);
|
||||
};
|
||||
|
||||
px_matrix CPxRigidBody::GetMatrix ( void )
|
||||
{
|
||||
return px_getmatrix(px, m_pRigidBody);
|
||||
};
|
||||
|
||||
void CPxRigidBody::Destroy()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPxStaticBody::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
|
||||
{
|
||||
px_staticbody(px, pCollider->m_pCollider, matrix);
|
||||
};
|
||||
px_vec3 CPxStaticBody::GetPosition( void )
|
||||
{
|
||||
return px_getposition(px, m_pCollider);
|
||||
};
|
||||
px_matrix CPxStaticBody::GetMatrix ( void )
|
||||
{
|
||||
return px_getmatrix(px, m_pCollider);
|
||||
};
|
||||
|
||||
void CPxStaticBody::Destroy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
;
|
||||
void CPxFixedBody::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
|
||||
{
|
||||
px_fixedbody(px, pCollider->m_pCollider);
|
||||
};
|
||||
px_vec3 CPxFixedBody::GetPosition( void )
|
||||
{
|
||||
return px_getposition(px, m_pCollider);
|
||||
};
|
||||
px_matrix CPxFixedBody::GetMatrix ( void )
|
||||
{
|
||||
return px_getmatrix(px, m_pCollider);
|
||||
};
|
||||
|
||||
void CPxFixedBody::Destroy()
|
||||
{
|
||||
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
#include "rendering.h"
|
||||
|
||||
CRenderingStep::CRenderingStep()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CRenderingStep::CRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CPrepassRenderingStep::CPrepassRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
|
||||
{
|
||||
Renderer()->m_StepPrepass.AppendTail({pfn(), szStepName});
|
||||
}
|
||||
|
||||
CMeshRenderingStep::CMeshRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
|
||||
{
|
||||
Renderer()->m_StepMeshRendering.AppendTail({pfn(), szStepName});
|
||||
}
|
||||
|
||||
CShadingRenderingStep::CShadingRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
|
||||
{
|
||||
Renderer()->m_StepShading.AppendTail({pfn(), szStepName});
|
||||
}
|
||||
|
||||
CPostProcessingRenderingStep::CPostProcessingRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
|
||||
{
|
||||
Renderer()->m_StepPostProcessing.AppendTail({pfn(), szStepName});
|
||||
}
|
||||
|
||||
CUIRenderingStep::CUIRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
|
||||
{
|
||||
Renderer()->m_StepUI.AppendTail({pfn(), szStepName});
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
#include "server.h"
|
||||
#include "engine.h"
|
||||
#include "input.h"
|
||||
#include "steam/steam_api_common.h"
|
||||
#include "tier1/commandline.h"
|
||||
#include "tier1/utlstring.h"
|
||||
#include "baseentity.h"
|
||||
#include "console.h"
|
||||
#include "physics.h"
|
||||
#include "input.h"
|
||||
#include "networking.h"
|
||||
|
||||
void *g_serverdll;
|
||||
ConVar g_tickrate("tickrate","64",FCVAR_PROTECTED);
|
||||
float g_fAccumulator = 0;
|
||||
|
||||
extern "C" void IGame_Load(void);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Loads game and client libraries if linking dynamically, otherwise it runs
|
||||
// IGame_Load compiled statically.
|
||||
//-----------------------------------------------------------------------------
|
||||
void IServer::LoadGame( const char *psz )
|
||||
{
|
||||
#ifndef STATIC_BUILD
|
||||
#ifdef __linux__
|
||||
g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.so", psz));
|
||||
if (!ICommandLine::CheckParam("-dedicated"))
|
||||
Plat_LoadLibrary(CUtlString("%s/bin/libclient.so", psz));
|
||||
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.dylib", psz));
|
||||
if (!ICommandLine::CheckParam("-dedicated"))
|
||||
Plat_LoadLibrary(CUtlString("%s/bin/libclient.dylib", psz));
|
||||
#endif
|
||||
void (*GameLoadfn)() = (void(*)())Plat_GetProc(g_serverdll, "IGame_Load");
|
||||
if (!GameLoadfn)
|
||||
Plat_FatalErrorFunc("IGame_Load not found in libserver.so\n");
|
||||
GameLoadfn();
|
||||
#else
|
||||
IGame_Load();
|
||||
#endif
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Updates server and client state.
|
||||
//-----------------------------------------------------------------------------
|
||||
void IServer::Think( float fDelta )
|
||||
{
|
||||
g_fAccumulator += fDelta;
|
||||
float fTickrate = 1.0/g_tickrate.GetFloat();
|
||||
|
||||
/* tickrate */
|
||||
while(g_fAccumulator>=fTickrate)
|
||||
{
|
||||
if (INetworking::IsClient())
|
||||
Input()->Frame();
|
||||
Console()->Execute();
|
||||
g_fAccumulator-=fTickrate;
|
||||
for (auto &entity: EntityManager()->m_entities)
|
||||
{
|
||||
entity->Think(fTickrate);
|
||||
entity->SendToServer();
|
||||
}
|
||||
px_frame(px, fTickrate);
|
||||
INetworking::Frame();
|
||||
}
|
||||
for (auto &entity: EntityManager()->m_entities)
|
||||
{
|
||||
if (entity->pClientEntity)
|
||||
entity->pClientEntity->Think(fDelta);
|
||||
}
|
||||
};
|
||||
|
||||
void IGame_Exit( int argc, char **argv ) {
|
||||
IEngine::Shutdown();
|
||||
Plat_Exit(0);
|
||||
}
|
||||
ConCommand ExitCmd("exit", IGame_Exit, 0);
|
||||
21
engine/sv_dll.cpp
Normal file
21
engine/sv_dll.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "sv_dll.h"
|
||||
#include "tier1/interface.h"
|
||||
#include "tier0/platform.h"
|
||||
|
||||
void CServerGameDLL::Init()
|
||||
{
|
||||
#if defined(__linux__)
|
||||
#endif
|
||||
}
|
||||
|
||||
void CServerGameDLL::Shutdown()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CServerGameDLL *ServerGameDLL()
|
||||
{
|
||||
static CServerGameDLL s_serverdll;
|
||||
return &s_serverdll;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#include "baseentity.h"
|
||||
#include "physics.h"
|
||||
|
||||
class CLight: public CBaseEntity
|
||||
{
|
||||
public:
|
||||
virtual void Precache ( void ) override;
|
||||
virtual void Spawn( void ) override;
|
||||
virtual void ReadParameter( const char *szName, const char *szValue ) override;
|
||||
virtual void Destroy( void ) override;
|
||||
virtual void Think( float fDelta ) override;
|
||||
virtual void SendToServer() override;
|
||||
virtual void RecieveFromServer( void *pData, uint32_t nDataSize ) override;
|
||||
};
|
||||
|
||||
void CLight::Precache()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CLight::Spawn()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
void CLight::ReadParameter( const char *szName, const char *szValue )
|
||||
{
|
||||
CBaseEntity::ReadParameter(szName, szValue);
|
||||
}
|
||||
|
||||
void CLight::Destroy()
|
||||
{
|
||||
|
||||
}
|
||||
void CLight::Think( float fDelta )
|
||||
{
|
||||
};
|
||||
|
||||
void CLight::SendToServer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CLight::RecieveFromServer( void *pData, uint32_t nDataSize )
|
||||
{
|
||||
};
|
||||
|
||||
DECLARE_ENTITY(light, CLight)
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "baseentity.h"
|
||||
#include "baseplayer.h"
|
||||
#include "engine.h"
|
||||
#include "tier1/utlvector.h"
|
||||
|
||||
|
||||
CUtlVector<CPlayerStart*> g_PlayerStarts = {};
|
||||
|
||||
void CPlayerStart::Precache()
|
||||
{
|
||||
}
|
||||
|
||||
void CPlayerStart::Spawn()
|
||||
{
|
||||
g_PlayerStarts.AppendTail(this);
|
||||
};
|
||||
|
||||
void CPlayerStart::ReadParameter( const char *szName, const char *szValue )
|
||||
{
|
||||
CBaseEntity::ReadParameter(szName, szValue);
|
||||
}
|
||||
|
||||
void CPlayerStart::Destroy()
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (auto &start: g_PlayerStarts)
|
||||
{
|
||||
if (start == this)
|
||||
{
|
||||
g_PlayerStarts.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerStart::Think( float fDelta )
|
||||
{
|
||||
}
|
||||
|
||||
void CPlayerStart::RoundEnd( void )
|
||||
{
|
||||
m_bIsRunning = false;
|
||||
}
|
||||
|
||||
void CPlayerStart::RoundStart(IIClient *pClient)
|
||||
{
|
||||
IIEngine::DestroyEntity(pOwningPlayer);
|
||||
if (!pClient)
|
||||
return;
|
||||
m_bIsRunning = true;
|
||||
pOwningPlayer = (CBasePlayer*)IIEngine::SpawnEntity("player");
|
||||
if (pOwningPlayer)
|
||||
{
|
||||
pOwningPlayer->pOwningSpawn = this;
|
||||
pOwningPlayer->SetPosition(m_position);
|
||||
}
|
||||
else
|
||||
V_printf("Failed to spawn player\n");
|
||||
IIEngine::InitEntity(pOwningPlayer);
|
||||
pClient->pBasePlayer = pOwningPlayer;
|
||||
};
|
||||
|
||||
void CPlayerStart::SendToServer()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void CPlayerStart::RecieveFromServer( void *pData, uint32_t nDataSize )
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
DECLARE_ENTITY(info_player_start, CPlayerStart);
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
#include "brush.h"
|
||||
|
||||
class CWorldSpawn: public CBrushEntity
|
||||
{
|
||||
public:
|
||||
virtual void Precache ( void ) override;
|
||||
virtual void Spawn( void ) override;
|
||||
virtual void ReadParameter( const char *szName, const char *szValue ) override;
|
||||
virtual void Destroy( void ) override;
|
||||
virtual void Think( float fDelta ) override;
|
||||
virtual void SendToServer() override;
|
||||
virtual void RecieveFromServer( void *pData, uint32_t nDataSize ) override;
|
||||
};
|
||||
|
||||
void CWorldSpawn::Precache()
|
||||
{
|
||||
CBrushEntity::Precache();
|
||||
}
|
||||
|
||||
void CWorldSpawn::Spawn()
|
||||
{
|
||||
CBrushEntity::Spawn();
|
||||
};
|
||||
|
||||
void CWorldSpawn::ReadParameter( const char *szName, const char *szValue )
|
||||
{
|
||||
CBrushEntity::ReadParameter(szName, szValue);
|
||||
}
|
||||
|
||||
void CWorldSpawn::Destroy()
|
||||
{
|
||||
CBrushEntity::Destroy();
|
||||
}
|
||||
|
||||
void CWorldSpawn::Think( float fDelta )
|
||||
{
|
||||
CBrushEntity::Think(fDelta);
|
||||
}
|
||||
|
||||
void CWorldSpawn::SendToServer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CWorldSpawn::RecieveFromServer( void *pData, uint32_t nDataSize )
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
DECLARE_ENTITY(worldspawn, CWorldSpawn)
|
||||
@@ -1,16 +0,0 @@
|
||||
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);
|
||||
VK_DEVICE_FUNCTION(vkCmdSetLogicOpEXT);
|
||||
VK_DEVICE_FUNCTION(vkCmdTraceRaysKHR);
|
||||
VK_DEVICE_FUNCTION(vkCreateAccelerationStructureKHR);
|
||||
VK_DEVICE_FUNCTION(vkDestroyAccelerationStructureKHR);
|
||||
VK_DEVICE_FUNCTION(vkGetAccelerationStructureBuildSizesKHR);
|
||||
VK_DEVICE_FUNCTION(vkCmdBuildAccelerationStructuresKHR);
|
||||
VK_DEVICE_FUNCTION(vkCreateRayTracingPipelinesKHR);
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "filesystem.h"
|
||||
#include "rendering.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "console.h"
|
||||
#include "tier1/commandline.h"
|
||||
|
||||
#include "vulkan/vulkan.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
|
||||
|
||||
class CVkBuffer: public IBuffer
|
||||
{
|
||||
public:
|
||||
void *Map() override;
|
||||
void Unmap() override;
|
||||
vk_buffer_t m_buffer;
|
||||
void *m_pAllocated = NULL;
|
||||
};
|
||||
|
||||
class CVkImage: public IImage
|
||||
{
|
||||
public:
|
||||
vk_image2d_t m_image = {};
|
||||
uint32_t m_usage;
|
||||
VkImageLayout m_currentLayout;
|
||||
};
|
||||
|
||||
|
||||
class CVkTexture: public ITexture
|
||||
{
|
||||
public:
|
||||
vk_image2d_t image;
|
||||
};
|
||||
|
||||
|
||||
|
||||
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 VkFormat g_swapchainFormat;
|
||||
|
||||
extern char g_bConfigNotify;
|
||||
extern uint32_t g_nWindowWidth;
|
||||
extern uint32_t g_nWindowHeight;
|
||||
|
||||
extern VkSampler g_invalidTextureSampler;
|
||||
|
||||
extern CUtlVector<ITexture*> g_textures;
|
||||
|
||||
extern IBuffer *g_cameraProperties;
|
||||
|
||||
extern IImage *g_meshDepth;
|
||||
extern IImage *g_meshDepthMSAA;
|
||||
extern IImage *g_meshColor;
|
||||
extern IImage *g_meshColorMSAA;
|
||||
1410
engine/vk_video.cpp
1410
engine/vk_video.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,107 +0,0 @@
|
||||
#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<uint8_t> &spirv, VkShaderStageFlagBits shaderStage );
|
||||
void Destroy( void );
|
||||
|
||||
VkShaderModule m_shaderModule = NULL;
|
||||
VkPipelineShaderStageCreateInfo m_stageCreateInfo;
|
||||
};
|
||||
|
||||
struct vk_tripipeline_t
|
||||
{
|
||||
void Create(
|
||||
CUtlVector<vk_shader_t> &shaders,
|
||||
CUtlVector<VkDescriptorSetLayoutBinding> &bindings,
|
||||
uint32_t pushConstantsSize,
|
||||
uint32_t nVertexSize,
|
||||
CUtlVector<VertexAttribute_t> vertexFormat,
|
||||
CUtlVector<VkFormat> formats
|
||||
/* the rest of the stuff is set by the dynamic state */
|
||||
/* literally */
|
||||
);
|
||||
void Destroy();
|
||||
CUtlVector<vk_shader_t> m_shaders;
|
||||
VkDescriptorSetLayout m_descriptorSetLayout;
|
||||
VkPipelineLayout m_layout;
|
||||
VkPipeline m_pipeline;
|
||||
};
|
||||
|
||||
struct vk_comppipeline_t
|
||||
{
|
||||
void Create(
|
||||
vk_shader_t &shader,
|
||||
CUtlVector<VkDescriptorSetLayoutBinding> &bindings,
|
||||
uint32_t pushConstantsSize
|
||||
);
|
||||
void Destroy();
|
||||
VkDescriptorSetLayout m_descriptorSetLayout;
|
||||
VkPipelineLayout m_layout;
|
||||
VkPipeline m_pipeline;
|
||||
};
|
||||
|
||||
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, VkSampleCountFlagBits samples);
|
||||
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 CreatePipelines();
|
||||
static void Frame();
|
||||
static void Deinit();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,452 +0,0 @@
|
||||
#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<VkCommandBuffer> g_commandBuffers;
|
||||
VkCommandBuffer g_vkCommandBuffer;
|
||||
CUtlVector<vk_framedata_t> g_frameData;
|
||||
CUtlVector<VkImage> g_swapchainImages;
|
||||
CUtlVector<VkImageView> g_swapchainImageViews;
|
||||
VkImageView g_swapchainImageView;
|
||||
VkImage g_swapchainImage;
|
||||
|
||||
uint32_t g_nNumSwapchainImages = 0;
|
||||
|
||||
#define VK_DEVICE_FUNCTION(name) PFN_##name _##name
|
||||
#include "vk_external_functions.cpp"
|
||||
#undef VK_DEVICE_FUNCTION
|
||||
|
||||
char g_bConfigNotify = 0;
|
||||
uint32_t g_nWindowWidth = 1280;
|
||||
uint32_t g_nWindowHeight = 720;
|
||||
|
||||
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<VkSurfaceFormatKHR> 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<VkPresentModeKHR> 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<VkImage>(g_nNumSwapchainImages);
|
||||
g_swapchainImageViews = CUtlVector<VkImageView>(g_nNumSwapchainImages);
|
||||
g_commandBuffers = CUtlVector<VkCommandBuffer>(g_nNumSwapchainImages);
|
||||
g_frameData = CUtlVector<vk_framedata_t>(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);
|
||||
}
|
||||
};
|
||||
|
||||
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<VkPhysicalDevice> 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()];
|
||||
VkPhysicalDeviceProperties Properties = {};
|
||||
vkGetPhysicalDeviceProperties(g_vkPhysicalDevice, &Properties);
|
||||
V_printf("Using %s\n", Properties.deviceName);
|
||||
|
||||
/* queue family */
|
||||
uint32_t nNumQueueFamilies = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL);
|
||||
CUtlVector<VkQueueFamilyProperties> 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();
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -1,566 +0,0 @@
|
||||
#include "SDL3/SDL_gamepad.h"
|
||||
#include "SDL3/SDL_joystick.h"
|
||||
#include "rendering.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "console.h"
|
||||
#include "tier1/commandline.h"
|
||||
#include "input.h"
|
||||
|
||||
#include "vulkan/vulkan.h"
|
||||
#include "SDL3/SDL.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
#include "SDL3/SDL_keycode.h"
|
||||
#include "SDL3/SDL_vulkan.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
|
||||
#define VULKAN_RENDERING_IMPL
|
||||
#include "vk_video.h"
|
||||
|
||||
#define VMA_VULKAN_VERSION 1004000
|
||||
#define VMA_IMPLEMENTATION
|
||||
#include "tier0/minmax_off.h"
|
||||
#include "vk_mem_alloc.h"
|
||||
#include "tier0/minmax.h"
|
||||
|
||||
SDL_Window *g_window;
|
||||
|
||||
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<VkCommandBuffer> g_commandBuffers;
|
||||
VkCommandBuffer g_vkCommandBuffer;
|
||||
CUtlVector<vk_framedata_t> g_frameData;
|
||||
CUtlVector<VkImage> g_swapchainImages;
|
||||
CUtlVector<VkImageView> g_swapchainImageViews;
|
||||
VkImageView g_swapchainImageView;
|
||||
VkImage g_swapchainImage;
|
||||
VkFormat g_swapchainFormat;
|
||||
|
||||
uint32_t g_nNumSwapchainImages = 0;
|
||||
|
||||
|
||||
char g_bConfigNotify = 0;
|
||||
uint32_t g_nWindowWidth = 1280;
|
||||
uint32_t g_nWindowHeight = 720;
|
||||
|
||||
#define VK_DEVICE_FUNCTION(name) PFN_##name _##name
|
||||
#include "vk_external_functions.cpp"
|
||||
#undef VK_DEVICE_FUNCTION
|
||||
|
||||
void IVideo_SwapchainInit()
|
||||
{
|
||||
|
||||
/* swapchain */
|
||||
SDL_Vulkan_CreateSurface(g_window, g_vkInstance, NULL, &g_surface);
|
||||
|
||||
VkSurfaceCapabilitiesKHR surfaceCapatibilities = {};
|
||||
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vkPhysicalDevice, g_surface, &surfaceCapatibilities);
|
||||
|
||||
const VkFormat preferedSurfaceFormats[] = {
|
||||
VK_FORMAT_B8G8R8A8_UNORM,
|
||||
VK_FORMAT_R8G8B8A8_UNORM,
|
||||
};
|
||||
|
||||
uint32_t numSurfaceFormats = 0;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_surface, &numSurfaceFormats, NULL);
|
||||
CUtlVector<VkSurfaceFormatKHR> 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++)
|
||||
{
|
||||
if (format.format == preferedSurfaceFormats[i])
|
||||
{
|
||||
selectedFormat = format;
|
||||
goto formatPicked;
|
||||
}
|
||||
}
|
||||
}
|
||||
formatPicked:
|
||||
|
||||
uint32_t numSurfacePresentModes = 0;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, g_surface, &numSurfacePresentModes, NULL);
|
||||
CUtlVector<VkPresentModeKHR> 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 | VK_IMAGE_USAGE_TRANSFER_DST_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<VkImage>(g_nNumSwapchainImages);
|
||||
g_swapchainImageViews = CUtlVector<VkImageView>(g_nNumSwapchainImages);
|
||||
g_commandBuffers = CUtlVector<VkCommandBuffer>(g_nNumSwapchainImages);
|
||||
g_frameData = CUtlVector<vk_framedata_t>(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]);
|
||||
}
|
||||
g_swapchainFormat = selectedFormat.format;
|
||||
|
||||
|
||||
/* 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);
|
||||
}
|
||||
};
|
||||
|
||||
EInputKey ISDL_KeyName(SDL_Keycode key)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case SDLK_ESCAPE: return KEY_ESCAPE;
|
||||
case SDLK_TAB: return KEY_TAB;
|
||||
case SDLK_RETURN: return KEY_ENTER;
|
||||
case SDLK_RCTRL: return KEY_CONTROL;
|
||||
case SDLK_LCTRL: return KEY_CONTROL;
|
||||
case SDLK_RSHIFT: return KEY_SHIFT;
|
||||
case SDLK_LSHIFT: return KEY_SHIFT;
|
||||
case SDLK_RALT: return KEY_ALT;
|
||||
case SDLK_LALT: return KEY_ALT;
|
||||
case SDLK_SPACE: return KEY_SPACE;
|
||||
|
||||
case SDLK_GRAVE: return KEY_TILDE;
|
||||
|
||||
case SDLK_F1: return KEY_F1;
|
||||
case SDLK_F2: return KEY_F2;
|
||||
case SDLK_F3: return KEY_F3;
|
||||
case SDLK_F4: return KEY_F4;
|
||||
case SDLK_F5: return KEY_F5;
|
||||
case SDLK_F6: return KEY_F6;
|
||||
case SDLK_F7: return KEY_F7;
|
||||
case SDLK_F8: return KEY_F8;
|
||||
case SDLK_F9: return KEY_F9;
|
||||
case SDLK_F10: return KEY_F10;
|
||||
case SDLK_F11: return KEY_F11;
|
||||
case SDLK_F12: return KEY_F12;
|
||||
|
||||
case SDLK_1: return KEY_1;
|
||||
case SDLK_2: return KEY_2;
|
||||
case SDLK_3: return KEY_3;
|
||||
case SDLK_4: return KEY_4;
|
||||
case SDLK_5: return KEY_5;
|
||||
case SDLK_6: return KEY_6;
|
||||
case SDLK_7: return KEY_7;
|
||||
case SDLK_8: return KEY_8;
|
||||
case SDLK_9: return KEY_9;
|
||||
case SDLK_0: return KEY_0;
|
||||
|
||||
case SDLK_A: return KEY_A;
|
||||
case SDLK_B: return KEY_B;
|
||||
case SDLK_C: return KEY_C;
|
||||
case SDLK_D: return KEY_D;
|
||||
case SDLK_E: return KEY_E;
|
||||
case SDLK_F: return KEY_F;
|
||||
case SDLK_G: return KEY_G;
|
||||
case SDLK_H: return KEY_H;
|
||||
case SDLK_I: return KEY_I;
|
||||
case SDLK_J: return KEY_J;
|
||||
case SDLK_K: return KEY_K;
|
||||
case SDLK_L: return KEY_L;
|
||||
case SDLK_M: return KEY_M;
|
||||
case SDLK_N: return KEY_N;
|
||||
case SDLK_O: return KEY_O;
|
||||
case SDLK_P: return KEY_P;
|
||||
case SDLK_Q: return KEY_Q;
|
||||
case SDLK_R: return KEY_R;
|
||||
case SDLK_S: return KEY_S;
|
||||
case SDLK_T: return KEY_T;
|
||||
case SDLK_U: return KEY_U;
|
||||
case SDLK_V: return KEY_V;
|
||||
case SDLK_W: return KEY_W;
|
||||
case SDLK_X: return KEY_X;
|
||||
case SDLK_Y: return KEY_Y;
|
||||
case SDLK_Z: return KEY_Z;
|
||||
}
|
||||
return KEY_NONE;
|
||||
};
|
||||
|
||||
void IVideo::Init()
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD);
|
||||
g_window = SDL_CreateWindow("rtt", 1280, 720, SDL_WINDOW_VULKAN);
|
||||
|
||||
int nNumGamepads = 0;
|
||||
SDL_JoystickID *pGamepads = SDL_GetGamepads(&nNumGamepads);
|
||||
for ( uint32_t i = 0; i < nNumGamepads; i++ )
|
||||
{
|
||||
SDL_OpenGamepad(pGamepads[i]);
|
||||
}
|
||||
|
||||
unsigned int nExtensionCount = 0;
|
||||
const char* const* szExtensions = SDL_Vulkan_GetInstanceExtensions(&nExtensionCount);
|
||||
|
||||
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;
|
||||
|
||||
instanceCreateInfo.enabledExtensionCount = nExtensionCount;
|
||||
instanceCreateInfo.ppEnabledExtensionNames = szExtensions;
|
||||
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<VkPhysicalDevice> 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()];
|
||||
VkPhysicalDeviceProperties Properties = {};
|
||||
vkGetPhysicalDeviceProperties(g_vkPhysicalDevice, &Properties);
|
||||
V_printf("Using %s\n", Properties.deviceName);
|
||||
|
||||
/* queue family */
|
||||
uint32_t nNumQueueFamilies = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL);
|
||||
CUtlVector<VkQueueFamilyProperties> 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;
|
||||
|
||||
VkPhysicalDeviceShaderObjectFeaturesEXT pdsofe = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT,
|
||||
.pNext = 0,
|
||||
.shaderObject = VK_TRUE,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT pdeds3fe = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT,
|
||||
.pNext = &pdsofe,
|
||||
.extendedDynamicState3DepthClampEnable = VK_TRUE,
|
||||
.extendedDynamicState3PolygonMode = VK_TRUE,
|
||||
.extendedDynamicState3RasterizationSamples = VK_TRUE,
|
||||
.extendedDynamicState3SampleMask = VK_TRUE,
|
||||
.extendedDynamicState3AlphaToCoverageEnable = VK_TRUE,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceVulkan13Features pdv13f = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
|
||||
.pNext = &pdeds3fe,
|
||||
.synchronization2 = VK_TRUE,
|
||||
.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_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();
|
||||
|
||||
IVulkan::Init();
|
||||
}
|
||||
|
||||
void IInput::SetInputMode( EInputMode mode )
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case INPUT_MODE_GAME:
|
||||
SDL_SetWindowRelativeMouseMode(g_window, true);
|
||||
return;
|
||||
case INPUT_MODE_MENU:
|
||||
SDL_SetWindowRelativeMouseMode(g_window, false);
|
||||
return;
|
||||
case INPUT_MODE_CONSOLE:
|
||||
SDL_SetWindowRelativeMouseMode(g_window, true);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ConVar m_pitch("m_pitch", "0.022", FCVAR_ARCHIVE);
|
||||
ConVar m_yaw("m_yaw", "0.022", FCVAR_ARCHIVE);
|
||||
void IVideo_HandleEvents()
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
SDL_KeyboardEvent *key = &event.key;
|
||||
SDL_MouseMotionEvent *motion = &event.motion;
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_WINDOW_RESIZED:
|
||||
g_nWindowWidth = event.window.data1;
|
||||
g_nWindowHeight = event.window.data2;
|
||||
g_bConfigNotify = 2;
|
||||
break;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (!key->repeat)
|
||||
Input()->KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_DOWN);
|
||||
break;
|
||||
case SDL_EVENT_KEY_UP:
|
||||
key = &event.key;
|
||||
if (!key->repeat)
|
||||
Input()->KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_UP);
|
||||
break;
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
Input()->AxisEvent(AXIS_MOUSE_X, motion->yrel*m_pitch.GetFloat());
|
||||
Input()->AxisEvent(AXIS_MOUSE_Y, -motion->xrel*m_yaw.GetFloat());
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
{
|
||||
SDL_GamepadAxis axis = (SDL_GamepadAxis)event.gaxis.axis;
|
||||
float value = event.gaxis.value / 32768.0f;
|
||||
if (abs(event.gaxis.value)<1000)
|
||||
value = 0;
|
||||
SDL_JoystickID id = event.gaxis.which;
|
||||
|
||||
if (axis == SDL_GAMEPAD_AXIS_RIGHTY)
|
||||
{
|
||||
Input()->AxisEvent(AXIS_CONTROLLER_PITCH, value);
|
||||
}
|
||||
if (axis == SDL_GAMEPAD_AXIS_RIGHTX)
|
||||
{
|
||||
Input()->AxisEvent(AXIS_CONTROLLER_YAW, -value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
break;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
break;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void IVideo::CreatePipelines( )
|
||||
{
|
||||
IVulkan::CreatePipelines();
|
||||
};
|
||||
|
||||
void IVideo::Frame( float fDelta )
|
||||
{
|
||||
static uint32_t s_frameID = 0;
|
||||
IVideo_HandleEvents();
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user