working on rendering

This commit is contained in:
2025-12-23 15:03:44 +02:00
parent 5a71b3023a
commit 3b4e2eea32
65 changed files with 1971 additions and 190 deletions

3
.gitmodules vendored
View File

@@ -22,3 +22,6 @@
[submodule "external/Vulkan-Utility-Libraries"] [submodule "external/Vulkan-Utility-Libraries"]
path = external/Vulkan-Utility-Libraries path = external/Vulkan-Utility-Libraries
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries
[submodule "external/slang"]
path = external/slang
url = https://github.com/shader-slang/slang.git

View File

@@ -83,7 +83,7 @@ CUtlString client_lib;
#include "rapier/__build.cpp" #include "rapier/__build.cpp"
#include "engine/__build.cpp" #include "engine/__build.cpp"
#include "shadercompiler/__build.cpp"
#include "launcher/__build.cpp" #include "launcher/__build.cpp"
#include "funnyassets/__build.cpp" #include "funnyassets/__build.cpp"

View File

@@ -18,7 +18,63 @@ extern "C" void FunnyMain( int argc, char **argv )
ServerGameDLL()->Init(); ServerGameDLL()->Init();
IShader *pShader = NULL;
IBuffer *pCameraInfoBuffer = NULL;
IMaterial *pMaterial = NULL;
IImage *pOutputImage = NULL;
IVertexBuffer *pVertices = NULL;
float vertices[9] = {
0,-0.5, 0,
0.5,0.5, 0,
-0.5,0.5, 0,
};
pVertices = g_pRenderContext->CreateVertexBuffer(36);
void *pMapped = pVertices->Map();
V_memcpy(pMapped, vertices, 36);
pVertices->Unmap();
pCameraInfoBuffer = g_pRenderContext->CreateConstantBuffer(64);
pShader = g_pRenderContext->CreateShader("funnygame/core/shaders/flat.shader_c");
pMaterial = g_pRenderContext->CreateMaterial(pShader);
pMaterial->PSSetConstantsBuffer(0, pCameraInfoBuffer);
pOutputImage = g_pRenderContext->CreateRenderTarget(
g_pRenderContext->GetNewOutputImageWidth(),
g_pRenderContext->GetNewOutputImageHeight(),
IMAGE_FORMAT_RGBA8_UNORM,
MULTISAMPLE_TYPE_NONE);
IRenderCommandList *pCommandList = g_pRenderContext->CreateCommandList();
pCommandList->StartRecording();
pCommandList->SetRenderTarget(0, pOutputImage);
pCommandList->SetMaterial(pMaterial);
pCommandList->SetVertexBuffer(0, pVertices);
pCommandList->DrawPrimitives(3, 0, 1, 0);
pCommandList->EndRecording();
for (;;) { for (;;) {
/*
if (g_pRenderContext->BIsOutputImageOutdated())
{
uint32_t nWidth;
uint32_t nHeight;
pOutputImage = g_pRenderContext->CreateRenderTarget(
g_pRenderContext->GetNewOutputImageWidth(),
g_pRenderContext->GetNewOutputImageHeight(),
IMAGE_FORMAT_RGBA8_UNORM,
MULTISAMPLE_TYPE_NONE);
}
*/
g_pRenderContext->SubmitCommandList(pCommandList);
g_pRenderContext->SetOutputImage(pOutputImage);
gamewindow->UpdateWindow(); gamewindow->UpdateWindow();
Materials()->Frame(0); Materials()->Frame(0);
}; };

View File

@@ -83,6 +83,7 @@ public:
delete pHandle; delete pHandle;
} }
virtual CUtlBuffer<unsigned char> Read( IFileHandle *pFile ) override { return NULL; }; virtual CUtlBuffer<unsigned char> Read( IFileHandle *pFile ) override { return NULL; };
virtual const char *ReadString( IFileHandle *pFile ) override { return NULL; };
}; };
EXPOSE_FILESYSTEM(CPAKFileSystem, "pakfs"); EXPOSE_FILESYSTEM(CPAKFileSystem, "pakfs");

BIN
external/linux/libgfx.so vendored Executable file

Binary file not shown.

BIN
external/linux/libgfx.so.0.2025.24.2 vendored Normal file

Binary file not shown.

BIN
external/linux/libslang-compiler.so vendored Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
external/linux/libslang-llvm.so vendored Normal file

Binary file not shown.

BIN
external/linux/libslang-rt.so vendored Executable file

Binary file not shown.

Binary file not shown.

BIN
external/linux/libslang.so vendored Executable file

Binary file not shown.

1
external/slang vendored Submodule

Submodule external/slang added at 5d775e2829

Binary file not shown.

View File

@@ -157,6 +157,7 @@ CUtlString CClangLinker::Link( LinkProject_t *pProject )
if (pProject->m_target.kernel == TARGET_KERNEL_LINUX || pProject->m_target.kernel == TARGET_KERNEL_ANDROID) if (pProject->m_target.kernel == TARGET_KERNEL_LINUX || pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{ {
args.AppendTail("-rdynamic"); args.AppendTail("-rdynamic");
args.AppendTail("-Wl,-rpath,$ORIGIN");
} }
// Dynamic libraries // Dynamic libraries
@@ -180,6 +181,11 @@ CUtlString CClangLinker::Link( LinkProject_t *pProject )
args.AppendTail("-l"); args.AppendTail("-l");
args.AppendTail(lib); args.AppendTail(lib);
} }
for (auto lib: pProject->libraryDirectories)
{
args.AppendTail("-L");
args.AppendTail(lib);
}
// Apple frameworks // Apple frameworks
for (auto &directory: pProject->frameworkDirectories) for (auto &directory: pProject->frameworkDirectories)

View File

@@ -63,6 +63,9 @@ void IEngine_Signal(int sig)
Plat_Backtrace(); Plat_Backtrace();
Plat_FatalErrorFunc("Fault"); Plat_FatalErrorFunc("Fault");
break; break;
case SIGINT:
Plat_Exit(0);
break;
default: default:
break; break;
}; };

View File

@@ -37,7 +37,6 @@ DECLARE_BUILD_STAGE(assets)
filesystem2->CopyDirectory("build", "tools"); filesystem2->CopyDirectory("build", "tools");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/maps"); filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/maps");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/shaders");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/fonts"); filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/fonts");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/textures"); filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/textures");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/materials"); filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/materials");
@@ -49,13 +48,14 @@ DECLARE_BUILD_STAGE(assets)
build_shader("fgui_text_frag"); build_shader("fgui_text_frag");
build_shader("fgui_text_vert"); build_shader("fgui_text_vert");
*/ */
build_shader("flat");
CUtlVector<CUtlString> python_args = { CUtlVector<CUtlString> python_args = {
"build/tools/makepak64.py", "build/tools/makepak64.py",
CUtlString("build/funnygame/assets"), CUtlString("build/funnygame/assets"),
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "rtt") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "rtt"), bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "rtt") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "rtt"),
}; };
runner->Run("python3", python_args); runner->Run("python3", python_args);
filesystem2->CopyDirectory(CUtlString("%s/funnygame/core", szOutputDir.GetString()),"build/funnygame/assets");
/*
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS ||Target_t::DefaultTarget().kernel == TARGET_KERNEL_DARWIN) if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS ||Target_t::DefaultTarget().kernel == TARGET_KERNEL_DARWIN)
{ {
python_args = { python_args = {
@@ -66,15 +66,14 @@ DECLARE_BUILD_STAGE(assets)
runner->Run("python3", python_args); runner->Run("python3", python_args);
} else { } else {
filesystem2->CopyDirectory(CUtlString("%s/funnygame", szOutputDir.GetString()),"build/funnygame/vulkan/shaders"); filesystem2->CopyDirectory(CUtlString("%s/funnygame", szOutputDir.GetString()),"build/funnygame/vulkan/shaders");
/*
python_args = { python_args = {
"build/tools/makepak64.py", "build/tools/makepak64.py",
CUtlString("build/funnygame/vulkan"), CUtlString("build/funnygame/vulkan"),
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "vulkan") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "vulkan"), bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "vulkan") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "vulkan"),
}; };
runner->Run("python3", python_args); runner->Run("python3", python_args);
*/
} }
*/
runner->Wait(); runner->Wait();
if (bStaticBuild) if (bStaticBuild)

View File

@@ -0,0 +1,48 @@
#define COMMON using namespace Common; namespace Common
#ifdef VS_SHADER
#define VS using namespace VertexShader; namespace VertexShader
#else
#define VS namespace VertexShader_DO_NOT_USE
#endif
#ifdef PS_SHADER
#define PS using namespace PixelShader; namespace PixelShader
#else
#define PS namespace PixelShader_DO_NOT_USE
#endif
COMMON
{
struct PS_INPUT
{
float4 m_vPosition : SV_Position;
}
}
VS
{
cbuffer CameraInfo
{
float4x4 m_viewProj;
};
struct VS_INPUT
{
float3 m_vPosition: POSITION;
}
PS_INPUT vsMain( VS_INPUT i )
{
PS_INPUT o;
o.m_vPosition = { i.m_vPosition, 1 };
return o;
}
}
PS
{
float4 psMain( PS_INPUT i )
{
return float4(1);
}
}

View File

@@ -0,0 +1,2 @@
[Inputs]

View File

@@ -1,23 +0,0 @@
struct VS_INPUT
{
float3 m_vPosition;
}
struct PS_INPUT
{
float4 m_vPosition;
}
[shader("vertex")]
PS_INPUT vsMain( VS_INPUT i )
{
PS_INPUT o;
o.m_vPosition = { i.m_vPosition, 1 };
return o;
}
[shader("pixel")]
float4 psMain( PS_INPUT i )
{
return float4(1);
}

View File

@@ -83,7 +83,7 @@ void C_MOBAPlayer::Spawn()
pVertexBuffer->Unmap(); pVertexBuffer->Unmap();
m_pMesh = IMeshRendering::CreateMesh(); m_pMesh = IMeshRendering::CreateMesh();
m_pMesh->SetVertexBuffer(pVertexBuffer); m_pMesh->SetVertexBuffer(0, pVertexBuffer);
m_pMeshInstance = m_pMesh->CreateInstance(); m_pMeshInstance = m_pMesh->CreateInstance();
}; };

View File

@@ -82,6 +82,7 @@ int main( int argc, char **argv ) {
// chdir to right directory // chdir to right directory
dirname(szLauncherPath); dirname(szLauncherPath);
chdir(szLauncherPath); chdir(szLauncherPath);
printf("%s\n",szLauncherPath);
pEngineMain(argc, argv); pEngineMain(argc, argv);
dlclose(pEngineLib); dlclose(pEngineLib);

View File

@@ -6,11 +6,15 @@
CUtlVector<CUtlString> MaterialSystem_CompiledFiles = { CUtlVector<CUtlString> MaterialSystem_CompiledFiles = {
"materialsystem/materialsystem.cpp", "materialsystem/materialsystem.cpp",
"materialsystem/compiledshader.cpp",
"materialsystem/vulkan/shaderparser.cpp",
"materialsystem/vulkan/rendercontext.cpp", "materialsystem/vulkan/rendercontext.cpp",
"materialsystem/vulkan/material.cpp",
"materialsystem/vulkan/commandbuffer.cpp", "materialsystem/vulkan/commandbuffer.cpp",
"materialsystem/vulkan/utils.cpp", "materialsystem/vulkan/rendercommandlist.cpp",
"materialsystem/vulkan/material.cpp",
"materialsystem/vulkan/shader.cpp", "materialsystem/vulkan/shader.cpp",
"materialsystem/vulkan/utils.cpp",
"materialsystem/vulkan/vma.cpp",
"materialsystem/vulkan/commands/draw.cpp", "materialsystem/vulkan/commands/draw.cpp",
"materialsystem/vulkan/commands/base.cpp", "materialsystem/vulkan/commands/base.cpp",
"materialsystem/vulkan/libraries/raster.cpp", "materialsystem/vulkan/libraries/raster.cpp",

View File

@@ -0,0 +1,145 @@
#include "shadercompiler/icompiler.h"
#include "materialsystem/compiledshadermgr.h"
#include "tier2/ifilesystem.h"
uint32_t CCompiledShader::AllocateLump( uint32_t nSize )
{
m_lumps.AppendTail({V_malloc(nSize),nSize});
return m_lumps.GetSize()-1;
}
void *CCompiledShader::GetLumpPtr( uint32_t nLump )
{
return m_lumps[nLump].m_pAddress;
}
uint32_t CCompiledShader::GetLumpSize( uint32_t nLump )
{
return m_lumps[nLump].m_nSize;
}
ShaderObject_t *CCompiledShader::AllocateShader()
{
m_objects.AppendTail({});
return &m_objects[m_objects.GetSize()-1];
}
ShaderObject_t *CCompiledShader::FindShaderObject( EShaderBackend eBackend, EShaderStage eStage )
{
for ( auto &o: m_objects )
{
if ( o.m_eBackend != eBackend )
continue;
if ( o.m_eStage != eStage )
continue;
return &o;
}
return NULL;
}
CCompiledShader::~CCompiledShader()
{
for ( auto l: m_lumps )
V_free(l.m_pAddress);
}
class CCompiledShaderManager: public ICompiledShaderManager
{
public:
virtual void WriteToFile( CCompiledShader *pShader, const char *szFile ) override;
virtual void ReadFromFile( CCompiledShader *pShader, const char *szFile ) override;
};
void CCompiledShaderManager::WriteToFile( CCompiledShader *pShader, const char *szFile )
{
IFileHandle *pFile;
ShaderHeader_t stHeader = {};
uint32_t nTotalSize = sizeof(ShaderHeader_t);
stHeader.m_cSignature[0] = 'f';
stHeader.m_cSignature[1] = 's';
stHeader.m_cSignature[2] = 'h';
stHeader.m_cSignature[3] = 'o';
stHeader.m_nNumLumps = pShader->m_lumps.GetSize();
stHeader.m_nNumShaders = pShader->m_objects.GetSize();
pFile = filesystem->Open(szFile, FILEMODE_WRITE);
pFile->Write(&stHeader, sizeof(ShaderHeader_t));
// We want to get offset for the lump data
nTotalSize += sizeof(ShaderLump_t) * pShader->m_lumps.GetSize();
nTotalSize += sizeof(ShaderObject_t) * pShader->m_objects.GetSize();
// ShaderLump_t
for ( auto l: pShader->m_lumps )
{
ShaderLump_t stLump = {};
stLump.m_nOffset = nTotalSize;
stLump.m_nSize = l.m_nSize;
pFile->Write(&stLump, sizeof(ShaderLump_t));
nTotalSize += l.m_nSize;
}
// ShaderObject_t
for ( auto o: pShader->m_objects )
{
}
// Lump Data
for ( auto l: pShader->m_lumps )
{
pFile->Write(l.m_pAddress, l.m_nSize);
}
pFile->Close();
}
void CCompiledShaderManager::ReadFromFile( CCompiledShader *pShader, const char *szFile )
{
IFileHandle *pFile;
ShaderHeader_t stHeader = {};
int i = 0;
CUtlVector<ShaderLump_t> lumps = {};
CUtlVector<ShaderObject_t> objects = {};
CUtlVector<HostShaderLump_t> lumpsData = {};
pFile = filesystem->Open(szFile, FILEMODE_READ);
pFile->Read(&stHeader, sizeof(ShaderHeader_t));
objects.Resize(stHeader.m_nNumShaders);
lumps.Resize(stHeader.m_nNumLumps);
lumpsData.Resize(stHeader.m_nNumLumps);
pFile->Read(lumps.GetData(), stHeader.m_nNumLumps * sizeof(ShaderLump_t));
pFile->Read(objects.GetData(), stHeader.m_nNumShaders * sizeof(ShaderObject_t));
for ( i = 0; i < stHeader.m_nNumLumps; i++ )
{
lumpsData[i].m_pAddress = V_malloc(lumps[i].m_nSize);
pFile->Seek(SEEKMODE_RELATIVE_START, lumps[i].m_nOffset);
pFile->Read(lumpsData[i].m_pAddress, lumps[i].m_nSize);
lumpsData[i].m_nSize = lumps[i].m_nSize;
};
pShader->m_objects = objects;
pShader->m_lumps = lumpsData;
pFile->Close();
}
ICompiledShaderManager *CompiledShaderManager()
{
static CCompiledShaderManager s_CompiledShaderManager;
return &s_CompiledShaderManager;
}

View File

@@ -6,31 +6,25 @@ public:
virtual void Init() override; virtual void Init() override;
virtual void Frame( float fTime ) override; virtual void Frame( float fTime ) override;
virtual void Shutdown() override; virtual void Shutdown() override;
virtual IRenderContext *GetRenderContext( void ) override;
}; };
extern IRenderContext *g_pVkRenderContext;
IRenderContext *g_pRenderContext;
void CMaterialSystem::Init() void CMaterialSystem::Init()
{ {
GetRenderContext()->Init(); g_pRenderContext = (IRenderContext*)CreateInterface(RENDER_CONTEXT_INTERFACE_NAME, NULL);
g_pRenderContext->Init();
} }
void CMaterialSystem::Frame( float fTime ) void CMaterialSystem::Frame( float fTime )
{ {
GetRenderContext()->Frame(fTime); g_pRenderContext->Frame(fTime);
} }
void CMaterialSystem::Shutdown() void CMaterialSystem::Shutdown()
{ {
GetRenderContext()->Shutdown(); g_pRenderContext->Shutdown();
}
extern IRenderContext *g_pVkRenderContext;
IRenderContext *CMaterialSystem::GetRenderContext( void )
{
return g_pVkRenderContext;
} }

View File

@@ -240,9 +240,9 @@ void CVkCommandBuffer::TryBarrier( int iCurrent, int iCurrentBuffer )
imageMemoryBarrier.dstAccessMask = VulkanGetAccessFlags(barrier.m_eNewDependency); imageMemoryBarrier.dstAccessMask = VulkanGetAccessFlags(barrier.m_eNewDependency);
if (barrier.m_eOldDependency == DEPENDENCY_MODE_FROM_PREVIOUS) if (barrier.m_eOldDependency == DEPENDENCY_MODE_FROM_PREVIOUS)
{ {
imageMemoryBarrier.oldLayout = VulkanGetImageLayout(pImage->m_eLastUsage); imageMemoryBarrier.oldLayout = VulkanGetImageLayout(DEPENDENCY_MODE_ALL_COMMANDS);
imageMemoryBarrier.srcStageMask = VulkanGetStageFlags(pImage->m_eLastUsage); imageMemoryBarrier.srcStageMask = VulkanGetStageFlags(DEPENDENCY_MODE_ALL_COMMANDS);
imageMemoryBarrier.srcAccessMask = VulkanGetAccessFlags(pImage->m_eLastUsage); imageMemoryBarrier.srcAccessMask = VulkanGetAccessFlags(DEPENDENCY_MODE_ALL_COMMANDS);
} else { } else {
imageMemoryBarrier.oldLayout = VulkanGetImageLayout(barrier.m_eOldDependency); imageMemoryBarrier.oldLayout = VulkanGetImageLayout(barrier.m_eOldDependency);
imageMemoryBarrier.srcStageMask = VulkanGetStageFlags(barrier.m_eOldDependency); imageMemoryBarrier.srcStageMask = VulkanGetStageFlags(barrier.m_eOldDependency);

View File

@@ -13,16 +13,6 @@ BEGIN_VULKAN_COMMAND(ClearColor)
IImage **ppSwapchainImages = NULL; IImage **ppSwapchainImages = NULL;
END_VULKAN_COMMAND(ClearColor) END_VULKAN_COMMAND(ClearColor)
struct VulkanRenderOutput_t {
EResolveMode m_eResolveMode;
VkFrameObject_t m_stImage;
VkFrameObject_t m_stResolveImage;
ELoadMode m_eLoadMode;
EStoreMode m_eStoreMode;
};
BEGIN_VULKAN_COMMAND(Begin) BEGIN_VULKAN_COMMAND(Begin)
CUtlVector<VulkanRenderOutput_t> images; CUtlVector<VulkanRenderOutput_t> images;
VulkanRenderOutput_t stDepthImage; VulkanRenderOutput_t stDepthImage;
@@ -35,6 +25,36 @@ END_VULKAN_COMMAND(Begin)
BEGIN_VULKAN_COMMAND(End) BEGIN_VULKAN_COMMAND(End)
END_VULKAN_COMMAND(End) END_VULKAN_COMMAND(End)
BEGIN_VULKAN_COMMAND(SetVertexBuffer)
uint32_t uBinding;
IVertexBuffer *pBuffer;
END_VULKAN_COMMAND(SetVertexBuffer)
BEGIN_VULKAN_COMMAND(SetShader)
IShader *pShader;
END_VULKAN_COMMAND(SetShader)
BEGIN_VULKAN_COMMAND(DrawPrimitives)
uint32_t nVertexCount;
uint32_t nFirstVertex;
uint32_t nInstanceCount;
uint32_t nFirstInstance;
END_VULKAN_COMMAND(DrawPrimitives)
BEGIN_VULKAN_COMMAND(SetScissors)
uint32_t uX;
uint32_t uY;
uint32_t uWidth;
uint32_t uHeight;
END_VULKAN_COMMAND(SetScissors)
BEGIN_VULKAN_COMMAND(SetViewport)
uint32_t uX;
uint32_t uY;
uint32_t uWidth;
uint32_t uHeight;
END_VULKAN_COMMAND(SetViewport)
BEGIN_VULKAN_COMMAND(Empty) BEGIN_VULKAN_COMMAND(Empty)
END_VULKAN_COMMAND(Empty) END_VULKAN_COMMAND(Empty)

View File

@@ -31,10 +31,10 @@ DECLARE_VULKAN_COMMAND(ClearColor)
DECLARE_VULKAN_COMMAND(Begin) DECLARE_VULKAN_COMMAND(Begin)
{ {
VkRenderingInfo stRenderingInfo = {}; VkRenderingInfo stRenderingInfo = {};
CUtlVector<VkRenderingAttachmentInfo> attachments; CUtlVector<VkRenderingAttachmentInfo> attachments = {};
for (auto i: images) for (auto i: images)
{ {
VkRenderingAttachmentInfo a; VkRenderingAttachmentInfo a = {};
a.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; a.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
a.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; a.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
a.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; a.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -47,6 +47,7 @@ DECLARE_VULKAN_COMMAND(Begin)
stRenderingInfo.layerCount = 1; stRenderingInfo.layerCount = 1;
stRenderingInfo.colorAttachmentCount = attachments.GetSize(); stRenderingInfo.colorAttachmentCount = attachments.GetSize();
stRenderingInfo.pColorAttachments = attachments.GetData(); stRenderingInfo.pColorAttachments = attachments.GetData();
stRenderingInfo.renderArea = (VkRect2D){0,0,nResolutionX,nResolutionY};
vkCmdBeginRendering(hCommandBuffer, &stRenderingInfo); vkCmdBeginRendering(hCommandBuffer, &stRenderingInfo);
} }
@@ -55,3 +56,21 @@ DECLARE_VULKAN_COMMAND(End)
{ {
vkCmdEndRendering(hCommandBuffer); vkCmdEndRendering(hCommandBuffer);
} }
DECLARE_VULKAN_COMMAND(SetShader)
{
CVkShader *pVkShader = (CVkShader*)pShader;
vkCmdBindPipeline(hCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pVkShader->m_hPipeline);
}
DECLARE_VULKAN_COMMAND(SetVertexBuffer)
{
CVkBuffer *pVkBuffer = (CVkBuffer*)pBuffer;
VkDeviceSize uOffset = 0;
vkCmdBindVertexBuffers(hCommandBuffer, uBinding, 1, &pVkBuffer->m_buffer, &uOffset);
}
DECLARE_VULKAN_COMMAND(DrawPrimitives)
{
vkCmdDraw(hCommandBuffer, nVertexCount, nInstanceCount, nFirstVertex, nFirstInstance);
}

View File

@@ -3,7 +3,8 @@
#include "tier1/utlbuffer.h" #include "tier1/utlbuffer.h"
#include "tier1/utlvector.h" #include "tier1/utlvector.h"
#include "tier2/ifilesystem.h" #include "tier2/ifilesystem.h"
#include "vulkan/vulkan_core.h" #include "../shaderparser.h"
BEGIN_BUILD_PIPELINE_LIBRARY(VertexDescription) BEGIN_BUILD_PIPELINE_LIBRARY(VertexDescription)
library.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT; library.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
@@ -48,3 +49,250 @@ void CVkVertexDescriptionPipelineLibrary::SetTopology( ETopologyMode eTopology )
{ {
m_eTopology = VulkanGetTopology(eTopology); m_eTopology = VulkanGetTopology(eTopology);
} }
struct VulkanDescriptorInit_t
{
CUtlVector<VkDescriptorSetLayoutBinding> m_bindings = {};
VkDescriptorSetLayoutCreateInfo m_set = {};
};
BEGIN_BUILD_PIPELINE_LIBRARY(VertexTransform)
library.flags = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
VkPipelineRasterizationStateCreateInfo rasterState = {};
VkPipelineViewportStateCreateInfo viewportState = {};
int i = 0;
CUtlVector<VulkanDescriptor_t> vertexDescriptors = ShaderParser()->GetDescriptors(m_pShader, SHADER_STAGE_VERTEX);
VulkanDescriptorInit_t inits[SHADER_STAGE_COUNT] = {};
CUtlVector<CUtlBuffer<unsigned char>> spirvs = {};
CUtlVector<VkPipelineShaderStageCreateInfo> stages = {};
CUtlVector<VkShaderModuleCreateInfo> stageShaders = {};
for ( auto desc: vertexDescriptors )
{
VkDescriptorSetLayoutBinding binding = {};
binding.descriptorCount = 1;
binding.descriptorType = desc.eDescriptorType;
binding.binding = desc.uBinding;
inits[desc.eDescriptorType].m_bindings.AppendTail(binding);
}
for ( i = 0; i < SHADER_STAGE_COUNT; i++)
{
inits[i].m_set.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
inits[i].m_set.bindingCount = inits[i].m_bindings.GetSize();
inits[i].m_set.pBindings = inits[i].m_bindings.GetData();
vkCreateDescriptorSetLayout(g_vkDevice, &inits[i].m_set, NULL, &m_setLayouts[i] );
}
for ( i = 0; i < SHADER_STAGE_COUNT; i++)
{
if ( i == SHADER_STAGE_PIXEL )
continue;
CUtlBuffer<unsigned char> code = ShaderParser()->GetShaderCode(m_pShader, (EShaderStage)i);
// We may fail loading the specific stage
if (code.GetSize() == 0)
continue;
VkShaderModuleCreateInfo mod = {};
mod.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
mod.codeSize = code.GetSize();
VkPipelineShaderStageCreateInfo shader = {};
shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader.pName = "main";
shader.stage = VulkanGetShaderStage((EShaderStage)i);
spirvs.AppendTail(code);
stageShaders.AppendTail(mod);
stages.AppendTail(shader);
}
// Fix pointers
for ( i = 0; i < stages.GetSize(); i++ )
{
stageShaders[i].pCode = (uint32_t*)spirvs[i].GetMemory();
stages[i].pNext = &stageShaders[i];
}
VkPipelineLayoutCreateInfo stPipelineLayout = {};
stPipelineLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
stPipelineLayout.setLayoutCount = SHADER_STAGE_COUNT;
stPipelineLayout.pSetLayouts = m_setLayouts;
stPipelineLayout.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT ;
vkCreatePipelineLayout(g_vkDevice, &stPipelineLayout, NULL, &m_layout);
rasterState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterState.polygonMode = VK_POLYGON_MODE_FILL;
rasterState.lineWidth = 1;
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
VkDynamicState dynamicStates[] = {
VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT,
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT,
};
VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = 2;
dynamicState.pDynamicStates = dynamicStates;
pipeline.stageCount = stages.GetSize();
pipeline.pStages = stages.GetData();
pipeline.pDynamicState = &dynamicState;
pipeline.pRasterizationState = &rasterState;
pipeline.pViewportState = &viewportState;
pipeline.layout = m_layout;
END_BUILD_PIPELINE_LIBRARY()
void CVkVertexTransformPipelineLibrary::SetShader( CCompiledShader *pShader )
{
m_pShader = pShader;
}
BEGIN_BUILD_PIPELINE_LIBRARY(PixelShader)
printf("--- PixelShader ---\n");
VkPipelineDepthStencilStateCreateInfo depthStencil = {};
int i = 0;
CUtlVector<VulkanDescriptor_t> vertexDescriptors = ShaderParser()->GetDescriptors(m_pShader, SHADER_STAGE_PIXEL);
VulkanDescriptorInit_t inits[SHADER_STAGE_COUNT] = {};
for ( auto desc: vertexDescriptors )
{
VkDescriptorSetLayoutBinding binding = {};
binding.descriptorCount = 1;
binding.descriptorType = desc.eDescriptorType;
binding.binding = desc.uBinding;
inits[desc.eDescriptorType].m_bindings.AppendTail(binding);
}
for ( i = 0; i < SHADER_STAGE_COUNT; i++)
{
inits[i].m_set.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
inits[i].m_set.bindingCount = inits[i].m_bindings.GetSize();
inits[i].m_set.pBindings = inits[i].m_bindings.GetData();
vkCreateDescriptorSetLayout(g_vkDevice, &inits[i].m_set, NULL, &m_setLayouts[i] );
}
VkPipelineLayoutCreateInfo stPipelineLayout = {};
stPipelineLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
stPipelineLayout.setLayoutCount = SHADER_STAGE_COUNT;
stPipelineLayout.pSetLayouts = m_setLayouts;
stPipelineLayout.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT ;
vkCreatePipelineLayout(g_vkDevice, &stPipelineLayout, NULL, &m_layout);
CUtlBuffer<unsigned char> spirv = {};
VkPipelineShaderStageCreateInfo shader = {};
VkShaderModuleCreateInfo mod = {};
for ( auto desc: vertexDescriptors )
{
VkDescriptorSetLayoutBinding binding = {};
binding.descriptorCount = 1;
binding.descriptorType = desc.eDescriptorType;
binding.binding = desc.uBinding;
inits[desc.eDescriptorType].m_bindings.AppendTail(binding);
}
for ( i = 0; i < SHADER_STAGE_COUNT; i++)
{
inits[i].m_set.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
inits[i].m_set.bindingCount = inits[i].m_bindings.GetSize();
inits[i].m_set.pBindings = inits[i].m_bindings.GetData();
vkCreateDescriptorSetLayout(g_vkDevice, &inits[i].m_set, NULL, &m_setLayouts[i] );
}
spirv = ShaderParser()->GetShaderCode(m_pShader, SHADER_STAGE_PIXEL);
if (spirv.GetSize() == 0)
goto skipshader;
mod.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
mod.codeSize = spirv.GetSize();
mod.pCode = (uint32_t*)spirv.GetMemory();
shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader.pName = "main";
shader.stage = VulkanGetShaderStage(SHADER_STAGE_PIXEL);
shader.pNext = &mod;
pipeline.stageCount = 1;
pipeline.pStages = &shader;
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.minDepthBounds = 0;
depthStencil.maxDepthBounds = 1;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
pipeline.pDepthStencilState = &depthStencil;
skipshader:
library.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
pipeline.layout = m_layout;
END_BUILD_PIPELINE_LIBRARY()
void CVkPixelShaderPipelineLibrary::SetShader( CCompiledShader *pShader )
{
m_pShader = pShader;
}
BEGIN_BUILD_PIPELINE_LIBRARY(PixelOutput)
printf("--- PixelOutput ---\n");
VkPipelineMultisampleStateCreateInfo msaa = {};
VkPipelineRenderingCreateInfo render = {};
VkPipelineDepthStencilStateCreateInfo depthStencil = {};
VkPipelineColorBlendStateCreateInfo blend = {};
CUtlVector<VkPipelineColorBlendAttachmentState> attachments = {};
msaa.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
msaa.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
render.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
render.colorAttachmentCount = m_eFormats.GetSize();
render.pColorAttachmentFormats = m_eFormats.GetData();
render.depthAttachmentFormat = VK_FORMAT_D32_SFLOAT;;
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.minDepthBounds = 0;
depthStencil.maxDepthBounds = 1;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
for ( auto e: m_eFormats )
{
VkPipelineColorBlendAttachmentState a = {};
a.blendEnable = VK_TRUE;
a.blendEnable = VK_TRUE;
a.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
a.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
a.colorBlendOp = VK_BLEND_OP_ADD;
a.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
a.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
a.alphaBlendOp = VK_BLEND_OP_ADD;
attachments.AppendTail(a);
}
blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
blend.attachmentCount = m_eFormats.GetSize();
blend.pAttachments = attachments.GetData();
pipeline.pDepthStencilState = &depthStencil;
pipeline.pColorBlendState = &blend;
pipeline.pMultisampleState = &msaa;
render.pNext = pipeline.pNext;
pipeline.pNext = &render;
library.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
END_BUILD_PIPELINE_LIBRARY()
void CVkPixelOutputPipelineLibrary::AddAttachment( EImageFormat eFormat )
{
m_eFormats.AppendTail(CVkImage::GetImageFormat(eFormat));
}

View File

@@ -0,0 +1,36 @@
#include "vulkan_state.h"
CVkMaterial::CVkMaterial( IShader *pShader )
{
m_pVkShader = (CVkShader*)pShader;
}
CVkMaterial::~CVkMaterial()
{
}
void CVkMaterial::VSSetShaderResource( uint32_t uRegister, IRenderingObject *pResource )
{
SetShaderResource(uRegister, SHADER_STAGE_VERTEX, pResource);
}
void CVkMaterial::PSSetShaderResource( uint32_t uRegister, IRenderingObject *pResource )
{
SetShaderResource(uRegister, SHADER_STAGE_PIXEL, pResource);
}
void CVkMaterial::VSSetConstantsBuffer( uint32_t uRegister, IBuffer *pConstants )
{
SetShaderResource(uRegister, SHADER_STAGE_VERTEX, pConstants);
}
void CVkMaterial::PSSetConstantsBuffer( uint32_t uRegister, IBuffer *pConstants )
{
SetShaderResource(uRegister, SHADER_STAGE_PIXEL, pConstants);
}
void CVkMaterial::SetShaderResource( uint32_t uRegister, uint32_t uSet, IRenderingObject *pObject)
{
}

View File

@@ -1,4 +1,5 @@
#include "materialsystem/imaterialsystem.h" #include "materialsystem/imaterialsystem.h"
#include "materialsystem/compiledshadermgr.h"
#include "tier1/utlvector.h" #include "tier1/utlvector.h"
#include "vulkan_state.h" #include "vulkan_state.h"
@@ -13,11 +14,28 @@ BEGIN_DEFINE_PIPELINE_LIBRARY(VertexDescription)
END_DEFINE_PIPELINE_LIBRARY() END_DEFINE_PIPELINE_LIBRARY()
BEGIN_DEFINE_PIPELINE_LIBRARY(VertexTransform) BEGIN_DEFINE_PIPELINE_LIBRARY(VertexTransform)
void SetShader( CCompiledShader *pShader );
CCompiledShader *m_pShader;
VkDescriptorSetLayout m_setLayouts[SHADER_STAGE_COUNT];
VkPipelineLayout m_layout;
END_DEFINE_PIPELINE_LIBRARY() END_DEFINE_PIPELINE_LIBRARY()
BEGIN_DEFINE_PIPELINE_LIBRARY(PixelShade) BEGIN_DEFINE_PIPELINE_LIBRARY(PixelShader)
void SetShader( CCompiledShader *pShader );
void SetDepthRequired( bool b );
CCompiledShader *m_pShader;
VkDescriptorSetLayout m_setLayouts[SHADER_STAGE_COUNT];
VkPipelineLayout m_layout;
bool m_bIsDepthRequired = false;
END_DEFINE_PIPELINE_LIBRARY() END_DEFINE_PIPELINE_LIBRARY()
BEGIN_DEFINE_PIPELINE_LIBRARY(PixelOutput) BEGIN_DEFINE_PIPELINE_LIBRARY(PixelOutput)
void AddAttachment( EImageFormat eFormat );
void SetDepthRequired( bool b );
CUtlVector<VkFormat> m_eFormats = {};
bool m_bIsDepthRequired = false;
END_DEFINE_PIPELINE_LIBRARY() END_DEFINE_PIPELINE_LIBRARY()

View File

@@ -0,0 +1,193 @@
#include "vulkan_state.h"
#include "commands.h"
void CVkRenderCommandList::ResetRendering()
{
/*
for ( auto m: m_materials)
{
delete m.m_pCommandBuffer;
}
*/
m_materials = {};
}
void CVkRenderCommandList::SetRenderTarget( uint32_t uIndex, IImage *pImage )
{
SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER);
VulkanRenderOutput_t *pOutput = FindOrCreateRenderOutput(uIndex);
pOutput->m_stImage.m_pSingle = pImage;
}
void CVkRenderCommandList::SetClearColor( uint32_t uIndex, float r, float g, float b, float a )
{
SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER);
VulkanRenderOutput_t *pOutput = FindOrCreateRenderOutput(uIndex);
pOutput->m_fClearColor[0] = r;
pOutput->m_fClearColor[1] = g;
pOutput->m_fClearColor[2] = b;
pOutput->m_fClearColor[3] = a;
}
void CVkRenderCommandList::SetDepthTarget( IImage *pDepth )
{
SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER);
m_depth.m_stImage.m_pSingle = pDepth;
}
void CVkRenderCommandList::SetClearDepth( float fVal)
{
SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER);
m_depth.m_fClearDepth = fVal;
}
void CVkRenderCommandList::SetRenderResolution( uint32_t iWidth, uint32_t iHeight )
{
SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER);
}
void CVkRenderCommandList::SetScissors( uint32_t uX, uint32_t uY, uint32_t uWidth, uint32_t uHeight )
{
SwitchRenderingStage(RENDERING_STAGE_RASTER);
}
void CVkRenderCommandList::SetViewport( uint32_t uX, uint32_t uY, uint32_t uWidth, uint32_t uHeight, float fMinDepth, float fMaxDepth )
{
SwitchRenderingStage(RENDERING_STAGE_RASTER);
}
void CVkRenderCommandList::SetMaterial( IMaterial *pMaterial )
{
SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER);
bool bWasCreated = false;
m_pCurrentMaterialBuffer = FindOrCreateMaterialCommandBuffer(pMaterial, &bWasCreated);
if (bWasCreated)
{
m_pCurrentMaterialBuffer->Reset();
CVkBeginCommand *pBeginCommand = CREATE_COMMAND(Begin);
pBeginCommand->images = m_pOutput;
pBeginCommand->nResolutionX = 1280;
pBeginCommand->nResolutionY = 720;
pBeginCommand->stDepthImage = m_depth;
for ( auto &i: pBeginCommand->images)
{
pBeginCommand->AddDependency(i.m_stImage.m_pSingle, DEPENDENCY_MODE_DRAWCALL_OUTPUT_IMAGE);
}
m_pCurrentMaterialBuffer->AddCommand(pBeginCommand);
CVkSetShaderCommand *pSetShader = CREATE_COMMAND(SetShader);
pSetShader->pShader = ((CVkMaterial*)pMaterial)->m_pVkShader;
m_pCurrentMaterialBuffer->AddCommand(pSetShader);
CVkSetScissorsCommand *pScissorsCommand = CREATE_COMMAND(SetScissors);
CVkSetViewportCommand *pViewportCommand = CREATE_COMMAND(SetViewport);
}
}
void CVkRenderCommandList::SetVertexBuffer( uint32_t uBinding, IVertexBuffer *pBuffer )
{
SwitchRenderingStage(RENDERING_STAGE_RASTER);
CVkSetVertexBufferCommand *pCmd = CREATE_COMMAND(SetVertexBuffer);
pCmd->uBinding = uBinding;
pCmd->pBuffer = pBuffer;
m_pCurrentMaterialBuffer->AddCommand(pCmd);
}
void CVkRenderCommandList::SetIndexBuffer( IVertexBuffer *pBuffer )
{
SwitchRenderingStage(RENDERING_STAGE_RASTER);
}
void CVkRenderCommandList::DrawPrimitives( uint32_t nVertexCount, uint32_t nFirstVertex, uint32_t nInstanceCount, uint32_t nFirstInstance )
{
SwitchRenderingStage(RENDERING_STAGE_RASTER);
CVkDrawPrimitivesCommand *pCmd = CREATE_COMMAND(DrawPrimitives);
pCmd->nVertexCount = nVertexCount;
pCmd->nFirstVertex = nFirstVertex;
pCmd->nInstanceCount = nInstanceCount;
pCmd->nFirstInstance = nFirstInstance;
m_pCurrentMaterialBuffer->AddCommand(pCmd);
}
void CVkRenderCommandList::DrawPrimitivesIndexed( uint32_t nIndexCount, uint32_t nFirstIndex, uint32_t nVertexOffset, uint32_t nInstanceCount, uint32_t nFirstInstance )
{
SwitchRenderingStage(RENDERING_STAGE_RASTER);
}
void CVkRenderCommandList::ResolveImage( IImage *pOriginal, IImage *pResolved )
{
SwitchRenderingStage(RENDERING_STAGE_POST_RASTER);
}
void CVkRenderCommandList::StartRecording()
{
ResetRendering();
}
void CVkRenderCommandList::EndRecording()
{
for ( auto m: m_materials)
{
CVkEndCommand *pEndCommand = CREATE_COMMAND(End);
m.m_pCommandBuffer->AddCommand(pEndCommand);
m.m_pCommandBuffer->Render();
}
}
void CVkRenderCommandList::Submit()
{
for ( auto m: m_materials)
{
m.m_pCommandBuffer->Submit();
}
}
void CVkRenderCommandList::SwitchRenderingStage( EVulkanRenderingStage eStage )
{
}
VulkanRenderOutput_t *CVkRenderCommandList::FindOrCreateRenderOutput( uint32_t uIndex )
{
for ( auto &v: m_pOutput )
{
if (v.m_uIndex == uIndex)
return &v;
}
VulkanRenderOutput_t output = {};
output.m_uIndex = uIndex;
m_pOutput.AppendTail(output);
return &m_pOutput[m_pOutput.GetSize()-1];
}
IVkCommandBuffer *CVkRenderCommandList::FindOrCreateMaterialCommandBuffer( IMaterial *pMaterial, bool *pbWasCreated )
{
for (auto &m: m_materials)
{
if (m.m_pMaterial == pMaterial)
{
if (pbWasCreated)
*pbWasCreated = false;
return m.m_pCommandBuffer;
}
}
VulkanMaterialCommandBuffer_t mat;
mat.m_pCommandBuffer = g_pCommandBufferManager->CreateCommandBuffer();
mat.m_pMaterial = pMaterial;
m_materials.AppendTail(mat);
if (pbWasCreated)
*pbWasCreated = true;
return m_materials.GetLast().m_pCommandBuffer;
}

View File

@@ -31,17 +31,18 @@ VkQueue g_vkDrawQueue;
VkQueue g_vkPresentQueue; VkQueue g_vkPresentQueue;
VkInstance g_vkInstance; VkInstance g_vkInstance;
VmaAllocator g_vkAllocator;
VkPhysicalDevice g_vkPhysicalDevice; VkPhysicalDevice g_vkPhysicalDevice;
VkDevice g_vkDevice; VkDevice g_vkDevice;
VkSwapchainKHR g_vkSwapchain; VkSwapchainKHR g_vkSwapchain;
CUtlVector<VkFence> g_vkFences; CUtlVector<VkFence> g_vkFences = {};
CUtlVector<VkSemaphore> g_vkGraphicsSemaphores; CUtlVector<VkSemaphore> g_vkGraphicsSemaphores = {};
CUtlVector<VkSemaphore> g_vkPresentSemaphores; CUtlVector<VkSemaphore> g_vkPresentSemaphores = {};
CUtlVector<VkCommandPool> g_vkCommandPools; CUtlVector<VkCommandPool> g_vkCommandPools = {};
CUtlVector<IImage*> g_vkSwapchainImages; CUtlVector<IImage*> g_vkSwapchainImages = {};
VkFormat g_vkWindowImageFormat; VkFormat g_vkWindowImageFormat;
@@ -50,9 +51,14 @@ CVkImage::CVkImage()
} }
CVkImage::CVkImage( uint32_t nWidth, uint32_t nHeight, EImageFormat eFormat, EMultisampleType eMultisampleType) CVkImage::CVkImage( uint32_t nWidth, uint32_t nHeight, uint32_t nDepth, EImageFormat eFormat, EMultisampleType eMultisampleType, EImageType eImageType, VkImageUsageFlagBits eUsage )
{ {
CreateImage(nWidth, nHeight, eFormat, eMultisampleType); m_nWidth = nWidth;
m_nHeight = nHeight;
m_eMultisampleType = eMultisampleType;
m_eImageType = eImageType;
m_eFormat = eFormat;
CreateImage(nWidth, nHeight, eFormat, eMultisampleType, eUsage);
CreateImageView(); CreateImageView();
} }
@@ -107,9 +113,26 @@ VkFormat CVkImage::GetImageFormat( enum EImageFormat eImageFormat )
} }
} }
void CVkImage::CreateImage( uint32_t nWidth, uint32_t nHeight, EImageFormat eFormat, EMultisampleType eMultisampleType ) void CVkImage::CreateImage( uint32_t nWidth, uint32_t nHeight, EImageFormat eFormat, EMultisampleType eMultisampleType, VkImageUsageFlagBits eUsage )
{ {
VkImageCreateInfo stCreateInfo = {};
VmaAllocationCreateInfo stAlloc = {};
stCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
stCreateInfo.imageType = VK_IMAGE_TYPE_2D;
stCreateInfo.extent.width = nWidth;
stCreateInfo.extent.height = nHeight;
stCreateInfo.extent.depth = 1;
stCreateInfo.mipLevels = 1;
stCreateInfo.arrayLayers = 1;
stCreateInfo.usage = eUsage;
stCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
stCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
stCreateInfo.format = GetImageFormat(eFormat);
stCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
stAlloc.usage = VMA_MEMORY_USAGE_AUTO;
vmaCreateImage(g_vkAllocator, &stCreateInfo, &stAlloc, &m_image, &m_allocation, NULL);
} }
void CVkImage::CreateImageView() void CVkImage::CreateImageView()
@@ -159,6 +182,28 @@ EMultisampleType CVkImage::GetMultisampleType()
CVkBuffer::CVkBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage, uint32_t nAlignment ) CVkBuffer::CVkBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage, uint32_t nAlignment )
{ {
VkBufferUsageFlags2CreateInfo stUsage = {};
VkBufferCreateInfo stBufferInfo = {};
VmaAllocationCreateInfo stAllocInfo = {};
VkBufferDeviceAddressInfo stAddress = {};
stUsage.sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO;
stUsage.usage = eUsage | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT;
stBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
stBufferInfo.size = nSize;
stBufferInfo.pNext = &stUsage;
stAllocInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
stAllocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
vmaCreateBuffer(g_vkAllocator, &stBufferInfo, &stAllocInfo, &m_buffer, &m_allocation, NULL);
stAddress.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
stAddress.buffer = m_buffer;
m_address = vkGetBufferDeviceAddress(g_vkDevice, &stAddress);
m_nSize = nSize;
} }
CVkBuffer::~CVkBuffer() CVkBuffer::~CVkBuffer()
@@ -169,12 +214,10 @@ CVkBuffer::~CVkBuffer()
void CVkBuffer::SetDebugName( const char *szName ) void CVkBuffer::SetDebugName( const char *szName )
{ {
} }
void CVkBuffer::Lock() void CVkBuffer::Lock()
{ {
} }
void CVkBuffer::Unlock() void CVkBuffer::Unlock()
@@ -184,21 +227,22 @@ void CVkBuffer::Unlock()
void *CVkBuffer::Map() void *CVkBuffer::Map()
{ {
void *pData;
pData = NULL;
vmaMapMemory(g_vkAllocator, m_allocation, &pData);
return pData;
} }
void CVkBuffer::Unmap() void CVkBuffer::Unmap()
{ {
vmaUnmapMemory(g_vkAllocator, m_allocation);
} }
uint32_t CVkBuffer::GetSize() uint32_t CVkBuffer::GetSize()
{ {
return m_nSize;
} }
class CVkRenderContext: public IRenderContext class CVkRenderContext: public IRenderContext
{ {
public: public:
@@ -206,8 +250,17 @@ public:
virtual void Frame( float fDeltaTime ) override; virtual void Frame( float fDeltaTime ) override;
virtual void Shutdown() override; virtual void Shutdown() override;
virtual void SetOutputImage( IImage *pImage ) override;
virtual bool BIsOutputImageOutdated() override;
virtual uint32_t GetNewOutputImageWidth() override;
virtual uint32_t GetNewOutputImageHeight() override;
virtual EImageFormat GetNewOutputImageFormat() override;
virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) override; virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) override;
virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) override; virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) override;
virtual IBuffer *CreateConstantBuffer( uint32_t nSize ) override;
virtual IBuffer *CreateStorageBuffer( uint32_t nSize ) override;
virtual void DestroyBuffer( IBuffer *pBuffer ) override; virtual void DestroyBuffer( IBuffer *pBuffer ) override;
virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) override; virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) override;
@@ -218,16 +271,14 @@ public:
IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage ); IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage );
virtual IShader *CreateShader( const char *szName ) override; virtual IShader *CreateShader( const char *szName ) override;
virtual void DestroyShader( IShader *pMaterial ) override; virtual void DestroyShader( IShader *pShader ) override;
virtual IMaterial *CreateMaterial( IShader *pShader ) override; virtual IMaterial *CreateMaterial( IShader *pShader ) override;
virtual void DestroyMaterial( IMaterial *pMaterial ) override; virtual void DestroyMaterial( IMaterial *pMaterial ) override;
virtual void SetMaterial( IMaterial *pMaterial ) override; virtual IRenderCommandList *CreateCommandList() override;
virtual void SetVertexBuffer( IVertexBuffer *pBuffer ) override; virtual void DestroyCommandList( IRenderCommandList *pCommandList ) override;
virtual void SetIndexBuffer( IVertexBuffer *pBuffer ) override; virtual void SubmitCommandList(IRenderCommandList *pList) override;
virtual void DrawPrimitives( uint32_t nVertexCount, uint32_t nFirstVertex, uint32_t nInstanceCount, uint32_t nFirstInstance ) override;
virtual void DrawPrimitivesIndexed( uint32_t nIndexCount, uint32_t nFirstIndex, uint32_t nVertexOffset, uint32_t nInstanceCount, uint32_t nFirstInstance ) override;
private: private:
VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices ); VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices );
CUtlVector<const char *> GetDeviceExtensions(); CUtlVector<const char *> GetDeviceExtensions();
@@ -236,17 +287,45 @@ private:
void CreateSwapchain(); void CreateSwapchain();
void DestroySwapchain(); void DestroySwapchain();
};
CVkRenderContext s_vkRenderContext; IImage *m_pOutputImage = NULL;
IRenderContext *g_pVkRenderContext = &s_vkRenderContext; bool m_bOutputImageOutdated = true;
};
EXPOSE_INTERFACE(CVkRenderContext, IRenderContext, RENDER_CONTEXT_VULKAN_INTERFACE_NAME);
void CVkRenderContext::SetOutputImage( IImage *pImage )
{
m_pOutputImage = pImage;
}
bool CVkRenderContext::BIsOutputImageOutdated( )
{
return m_bOutputImageOutdated;
}
uint32_t CVkRenderContext::GetNewOutputImageWidth()
{
return 1280;
}
uint32_t CVkRenderContext::GetNewOutputImageHeight()
{
return 720;
}
EImageFormat CVkRenderContext::GetNewOutputImageFormat()
{
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Creates vertex buffer. Wrapper over CreateBuffer // Creates vertex buffer. Wrapper over CreateBuffer
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
IVertexBuffer *CVkRenderContext::CreateVertexBuffer( uint32_t nSize ) IVertexBuffer *CVkRenderContext::CreateVertexBuffer( uint32_t nSize )
{ {
return (IVertexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT); return (IVertexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT |VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT );
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -254,13 +333,28 @@ IVertexBuffer *CVkRenderContext::CreateVertexBuffer( uint32_t nSize )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
IIndexBuffer *CVkRenderContext::CreateIndexBuffer( uint32_t nSize ) IIndexBuffer *CVkRenderContext::CreateIndexBuffer( uint32_t nSize )
{ {
return (IIndexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT); return (IIndexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT);
}
//-----------------------------------------------------------------------------
// Creates storage buffer. Wrapper over CreateBuffer
//-----------------------------------------------------------------------------
IBuffer *CVkRenderContext::CreateStorageBuffer( uint32_t nSize )
{
return (IVertexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT);
}
//-----------------------------------------------------------------------------
// Creates constant buffer. Wrapper over CreateBuffer
//-----------------------------------------------------------------------------
IBuffer *CVkRenderContext::CreateConstantBuffer( uint32_t nSize )
{
return (IIndexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Creates basic vulkan buffer // Creates basic vulkan buffer
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
IBuffer *CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage ) IBuffer *CVkRenderContext::CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage )
{ {
CVkBuffer *pBuffer = new CVkBuffer(nSize, eUsage, 0); CVkBuffer *pBuffer = new CVkBuffer(nSize, eUsage, 0);
return pBuffer; return pBuffer;
@@ -271,7 +365,7 @@ IBuffer *CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage )
// Useful for everything eg: ray tracing, which requires them to be aligned // Useful for everything eg: ray tracing, which requires them to be aligned
// to the groupBaseAlignment. // to the groupBaseAlignment.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage ) IBuffer *CVkRenderContext::CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage )
{ {
} }
@@ -279,12 +373,15 @@ IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsage
IImage *CVkRenderContext::CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) IImage *CVkRenderContext::CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType )
{ {
if (eFormat == IMAGE_FORMAT_D32_SFLOAT)
return new CVkImage(x, y, 1, eFormat, eMultisampleType, IMAGE_TYPE_2D, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
else
return new CVkImage(x, y, 1, eFormat, eMultisampleType, IMAGE_TYPE_2D, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
} }
IImage *CVkRenderContext::CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) IImage *CVkRenderContext::CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType )
{ {
return new CVkImage(x, y, 1, eFormat, eMultisampleType, IMAGE_TYPE_2D, VK_IMAGE_USAGE_STORAGE_BIT);
} }
@@ -300,49 +397,69 @@ void CVkRenderContext::DestroyImage( IImage *pImage )
IShader *CVkRenderContext::CreateShader( const char *szName ) IShader *CVkRenderContext::CreateShader( const char *szName )
{ {
CCompiledShader stShader = {};
CompiledShaderManager()->ReadFromFile(&stShader, szName);
CVkVertexDescriptionPipelineLibrary vertexDescription = {};
vertexDescription.AddAttribute(0, 0, VERTEX_FORMAT_XYZ32_SFLOAT, 0);
vertexDescription.AddLayout(0, 12);
vertexDescription.SetTopology(TOPOLOGY_MODE_TRIANGLE_LIST);
vertexDescription.Build();
CVkVertexTransformPipelineLibrary vertexTransform = {};
vertexTransform.SetShader(&stShader);
vertexTransform.Build();
CVkPixelShaderPipelineLibrary pixelShader = {};
pixelShader.SetShader(&stShader);
pixelShader.Build();
CVkPixelOutputPipelineLibrary pixelOutput = {};
pixelOutput.AddAttachment(IMAGE_FORMAT_RGBA8_UNORM);
pixelOutput.Build();
CVkShader *pShader = new CVkShader();
pShader->AddShaderLibrary(&vertexDescription);
pShader->AddShaderLibrary(&vertexTransform);
pShader->AddShaderLibrary(&pixelShader);
pShader->AddShaderLibrary(&pixelOutput);
printf("--- general pipeline ---\n");
pShader->Build();
return pShader;
} }
void CVkRenderContext::DestroyShader( IShader *pMaterial ) void CVkRenderContext::DestroyShader( IShader *pShader )
{ {
delete pShader;
} }
IMaterial *CVkRenderContext::CreateMaterial( IShader *pShader ) IMaterial *CVkRenderContext::CreateMaterial( IShader *pShader )
{ {
return new CVkMaterial(pShader);
} }
void CVkRenderContext::DestroyMaterial( IMaterial *pMaterial ) void CVkRenderContext::DestroyMaterial( IMaterial *pMaterial )
{ {
delete pMaterial;
} }
void CVkRenderContext::SetMaterial( IMaterial *pMaterial )
IRenderCommandList *CVkRenderContext::CreateCommandList()
{
return new CVkRenderCommandList;
}
void CVkRenderContext::DestroyCommandList( IRenderCommandList *pCommandList )
{ {
} }
void CVkRenderContext::SetVertexBuffer( IVertexBuffer *pBuffer ) void CVkRenderContext::SubmitCommandList(IRenderCommandList *pList)
{ {
CVkRenderCommandList *pVkList = (CVkRenderCommandList*)pList;
pVkList->Submit();
} }
void CVkRenderContext::SetIndexBuffer( IVertexBuffer *pBuffer ) VkPipelineLayout g_pLibraryEmptyLayout;
{
}
void CVkRenderContext::DrawPrimitives( uint32_t nVertexCount, uint32_t nFirstVertex, uint32_t nInstanceCount, uint32_t nFirstInstance )
{
}
void CVkRenderContext::DrawPrimitivesIndexed( uint32_t nIndexCount, uint32_t nFirstIndex, uint32_t nVertexOffset, uint32_t nInstanceCount, uint32_t nFirstInstance )
{
}
IVkCommandBuffer *pCommandBuffer;
static IVkCommandBuffer *s_pPresentCommandBuffer; static IVkCommandBuffer *s_pPresentCommandBuffer;
void CVkRenderContext::Init() void CVkRenderContext::Init()
{ {
@@ -436,21 +553,48 @@ void CVkRenderContext::Init()
VkPhysicalDeviceVulkan13Features vk13Features = {}; VkPhysicalDeviceVulkan13Features vk13Features = {};
vk13Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; vk13Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
vk13Features.synchronization2 = VK_TRUE;
vk13Features.pNext = &gplFeatures; vk13Features.pNext = &gplFeatures;
vk13Features.synchronization2 = VK_TRUE;
vk13Features.dynamicRendering = VK_TRUE;
VkPhysicalDeviceVulkan12Features vk12Features = {};
vk12Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
vk12Features.pNext = &vk13Features;
vk12Features.bufferDeviceAddress = VK_TRUE;
stDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; stDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
stDeviceCreateInfo.queueCreateInfoCount = 1; stDeviceCreateInfo.queueCreateInfoCount = 1;
stDeviceCreateInfo.pQueueCreateInfos = &stDeviceQueueCreateInfo; stDeviceCreateInfo.pQueueCreateInfos = &stDeviceQueueCreateInfo;
stDeviceCreateInfo.enabledExtensionCount = enabledDeviceExtensions.GetSize(); stDeviceCreateInfo.enabledExtensionCount = enabledDeviceExtensions.GetSize();
stDeviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.GetData(); stDeviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.GetData();
stDeviceCreateInfo.pNext = &vk13Features; stDeviceCreateInfo.pNext = &vk12Features;
r = vkCreateDevice(g_vkPhysicalDevice, &stDeviceCreateInfo, NULL, &g_vkDevice); r = vkCreateDevice(g_vkPhysicalDevice, &stDeviceCreateInfo, NULL, &g_vkDevice);
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices); VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
for (auto &extension: enabledDeviceExtensions) for (auto &extension: enabledDeviceExtensions)
V_printf("%s\n", extension); V_printf("%s\n", extension);
vkGetDeviceQueue(g_vkDevice, g_iDrawFamily, 0, &g_vkDrawQueue); vkGetDeviceQueue(g_vkDevice, g_iDrawFamily, 0, &g_vkDrawQueue);
vkGetDeviceQueue(g_vkDevice, g_iPresentFamily, 0, &g_vkPresentQueue); vkGetDeviceQueue(g_vkDevice, g_iPresentFamily, 0, &g_vkPresentQueue);
volkLoadDevice(g_vkDevice);
VmaAllocatorCreateInfo stAllocatorInfo = {};
stAllocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
| VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT
;
stAllocatorInfo.vulkanApiVersion = VK_API_VERSION_1_4;
stAllocatorInfo.physicalDevice = g_vkPhysicalDevice;
stAllocatorInfo.device = g_vkDevice;
stAllocatorInfo.instance = g_vkInstance;
VmaVulkanFunctions vulkanFunctions;
vmaImportVulkanFunctionsFromVolk(&stAllocatorInfo, &vulkanFunctions);
stAllocatorInfo.pVulkanFunctions = &vulkanFunctions;
vmaCreateAllocator(&stAllocatorInfo, &g_vkAllocator);
VkPipelineLayoutCreateInfo stPipelineLayout = {};
stPipelineLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
stPipelineLayout.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
vkCreatePipelineLayout(g_vkDevice, &stPipelineLayout, NULL, &g_pLibraryEmptyLayout);
CreateSwapchain(); CreateSwapchain();
@@ -468,37 +612,12 @@ void CVkRenderContext::Init()
g_pCommandBufferManager = (IVkCommandBufferManager*)CreateInterface(VULKAN_COMMAND_BUFFER_MANAGER_INTERFACE_NAME, NULL); g_pCommandBufferManager = (IVkCommandBufferManager*)CreateInterface(VULKAN_COMMAND_BUFFER_MANAGER_INTERFACE_NAME, NULL);
g_pCommandBufferManager->Init(); g_pCommandBufferManager->Init();
pCommandBuffer = g_pCommandBufferManager->CreateCommandBuffer();
s_pPresentCommandBuffer = g_pCommandBufferManager->CreateCommandBuffer();
CVkClearColorCommand *pCommand = (CVkClearColorCommand*)g_pCommandBufferManager->CreateCommand("ClearColor");
pCommand->pImage = NULL;
pCommand->ppSwapchainImages = g_vkSwapchainImages.GetData();
pCommand->r = 1;
pCommand->b = 1;
pCommand->g = 0;
pCommand->AddSwapchainDependency( (IRenderingObject**)g_vkSwapchainImages.GetData(), DEPENDENCY_MODE_COLOR_CLEAR_DESTINATION );
CVkVertexDescriptionPipelineLibrary vertexDescription = {};
vertexDescription.AddAttribute(0, 0, VERTEX_FORMAT_XYZ32_SFLOAT, 0);
vertexDescription.AddLayout(0, 12);
vertexDescription.SetTopology(TOPOLOGY_MODE_TRIANGLE_LIST);
vertexDescription.Build();
CVkVertexTransformPipelineLibrary vertexTransform = {};
CVkEmptyCommand *pPresentCommand = (CVkEmptyCommand*)g_pCommandBufferManager->CreateCommand("Empty"); CVkEmptyCommand *pPresentCommand = (CVkEmptyCommand*)g_pCommandBufferManager->CreateCommand("Empty");
pPresentCommand->AddSwapchainDependency( (IRenderingObject**)g_vkSwapchainImages.GetData(), DEPENDENCY_MODE_IMAGE_PRESENT ); pPresentCommand->AddSwapchainDependency( (IRenderingObject**)g_vkSwapchainImages.GetData(), DEPENDENCY_MODE_IMAGE_PRESENT );
CVkBeginCommand *pBeginCommand = (CVkBeginCommand*)g_pCommandBufferManager->CreateCommand("Empty");
pBeginCommand->AddSwapchainDependency((IRenderingObject**)g_vkSwapchainImages.GetData(), DEPENDENCY_MODE_DRAWCALL_OUTPUT_IMAGE);
CVkBeginCommand *pEndCommand = (CVkBeginCommand*)g_pCommandBufferManager->CreateCommand("Empty");
pCommandBuffer->Reset();
pCommandBuffer->AddCommand(pCommand);
pCommandBuffer->Render();
s_pPresentCommandBuffer = g_pCommandBufferManager->CreateCommandBuffer();
s_pPresentCommandBuffer->Reset(); s_pPresentCommandBuffer->Reset();
s_pPresentCommandBuffer->AddCommand(pPresentCommand); s_pPresentCommandBuffer->AddCommand(pPresentCommand);
s_pPresentCommandBuffer->Render(); s_pPresentCommandBuffer->Render();
@@ -507,8 +626,7 @@ void CVkRenderContext::Init()
void CVkRenderContext::Frame( float fDeltaTime ) void CVkRenderContext::Frame( float fDeltaTime )
{ {
vkDeviceWaitIdle(g_vkDevice); vkDeviceWaitIdle(g_vkDevice);
pCommandBuffer->Render(); m_bOutputImageOutdated = false;
s_pPresentCommandBuffer->Render();
static uint32_t s_nImageIndex = 0; static uint32_t s_nImageIndex = 0;
uint32_t nImageIndex = 0; uint32_t nImageIndex = 0;
@@ -518,9 +636,7 @@ void CVkRenderContext::Frame( float fDeltaTime )
vkResetFences(g_vkDevice, 1, &g_vkFences[s_nImageIndex]); vkResetFences(g_vkDevice, 1, &g_vkFences[s_nImageIndex]);
g_vkCommandBuffers = {};
pCommandBuffer->Submit(nImageIndex);
s_pPresentCommandBuffer->Submit(nImageIndex); s_pPresentCommandBuffer->Submit(nImageIndex);
VkPipelineStageFlags uPipelineStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkPipelineStageFlags uPipelineStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
@@ -550,6 +666,7 @@ void CVkRenderContext::Frame( float fDeltaTime )
vkQueuePresentKHR(g_vkPresentQueue, &stPresentInfo); vkQueuePresentKHR(g_vkPresentQueue, &stPresentInfo);
s_nImageIndex = (s_nImageIndex + 1) % g_vkSwapchainImages.GetSize(); s_nImageIndex = (s_nImageIndex + 1) % g_vkSwapchainImages.GetSize();
g_vkCommandBuffers = {};
} }
void CVkRenderContext::CreateSwapchain() void CVkRenderContext::CreateSwapchain()

View File

@@ -1,3 +1,39 @@
#include "vulkan_state.h" #include "vulkan_state.h"
void CVkShader::AddShaderLibrary( CVkPipelineLibrary *pLibrary )
{
m_libraries.AppendTail(pLibrary);
}
void CVkShader::Build()
{
CUtlVector<VkPipeline> libs = {};
VkGraphicsPipelineCreateInfo createInfo = {};
VkPipelineLibraryCreateInfoKHR libInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
for ( auto l: m_libraries )
{
libs.AppendTail(l->m_hPipeline);
};
libInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
libInfo.libraryCount = libs.GetSize();
libInfo.pLibraries = libs.GetData();
createInfo.pNext = &libInfo;
createInfo.flags = VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
createInfo.layout = g_pLibraryEmptyLayout;
// Possibly schedule it?
vkCreateGraphicsPipelines(g_vkDevice, NULL, 1, &createInfo, NULL, &m_hPipeline);
}
uint32_t CVkShader::PSGetResourceByName( const char *szName )
{
}
uint32_t CVkShader::VSGetResourceByName( const char *szName )
{
}

View File

@@ -0,0 +1,28 @@
#include "shaderparser.h"
CUtlVector<VulkanDescriptor_t> CVkShaderParser::GetDescriptors( CCompiledShader *pShader, EShaderStage eStage )
{
CUtlVector<VulkanDescriptor_t> descriptors = {};
return descriptors;
};
CUtlBuffer<unsigned char> CVkShaderParser::GetShaderCode( CCompiledShader *pShader, EShaderStage eStage )
{
for ( auto &o: pShader->m_objects )
{
if (o.m_eStage != eStage)
continue;
CUtlBuffer<unsigned char> code = CUtlBuffer<unsigned char>(pShader->GetLumpSize(o.m_nDataLump));
V_memcpy(code, pShader->GetLumpPtr(o.m_nDataLump), code.GetSize());
return code;
}
return NULL;
};
CVkShaderParser *ShaderParser()
{
static CVkShaderParser s_shaderParser = CVkShaderParser();
return &s_shaderParser;
};

View File

@@ -0,0 +1,17 @@
#ifndef VULKAN_SHADER_PARSER_H
#define VULKAN_SHADER_PARSER_H
#include "materialsystem/vulkan_shadermeta.h"
#include "materialsystem/compiledshadermgr.h"
#include "tier1/utlvector.h"
class CVkShaderParser
{
public:
CUtlVector<VulkanDescriptor_t> GetDescriptors( CCompiledShader *pShader, EShaderStage eStage );
CUtlBuffer<unsigned char> GetShaderCode( CCompiledShader *pShader, EShaderStage eStage );
};
CVkShaderParser *ShaderParser();
#endif

View File

@@ -22,7 +22,7 @@ VkAccessFlags2 VulkanGetAccessFlags( EDependencyMode eMode )
case DEPENDENCY_MODE_COLOR_CLEAR_DESTINATION: return VK_ACCESS_2_TRANSFER_WRITE_BIT; case DEPENDENCY_MODE_COLOR_CLEAR_DESTINATION: return VK_ACCESS_2_TRANSFER_WRITE_BIT;
case DEPENDENCY_MODE_IMAGE_PRESENT: return VK_ACCESS_2_NONE; case DEPENDENCY_MODE_IMAGE_PRESENT: return VK_ACCESS_2_NONE;
default: default:
return 0; return VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
} }
} }
@@ -73,3 +73,14 @@ VkPrimitiveTopology VulkanGetTopology( ETopologyMode eMode )
case TOPOLOGY_MODE_TRIANGLE_STRIP: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; case TOPOLOGY_MODE_TRIANGLE_STRIP: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
} }
} }
VkShaderStageFlagBits VulkanGetShaderStage( EShaderStage eStage )
{
switch (eStage)
{
case SHADER_STAGE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
case SHADER_STAGE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
default:
break;
}
return VK_SHADER_STAGE_VERTEX_BIT;
}

View File

@@ -0,0 +1,6 @@
#define VMA_VULKAN_VERSION 1004000
#define VMA_IMPLEMENTATION
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#include "volk.h"
#include "vk_mem_alloc.h"

View File

@@ -8,6 +8,7 @@
#include "tier1/utlvector.h" #include "tier1/utlvector.h"
#include "tier2/iappsystem.h" #include "tier2/iappsystem.h"
#include "materialsystem/imaterialsystem.h" #include "materialsystem/imaterialsystem.h"
#include "materialsystem/shaderinternals.h"
#include "vulkan/vulkan_core.h" #include "vulkan/vulkan_core.h"
#define REQUIRED_EXTENSION(ext) bool bIsSupported_##ext; #define REQUIRED_EXTENSION(ext) bool bIsSupported_##ext;
@@ -26,6 +27,7 @@ extern CUtlVector<VkCommandPool> g_vkCommandPools;
extern CUtlVector<VkCommandBuffer> g_vkCommandBuffers; extern CUtlVector<VkCommandBuffer> g_vkCommandBuffers;
extern VkInstance g_vkInstance; extern VkInstance g_vkInstance;
extern VmaAllocator g_vkAllocator;
extern VkPhysicalDevice g_vkPhysicalDevice; extern VkPhysicalDevice g_vkPhysicalDevice;
extern VkDevice g_vkDevice; extern VkDevice g_vkDevice;
@@ -115,7 +117,7 @@ public:
virtual void AddCommand( CVkCommand *pCommand ) = 0; virtual void AddCommand( CVkCommand *pCommand ) = 0;
virtual void Reset() = 0; virtual void Reset() = 0;
virtual void Submit( int iFrameIndex ) = 0; virtual void Submit( int iFrameIndex = 0 ) = 0;
virtual void Render() = 0; virtual void Render() = 0;
}; };
@@ -135,6 +137,8 @@ class CVkCommandRegistry
public: public:
CVkCommandRegistry( const char *szName, fnCreateVulkanCommand_t pfnCreate ); CVkCommandRegistry( const char *szName, fnCreateVulkanCommand_t pfnCreate );
}; };
#define CREATE_COMMAND(name) \
(CVk##name##Command*)g_pCommandBufferManager->CreateCommand(#name)
#define BEGIN_VULKAN_COMMAND( name ) \ #define BEGIN_VULKAN_COMMAND( name ) \
class CVk##name##Command : public CVkCommand \ class CVk##name##Command : public CVkCommand \
@@ -162,7 +166,7 @@ class CVkImage: public IImage
{ {
public: public:
CVkImage(); CVkImage();
CVkImage( uint32_t nWidth, uint32_t nHeight, EImageFormat eFormat, EMultisampleType eMultisampleType ); CVkImage( uint32_t nWidth, uint32_t nHeight, uint32_t nDepth, EImageFormat eFormat, EMultisampleType eMultisampleType, EImageType eImageType, VkImageUsageFlagBits eUsage );
~CVkImage(); ~CVkImage();
virtual void SetDebugName( const char *szName ) override; virtual void SetDebugName( const char *szName ) override;
@@ -171,7 +175,7 @@ public:
virtual EImageFormat GetImageFormat() override; virtual EImageFormat GetImageFormat() override;
virtual EMultisampleType GetMultisampleType() override; virtual EMultisampleType GetMultisampleType() override;
void CreateImage( uint32_t nWidth, uint32_t nHeight, EImageFormat eFormat, EMultisampleType eMultisampleType ); void CreateImage( uint32_t nWidth, uint32_t nHeight, EImageFormat eFormat, EMultisampleType eMultisampleType, VkImageUsageFlagBits eUsage );
void CreateImageView(); void CreateImageView();
static VkImageViewType GetImageViewType( enum EImageType eImageType ); static VkImageViewType GetImageViewType( enum EImageType eImageType );
@@ -205,10 +209,10 @@ public:
virtual void Unmap() override; virtual void Unmap() override;
virtual uint32_t GetSize() override; virtual uint32_t GetSize() override;
VmaAllocation allocation; VmaAllocation m_allocation;
VkBuffer buffer; VkBuffer m_buffer;
VkDeviceAddress address; VkDeviceAddress m_address;
uint32_t nSize; uint32_t m_nSize;
}; };
class CVkPipelineLibrary class CVkPipelineLibrary
@@ -228,6 +232,7 @@ public: \
#define END_DEFINE_PIPELINE_LIBRARY() \ #define END_DEFINE_PIPELINE_LIBRARY() \
}; };
extern VkPipelineLayout g_pLibraryEmptyLayout;
#define BEGIN_BUILD_PIPELINE_LIBRARY(name) \ #define BEGIN_BUILD_PIPELINE_LIBRARY(name) \
void CVk##name##PipelineLibrary::Build() \ void CVk##name##PipelineLibrary::Build() \
{ \ { \
@@ -236,22 +241,59 @@ void CVk##name##PipelineLibrary::Build() \
pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; \ pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; \
library.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT; \ library.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT; \
pipeline.pNext = &library; \ pipeline.pNext = &library; \
pipeline.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; \ pipeline.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; \
pipeline.layout = g_pLibraryEmptyLayout;
#define END_BUILD_PIPELINE_LIBRARY() \ #define END_BUILD_PIPELINE_LIBRARY() \
vkCreateGraphicsPipelines(g_vkDevice, NULL, 1, &pipeline, NULL, &m_hPipeline); \ vkCreateGraphicsPipelines(g_vkDevice, NULL, 1, &pipeline, NULL, &m_hPipeline); \
} }
class CVkShader : IShader class CVkShader : public IShader
{ {
public: public:
void AddShaderLibrary( CVkPipelineLibrary *pLibrary ); void AddShaderLibrary( CVkPipelineLibrary *pLibrary );
void Build(); void Build();
virtual uint32_t PSGetResourceByName( const char *szName ) override;
virtual uint32_t VSGetResourceByName( const char *szName ) override;
VkPipeline m_hPipeline = NULL; VkPipeline m_hPipeline = NULL;
VkPipelineLayout m_hPipelineLayout; VkPipelineLayout m_hPipelineLayout;
CUtlVector<CVkPipelineLibrary*> m_libraries; CUtlVector<CVkPipelineLibrary*> m_libraries;
}; };
class CVkMaterial: public IMaterial
{
public:
CVkMaterial( IShader *pShader );
virtual ~CVkMaterial() override;
virtual void VSSetShaderResource( uint32_t uRegister, IRenderingObject *pResource ) override;
virtual void VSSetConstantsBuffer( uint32_t uRegister, IBuffer *pConstants ) override;
virtual void PSSetShaderResource( uint32_t uRegister, IRenderingObject *pResource ) override;
virtual void PSSetConstantsBuffer( uint32_t uRegister, IBuffer *pConstants ) override;
CVkShader *m_pVkShader;
private:
void SetShaderResource( uint32_t uRegister, uint32_t uSet, IRenderingObject *pObject);
};
enum EVulkanRenderingStage
{
RENDERING_STAGE_SETUP_RASTER,
RENDERING_STAGE_RASTER,
RENDERING_STAGE_POST_RASTER,
RENDERING_STAGE_FINISHED,
};
struct VulkanMaterialCommandBuffer_t
{
IMaterial *m_pMaterial;
IVkCommandBuffer *m_pCommandBuffer;
};
enum EVkFrameObjectType_t enum EVkFrameObjectType_t
{ {
FRAME_OBJECT_TYPE_SINGLE, FRAME_OBJECT_TYPE_SINGLE,
@@ -267,6 +309,64 @@ struct VkFrameObject_t
}; };
}; };
struct VulkanRenderOutput_t {
VkFrameObject_t m_stImage;
VkFrameObject_t m_stResolveImage;
float m_fClearColor[4];
float m_fClearDepth;
uint32_t m_uIndex;
EResolveMode m_eResolveMode;
ELoadMode m_eLoadMode;
EStoreMode m_eStoreMode;
};
class CVkRenderCommandList: public IRenderCommandList
{
public:
virtual void ResetRendering() override;
virtual void SetRenderTarget( uint32_t uIndex, IImage *pImage ) override;
virtual void SetClearColor( uint32_t uIndex, float r, float g, float b, float a ) override;
virtual void SetDepthTarget( IImage *pDepth ) override;
virtual void SetClearDepth( float fVal ) override;
virtual void SetRenderResolution( uint32_t iWidth, uint32_t iHeight ) override;
// Should they apply per material or for all?
virtual void SetScissors( uint32_t uX, uint32_t uY, uint32_t uWidth, uint32_t uHeight ) override;
virtual void SetViewport( uint32_t uX, uint32_t uY, uint32_t uWidth, uint32_t uHeight, float fMinDepth, float fMaxDepth ) override;
virtual void SetMaterial( IMaterial *pMaterial ) override;
virtual void SetVertexBuffer( uint32_t uBinding, IVertexBuffer *pBuffer ) override;
virtual void SetIndexBuffer( IVertexBuffer *pBuffer ) override;
virtual void DrawPrimitives( uint32_t nVertexCount, uint32_t nFirstVertex, uint32_t nInstanceCount, uint32_t nFirstInstance ) override;
virtual void DrawPrimitivesIndexed( uint32_t nIndexCount, uint32_t nFirstIndex, uint32_t nVertexOffset, uint32_t nInstanceCount, uint32_t nFirstInstance ) override;
virtual void ResolveImage( IImage *pOriginal, IImage *pResolved ) override;
virtual void StartRecording() override;
virtual void EndRecording() override;
void Submit();
private:
void SwitchRenderingStage( EVulkanRenderingStage eStage );
VulkanRenderOutput_t *FindOrCreateRenderOutput( uint32_t uIndex );
IVkCommandBuffer *FindOrCreateMaterialCommandBuffer( IMaterial *pMaterial, bool *pbWasCreated = NULL );
VulkanRenderOutput_t m_depth;
CUtlVector<VulkanRenderOutput_t> m_pOutput = {};
CUtlSelfReferencingVector<VulkanMaterialCommandBuffer_t> m_materials = {};
IVkCommandBuffer *m_pPostRaster;
IVkCommandBuffer *m_pCurrentMaterialBuffer = NULL;
};
IRenderingObject *VulkanGetObject( VkFrameObject_t stObject, int iIndex ); IRenderingObject *VulkanGetObject( VkFrameObject_t stObject, int iIndex );
VkAccessFlags2 VulkanGetAccessFlags( EDependencyMode eMode ); VkAccessFlags2 VulkanGetAccessFlags( EDependencyMode eMode );
@@ -274,4 +374,6 @@ VkPipelineStageFlags2 VulkanGetStageFlags( EDependencyMode eMode );
VkImageLayout VulkanGetImageLayout( EDependencyMode eMode ); VkImageLayout VulkanGetImageLayout( EDependencyMode eMode );
VkFormat VulkanGetVertexFormat( EVertexFormat eFormat ); VkFormat VulkanGetVertexFormat( EVertexFormat eFormat );
VkPrimitiveTopology VulkanGetTopology( ETopologyMode eMode ); VkPrimitiveTopology VulkanGetTopology( ETopologyMode eMode );
VkShaderStageFlagBits VulkanGetShaderStage( EShaderStage eStage );
#endif #endif

View File

@@ -0,0 +1,17 @@
#ifndef SHADER_WRITER_H
#define SHADER_WRITER_H
#include "tier1/interface.h"
#include "shadercompiler/icompiler.h"
abstract_class ICompiledShaderManager
{
public:
virtual void WriteToFile( CCompiledShader *pShader, const char *szFile ) = 0;
virtual void ReadFromFile( CCompiledShader *pShader, const char *szFile ) = 0;
};
ICompiledShaderManager *CompiledShaderManager();
#endif

View File

@@ -78,18 +78,25 @@ enum ETopologyMode
}; };
//-----------------------------------------------------------------------------
// Basic rendering object
//-----------------------------------------------------------------------------
abstract_class IRenderingObject abstract_class IRenderingObject
{ {
public: public:
virtual ~IRenderingObject() = 0;
virtual void SetDebugName( const char *szName ) = 0; virtual void SetDebugName( const char *szName ) = 0;
}; };
//-----------------------------------------------------------------------------
// Buffer object
//-----------------------------------------------------------------------------
abstract_class IBuffer : public IRenderingObject abstract_class IBuffer : public IRenderingObject
{ {
public: public:
virtual void Lock() = 0; virtual void Lock() = 0;
virtual void Unlock() = 0; virtual void Unlock() = 0;
virtual void *Map() = 0; virtual void *Map() = 0;
virtual void Unmap() = 0; virtual void Unmap() = 0;
virtual uint32_t GetSize() = 0; virtual uint32_t GetSize() = 0;
@@ -98,6 +105,9 @@ virtual void *Map() = 0;
typedef IBuffer IVertexBuffer; typedef IBuffer IVertexBuffer;
typedef IBuffer IIndexBuffer; typedef IBuffer IIndexBuffer;
//-----------------------------------------------------------------------------
// Image object
//-----------------------------------------------------------------------------
abstract_class IImage : public IRenderingObject abstract_class IImage : public IRenderingObject
{ {
public: public:
@@ -107,35 +117,83 @@ public:
virtual EMultisampleType GetMultisampleType() = 0; virtual EMultisampleType GetMultisampleType() = 0;
}; };
//-----------------------------------------------------------------------------
// Shader object
//-----------------------------------------------------------------------------
abstract_class IShader abstract_class IShader
{ {
public: public:
virtual ~IShader() = 0;
virtual uint32_t PSGetResourceByName( const char *szName ) = 0;
virtual uint32_t VSGetResourceByName( const char *szName ) = 0;
}; };
//-----------------------------------------------------------------------------
#define BEGIN_SHADER(name) \ // Material handle
class CShader_##name \ // It allows to specify resources in shaders such as textures, buffers etc.
{ //
// Resources must be updated prior to the frame, which can be done
#define END_SHADER() \ // prior to the frame.
} //-----------------------------------------------------------------------------
abstract_class IMaterial abstract_class IMaterial
{ {
public: public:
virtual void SetConstants( void *pData ) = 0; virtual ~IMaterial() = 0;
virtual void VSSetShaderResource( uint32_t uRegister, IRenderingObject *pResource ) = 0;
virtual void SetTexture( const char *szName, IImage *pImage ) = 0; virtual void PSSetShaderResource( uint32_t uRegister, IRenderingObject *pResource ) = 0;
virtual void SetBuffer( const char *szName, IBuffer *pImage ) = 0; virtual void VSSetConstantsBuffer( uint32_t uRegister, IBuffer *pImage ) = 0;
virtual void PSSetConstantsBuffer( uint32_t uRegister, IBuffer *pImage ) = 0;
}; };
abstract_class IRenderCommandList
{
public:
virtual void ResetRendering() = 0;
virtual void SetRenderTarget( uint32_t uIndex, IImage *pImage ) = 0;
virtual void SetClearColor( uint32_t uIndex, float r, float g, float b, float a ) = 0;
virtual void SetDepthTarget( IImage *pDepth ) = 0;
virtual void SetClearDepth( float fVal ) = 0;
virtual void SetRenderResolution( uint32_t iWidth, uint32_t iHeight ) = 0;
virtual void SetScissors( uint32_t uX, uint32_t uY, uint32_t uWidth, uint32_t uHeight ) = 0;
virtual void SetViewport( uint32_t uX, uint32_t uY, uint32_t uWidth, uint32_t uHeight, float fMinDepth, float fMaxDepth ) = 0;
virtual void SetMaterial( IMaterial *pMaterial ) = 0;
virtual void SetVertexBuffer( uint32_t uBinding, IVertexBuffer *pBuffer ) = 0;
virtual void SetIndexBuffer( IVertexBuffer *pBuffer ) = 0;
virtual void DrawPrimitives( uint32_t nVertexCount, uint32_t nFirstVertex, uint32_t nInstanceCount, uint32_t nFirstInstance ) = 0;
virtual void DrawPrimitivesIndexed( uint32_t nIndexCount, uint32_t nFirstIndex, uint32_t nVertexOffset, uint32_t nInstanceCount, uint32_t nFirstInstance ) = 0;
virtual void ResolveImage( IImage *pOriginal, IImage *pResolved ) = 0;
virtual void StartRecording() = 0;
virtual void EndRecording() = 0;
};
//-----------------------------------------------------------------------------
// Rendering context
//
// Responsible for the object handling
//-----------------------------------------------------------------------------
abstract_class IRenderContext: public IAppSystem abstract_class IRenderContext: public IAppSystem
{ {
public: public:
virtual void Frame( float fTime ) = 0; virtual void Frame( float fTime ) = 0;
virtual void SetOutputImage( IImage *pImage ) = 0;
virtual bool BIsOutputImageOutdated() = 0;
virtual uint32_t GetNewOutputImageWidth() = 0;
virtual uint32_t GetNewOutputImageHeight() = 0;
virtual EImageFormat GetNewOutputImageFormat() = 0;
virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) = 0; virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) = 0;
virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) = 0; virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) = 0;
virtual IBuffer *CreateConstantBuffer( uint32_t nSize ) = 0;
virtual IBuffer *CreateStorageBuffer( uint32_t nSize ) = 0;
virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) = 0; virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) = 0;
virtual IImage *CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) = 0; virtual IImage *CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) = 0;
@@ -148,22 +206,22 @@ public:
virtual IMaterial *CreateMaterial( IShader *pShader ) = 0; virtual IMaterial *CreateMaterial( IShader *pShader ) = 0;
virtual void DestroyMaterial( IMaterial *pMaterial ) = 0; virtual void DestroyMaterial( IMaterial *pMaterial ) = 0;
virtual void SetMaterial( IMaterial *pMaterial ) = 0; virtual IRenderCommandList *CreateCommandList() = 0;
virtual void SetVertexBuffer( IVertexBuffer *pBuffer ) = 0; virtual void DestroyCommandList( IRenderCommandList *pCommandList ) = 0;
virtual void SetIndexBuffer( IVertexBuffer *pBuffer ) = 0; virtual void SubmitCommandList(IRenderCommandList *pList) = 0;
virtual void DrawPrimitives( uint32_t nVertexCount, uint32_t nFirstVertex, uint32_t nInstanceCount, uint32_t nFirstInstance ) = 0;
virtual void DrawPrimitivesIndexed( uint32_t nIndexCount, uint32_t nFirstIndex, uint32_t nVertexOffset, uint32_t nInstanceCount, uint32_t nFirstInstance ) = 0;
}; };
#define RENDER_CONTEXT_INTERFACE_NAME "RenderContext001"
#define RENDER_CONTEXT_VULKAN_INTERFACE_NAME RENDER_CONTEXT_INTERFACE_NAME
abstract_class IMaterialSystem: public IAppSystem abstract_class IMaterialSystem: public IAppSystem
{ {
public: public:
virtual void Frame( float fTime ) = 0; virtual void Frame( float fTime ) = 0;
virtual IRenderContext *GetRenderContext( void ) = 0;
}; };
extern IRenderContext *g_pRenderContext;
IMaterialSystem *Materials( void ); IMaterialSystem *Materials( void );
#endif #endif

View File

@@ -0,0 +1,70 @@
//================= Copyright kotofyt, All rights reserved ==================//
// Purpose: Shader compilers.
//
// We kinda need to store shader contents in blobs so they can be parsed easily
//
// For now we store them like this
// ShaderHeader_t
// ShaderLump_t[m_nNumLump]
// ShaderObject_t[m_nNumShaders]
// ~An actual shader data~
//===========================================================================//
#ifndef SHADER_INTERNALS_H
#define SHADER_INTERNALS_H
#include "stdint.h"
enum EShaderBackend: uint32_t
{
SHADER_BACKEND_SPIRV_VULKAN,
SHADER_BACKEND_CODE_METAL,
};
enum EShaderStage: uint32_t
{
SHADER_STAGE_VERTEX,
SHADER_STAGE_TESSELATION_CONTROL,
SHADER_STAGE_TESSELATION_EVAL,
SHADER_STAGE_GEOMETRY,
SHADER_STAGE_PIXEL,
SHADER_STAGE_COMPUTE,
SHADER_STAGE_RAYGEN,
SHADER_STAGE_ANY_HIT,
SHADER_STAGE_CLOSEST_HIT,
SHADER_STAGE_MISS,
SHADER_STAGE_CALLABLE,
SHADER_STAGE_TASK,
SHADER_STAGE_MESH,
SHADER_STAGE_COMMON_DATA,
SHADER_STAGE_MAX,
SHADER_STAGE_COUNT = SHADER_STAGE_MAX
};
struct ShaderHeader_t
{
char m_cSignature[4];
uint32_t m_nNumLumps;
uint32_t m_nNumShaders;
};
struct ShaderLump_t
{
uint32_t m_nSize;
uint32_t m_nOffset;
};
struct ShaderObject_t
{
EShaderBackend m_eBackend;
EShaderStage m_eStage;
uint32_t m_nMetadataLump;
uint32_t m_nDataLump;
};
#endif

View File

@@ -0,0 +1,20 @@
#ifndef VULKAN_METADATA_H
#define VULKAN_METADATA_H
#include "shaderinternals.h"
#include "vulkan/vulkan.h"
struct VulkanDescriptor_t
{
VkDescriptorType eDescriptorType;
uint32_t uBinding;
uint32_t uSet;
};
struct VulkanInputMetaData_t
{
uint32_t nDescriptorsCount;
uint32_t pDescriptorSets;
};
#endif

View File

@@ -0,0 +1,41 @@
#ifndef SHADER_COMPILER_H
#define SHADER_COMPILER_H
#include "tier1/interface.h"
#include "tier1/utlvector.h"
#include "tier1/utlbuffer.h"
#include "tier2/iappsystem.h"
#include "materialsystem/shaderinternals.h"
struct HostShaderLump_t
{
void *m_pAddress;
uint32_t m_nSize;
};
class CCompiledShader
{
public:
CUtlVector<ShaderObject_t> m_objects = {};
CUtlVector<HostShaderLump_t> m_lumps = {};
~CCompiledShader();
uint32_t AllocateLump( uint32_t nSize );
void *GetLumpPtr( uint32_t nLump );
uint32_t GetLumpSize( uint32_t nLump );
ShaderObject_t *AllocateShader();
ShaderObject_t *FindShaderObject( EShaderBackend eBackend, EShaderStage eStage );
};
abstract_class IShaderCompiler: public IAppSystem
{
public:
virtual void CompileShader( const char *szInput, CCompiledShader *pShader ) = 0;
};
#define SLANG_SHADER_COMPILER_SPIRV_VULKAN "ShaderCompilerSlangVulkanSpirv"
#define SLANG_SHADER_COMPILER_CODE_METAL "ShaderCompilerSlangMetalCode"
#endif

View File

@@ -58,6 +58,9 @@ typedef void( *ListDirCallbackFn )( const char *szPath );
PLATFORM_INTERFACE void Plat_ListDirRecursive( const char *szPath, ListDirCallbackFn file, ListDirCallbackFn dir ); PLATFORM_INTERFACE void Plat_ListDirRecursive( const char *szPath, ListDirCallbackFn file, ListDirCallbackFn dir );
PLATFORM_INTERFACE void Plat_ListDir( const char *szPath, ListDirCallbackFn file, ListDirCallbackFn dir ); PLATFORM_INTERFACE void Plat_ListDir( const char *szPath, ListDirCallbackFn file, ListDirCallbackFn dir );
PLATFORM_INTERFACE char *Plat_GetExtension( const char *szPath ); PLATFORM_INTERFACE char *Plat_GetExtension( const char *szPath );
PLATFORM_INTERFACE void Plat_MakeDir( const char *szPath, int iPermissions );
PLATFORM_INTERFACE void Plat_TrapSignals( void (*pfn)() ); PLATFORM_INTERFACE void Plat_TrapSignals( void (*pfn)() );
PLATFORM_INTERFACE void Plat_Backtrace( void ); PLATFORM_INTERFACE void Plat_Backtrace( void );
@@ -65,6 +68,24 @@ PLATFORM_INTERFACE void *Plat_LoadLibrary( const char *psz );
PLATFORM_INTERFACE void *Plat_GetProc( void *lib, const char *psz ); PLATFORM_INTERFACE void *Plat_GetProc( void *lib, const char *psz );
PLATFORM_INTERFACE void Plat_UnloadLibrary( void *psz ); PLATFORM_INTERFACE void Plat_UnloadLibrary( void *psz );
PLATFORM_INTERFACE void Plat_SetEnv( const char *szVar, const char *psz );
PLATFORM_INTERFACE const char *Plat_GetEnv( const char *szVar );
PLATFORM_INTERFACE void Plat_SetWorkingDir( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetWorkingDir( void );
PLATFORM_INTERFACE const char *Plat_GetExecutablePath( void );
PLATFORM_INTERFACE const char *Plat_GetParentDir( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetUNIXExecutable( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetWindowsExecutable( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetPlatformExecutable( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetDarwinSharedLib( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetUNIXSharedLib( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetWindowsSharedLib( const char *psz );
PLATFORM_INTERFACE const char *Plat_GetPlatformSharedLib( const char *psz );
PLATFORM_INTERFACE double Plat_GetTime( void ); PLATFORM_INTERFACE double Plat_GetTime( void );
PLATFORM_INTERFACE void Plat_Exit( int status ); PLATFORM_INTERFACE void Plat_Exit( int status );

7
public/tier1/appinit.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef APPINIT_H
#define APPINIT_H
void AppInitializePath();
#endif

View File

@@ -6,6 +6,8 @@
typedef void *( *CreateInterfaceFn )( const char *szName, int *pReturnCode ); typedef void *( *CreateInterfaceFn )( const char *szName, int *pReturnCode );
typedef void *( *InstantiateInterfaceFn )( void ); typedef void *( *InstantiateInterfaceFn )( void );
CreateInterfaceFn Plat_GetInterfaceFactory( void *lib );
class CInterfaceRegistry class CInterfaceRegistry
{ {
public: public:

View File

@@ -23,6 +23,10 @@ public:
void RemoveHead( size_t nCount ); void RemoveHead( size_t nCount );
void RemoveAt( size_t nPosition, size_t nCount ); void RemoveAt( size_t nPosition, size_t nCount );
CUtlString GetFileName();
CUtlString GetDirectory();
CUtlString RemoveHeadFile();
char *GetString( void ); char *GetString( void );
size_t GetLenght( void ); size_t GetLenght( void );
operator char*( void ); operator char*( void );

View File

@@ -306,6 +306,9 @@ public:
void RemoveTail( void ); void RemoveTail( void );
void RemoveAt( size_t nIndex ); void RemoveAt( size_t nIndex );
T &GetFirst();
T &GetLast();
size_t GetSize(); size_t GetSize();
T operator[]( size_t nIndex ); T operator[]( size_t nIndex );
@@ -428,4 +431,17 @@ void CUtlSelfReferencingVector<T>::RemoveTail( void )
} }
template<typename T>
T &CUtlSelfReferencingVector<T>::GetFirst()
{
return m_pHead->data;
}
template<typename T>
T &CUtlSelfReferencingVector<T>::GetLast()
{
return m_pTail->data;
}
#endif #endif

View File

@@ -59,6 +59,10 @@ public:
// Some cool stuff // Some cool stuff
virtual CUtlBuffer<unsigned char> Read( IFileHandle *pFile ) = 0; virtual CUtlBuffer<unsigned char> Read( IFileHandle *pFile ) = 0;
// Leaks memory
// Should be cleaned by the user
virtual const char *ReadString( IFileHandle *pFile ) = 0;
IFileSystem *m_pNext; IFileSystem *m_pNext;
void RegisterFileSystem(); void RegisterFileSystem();

View File

@@ -0,0 +1,75 @@
#include "c.h"
#include "helper.h"
#include "ld.h"
#include "target.h"
CUtlString shadercompiler_lib;
CUtlString shadercompiler_exe;
DECLARE_BUILD_STAGE(libshadercompiler)
{
CProject_t stProject;
LinkProject_t stLinkProject;
CUtlString szOutput;
stProject.m_szName = "shadercompiler";
stProject.m_target = Target_t::HostTarget();
stProject.bFPIC = true;
stProject.includeDirectories = {
"public",
"external/slang/include",
"external/Vulkan-Headers/include",
};
stProject.files = {
"shadercompiler/slang/vulkan_spirv.cpp",
"materialsystem/compiledshader.cpp",
};
stLinkProject = ccompiler->Compile(&stProject);
stLinkProject.linkType = ELINK_STATIC_LIBRARY;
szOutput = linker->Link(&stLinkProject);
shadercompiler_lib = szOutput;
return 1;
}
DECLARE_BUILD_STAGE(shadercompiler)
{
CProject_t stProject;
LinkProject_t stLinkProject;
CUtlString szOutput;
stProject.m_szName = "fsc";
stProject.m_target = Target_t::HostTarget();
stProject.includeDirectories = {"public"};
stProject.files = {
"shadercompiler/main.cpp",
};
stLinkProject = ccompiler->Compile(&stProject);
stLinkProject.linkType = ELINK_EXECUTABLE;
stLinkProject.objects.AppendTail((Object_t){tier0_lib});
stLinkProject.objects.AppendTail((Object_t){tier1_lib});
stLinkProject.objects.AppendTail((Object_t){tier2_lib});
stLinkProject.objects.AppendTail((Object_t){shadercompiler_lib});
stLinkProject.libraries = {"slang-compiler","slang-glslang-2025.24.2"};
stLinkProject.libraryDirectories = {"external/linux"};
szOutput = linker->Link(&stLinkProject);
filesystem2->MakeDirectory(CUtlString("%s/bin/tools", szOutputDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/bin/tools", szOutputDir.GetString()), szOutput);
filesystem2->CopyFile(CUtlString("%s/bin/tools", szOutputDir.GetString()), "external/linux/libslang-compiler.so.0.2025.24.2");
filesystem2->CopyFile(CUtlString("%s/bin/tools", szOutputDir.GetString()), "external/linux/libslang-glslang-2025.24.2.so");
shadercompiler_exe = CUtlString("%s/bin/tools/fsc", szOutputDir.GetString());
return 1;
}
DECLARE_BUILD_STAGE(compileshaders)
{
if (CommandLine()->CheckParam("-nofsc"))
return 0;
CUtlVector<CUtlString> args = {"-i", "funnyassets", "-o", "build/funnygame/assets"};
runner->Run(shadercompiler_exe, args);
runner->Wait();
return 0;
};

61
shadercompiler/main.cpp Normal file
View File

@@ -0,0 +1,61 @@
#include "tier0/lib.h"
#include "tier1/commandline.h"
#include "tier1/appinit.h"
#include "tier1/utlstring.h"
#include "tier2/ifilesystem.h"
#include "shadercompiler/icompiler.h"
#include "materialsystem/compiledshadermgr.h"
static IShaderCompiler *s_pVulkanSpirvCompiler;
static const char *s_szGameRoot;
void CompileShader( const char *szShader )
{
CCompiledShader shader;
if (V_strcmp("shader",Plat_GetExtension(szShader)))
return;
s_pVulkanSpirvCompiler->CompileShader(szShader, &shader);
Plat_MakeDir("build/funnygame/assets", 0755);
Plat_MakeDir("build/funnygame/assets/shaders", 0755);
CUtlString szOutputDirectory = szShader;
szOutputDirectory.RemoveHead(strlen(s_szGameRoot)+1);
szOutputDirectory.AppendHead("build/funnygame/assets/");
szOutputDirectory.AppendTail("_c");
printf("%s\n",szOutputDirectory.GetString());
CompiledShaderManager()->WriteToFile(&shader, szOutputDirectory);
};
void PrintHelp()
{
printf("Usage: fsc -i [shader folder] -o [game root]");
Plat_Exit(0);
}
int main( int c, char **v )
{
CUtlString szExePath = Plat_GetExecutablePath();
CommandLine()->CreateCommandLine(c, v);
filesystem->Init();
s_pVulkanSpirvCompiler = (IShaderCompiler*)CreateInterface(SLANG_SHADER_COMPILER_SPIRV_VULKAN, NULL);
s_pVulkanSpirvCompiler->Init();
const char *szInputDirectory = CommandLine()->ParamValue("-i");
if (!szInputDirectory)
PrintHelp();
s_szGameRoot = szInputDirectory;
CUtlString szShaderDirectory = CUtlString("%s/shaders\n", szInputDirectory);
Plat_ListDirRecursive(szInputDirectory, CompileShader, NULL);
s_pVulkanSpirvCompiler->Shutdown();
return 0;
}

View File

View File

@@ -0,0 +1,144 @@
#include "shadercompiler/icompiler.h"
#include "slang.h"
#include "tier0/mem.h"
#include "tier1/utlstring.h"
#include "tier2/ifilesystem.h"
#include "vulkan/vulkan.h"
using namespace slang;
static IGlobalSession *s_pGlobalSession;
static ISession *s_pSession;
class CSlangVulkanSpirvShaderCompiler: public IShaderCompiler
{
public:
virtual void Init() override;
virtual void Shutdown() override;
virtual void CompileShader( const char *szInput, CCompiledShader *pShader ) override;
private:
IBlob *m_pDiagnostics = NULL;
void CheckDiagnostics();
void CompileShaderStage( EShaderStage eStage, const char *szMain, ISession *pSession, IModule *pModule, CCompiledShader *pShader );
};
EXPOSE_INTERFACE(CSlangVulkanSpirvShaderCompiler, IShaderCompiler, SLANG_SHADER_COMPILER_SPIRV_VULKAN)
void CSlangVulkanSpirvShaderCompiler::CompileShaderStage( EShaderStage eStage, const char *szMain, ISession *pSession, IModule *pModule, CCompiledShader *pShader )
{
SlangStage eSlangStage;
IEntryPoint *pEntryPoint = NULL;
IComponentType *pLinked = NULL;
IBlob *pBinary = NULL;
ShaderObject_t *pShaderObject = NULL;
switch (eStage)
{
case SHADER_STAGE_VERTEX:
eSlangStage = SLANG_STAGE_VERTEX;
break;
case SHADER_STAGE_PIXEL:
eSlangStage = SLANG_STAGE_PIXEL;
break;
default:
break;
}
pModule->findAndCheckEntryPoint(szMain, eSlangStage, &pEntryPoint, &m_pDiagnostics);
CheckDiagnostics();
pEntryPoint->link(&pLinked, &m_pDiagnostics);
CheckDiagnostics();
pLinked->getEntryPointCode(0, 0, &pBinary, &m_pDiagnostics);
CheckDiagnostics();
pShaderObject = pShader->AllocateShader();
pShaderObject->m_eBackend = SHADER_BACKEND_SPIRV_VULKAN;
pShaderObject->m_eStage = eStage;
pShaderObject->m_nDataLump = pShader->AllocateLump(pBinary->getBufferSize());
V_memcpy(pShader->GetLumpPtr(pShaderObject->m_nDataLump), pBinary->getBufferPointer(), pBinary->getBufferSize());
pEntryPoint->release();
}
void CSlangVulkanSpirvShaderCompiler::CompileShader( const char *szInput, CCompiledShader *pShader )
{
SessionDesc stSessionDesc = {};
TargetDesc stTargetDesc = {};
PreprocessorMacroDesc stStageMacroDesc = {};
const char *szMainName;
IModule *pModule = NULL;
ISession *pSession = NULL;
IBlob *pShaderSourceBlob = NULL;
IFileHandle *pFile = filesystem->Open(szInput, FILEMODE_READ);
const char *szShaderSource = filesystem->ReadString(pFile);
int i = 0;
pShaderSourceBlob = slang_createBlob(szShaderSource, pFile->Size());
filesystem->Close(pFile);
printf(" SLANG %s\n", szInput);
stSessionDesc.targetCount = 1;
stSessionDesc.targets = &stTargetDesc;
stTargetDesc.format = SLANG_SPIRV;
stTargetDesc.profile = s_pGlobalSession->findProfile("spirv_1_6");
for ( i = 0; i<SHADER_STAGE_COUNT; i++ )
{
szMainName = NULL;
switch (i)
{
case SHADER_STAGE_VERTEX:
szMainName = "vsMain";
stStageMacroDesc = { "VS_SHADER", "Enabled" };
break;
case SHADER_STAGE_PIXEL:
szMainName = "psMain";
stStageMacroDesc = { "PS_SHADER", "Enabled" };
break;
default:
break;
}
stSessionDesc.preprocessorMacroCount = 1;
stSessionDesc.preprocessorMacros = &stStageMacroDesc;
if ( szMainName == NULL )
continue;
pSession = NULL;
s_pGlobalSession->createSession(stSessionDesc, &pSession);
pModule = pSession->loadModuleFromSource("main", szInput, pShaderSourceBlob, &m_pDiagnostics);
CheckDiagnostics();
CompileShaderStage((EShaderStage)i, szMainName, pSession, pModule, pShader);
pModule->release();
pSession->release();
}
V_free((void*)szShaderSource);
}
void CSlangVulkanSpirvShaderCompiler::CheckDiagnostics()
{
if (m_pDiagnostics)
{
V_printf("%s\n",(const char*)m_pDiagnostics->getBufferPointer());
Plat_Exit(0);
}
};
void CSlangVulkanSpirvShaderCompiler::Init()
{
createGlobalSession(&s_pGlobalSession);
}
void CSlangVulkanSpirvShaderCompiler::Shutdown()
{
s_pGlobalSession->Release();
}

View File

@@ -15,6 +15,7 @@ DECLARE_BUILD_STAGE(tier0)
{ {
CProject_t compileProject = {}; CProject_t compileProject = {};
LinkProject_t ldProject = {}; LinkProject_t ldProject = {};
CUtlString szOutputProject = "";
compileProject.m_szName = "tier0"; compileProject.m_szName = "tier0";
compileProject.files = tier0_CompiledFiles; compileProject.files = tier0_CompiledFiles;
@@ -22,18 +23,21 @@ DECLARE_BUILD_STAGE(tier0)
compileProject.bFPIC = true; compileProject.bFPIC = true;
ldProject = ccompiler->Compile(&compileProject); ldProject = ccompiler->Compile(&compileProject);
if (bStaticBuild) if (bStaticBuild)
ldProject.linkType = ELINK_STATIC_LIBRARY;
else
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
CUtlString outputProject = linker->Link(&ldProject);
if (!bStaticBuild)
{ {
ldProject.linkType = ELINK_STATIC_LIBRARY;
szOutputProject = linker->Link(&ldProject);
tier0_lib = szOutputProject;
}
else
{
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
szOutputProject = linker->Link(&ldProject);
filesystem2->MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString())); filesystem2->MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), outputProject); filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), szOutputProject);
} else {
tier0_lib = outputProject; ldProject.linkType = ELINK_STATIC_LIBRARY;
szOutputProject = linker->Link(&ldProject);
tier0_lib = szOutputProject;
} }
return 0; return 0;

View File

@@ -117,6 +117,10 @@ PLATFORM_INTERFACE char *Plat_GetExtension( const char *szPath )
} }
return last+1; return last+1;
} }
PLATFORM_INTERFACE void Plat_MakeDir( const char *szPath, int iPermissions )
{
mkdir(szPath, ACCESSPERMS);
}
PLATFORM_INTERFACE void Plat_Backtrace( void ) PLATFORM_INTERFACE void Plat_Backtrace( void )
{ {
@@ -196,6 +200,45 @@ PLATFORM_INTERFACE void *Plat_GetProc( void *lib, const char *psz )
return (void*)GetProcAddress((HMODULE)lib, psz); return (void*)GetProcAddress((HMODULE)lib, psz);
#endif #endif
} }
PLATFORM_INTERFACE void Plat_SetEnv( const char *szVar, const char *psz )
{
setenv(szVar, psz, true);
}
PLATFORM_INTERFACE const char *Plat_GetEnv( const char *szVar )
{
return getenv(szVar);
}
PLATFORM_INTERFACE void Plat_SetWorkingDir( const char *psz )
{
}
PLATFORM_INTERFACE const char *Plat_GetWorkingDir( void )
{
}
#ifndef MAX_PATH
#define MAX_PATH 4096
#endif
static char s_szExecutablePath[MAX_PATH];
#ifdef __linux__
static ssize_t s_iExecutablePathSize = readlink("/proc/self/exe", s_szExecutablePath, MAX_PATH);
#endif
PLATFORM_INTERFACE const char *Plat_GetExecutablePath( void )
{
return s_szExecutablePath;
}
PLATFORM_INTERFACE const char *Plat_GetParentDir( const char *psz )
{
}
PLATFORM_INTERFACE void Plat_UnloadLibrary( void *lib ) PLATFORM_INTERFACE void Plat_UnloadLibrary( void *lib )
{ {
#ifdef __linux__ #ifdef __linux__

View File

@@ -6,6 +6,7 @@
CUtlVector<CUtlString> tier1_CompiledFiles = { CUtlVector<CUtlString> tier1_CompiledFiles = {
"tier1/interface.cpp", "tier1/interface.cpp",
"tier1/appinit.cpp",
"tier1/commandline.cpp", "tier1/commandline.cpp",
"tier1/utlbuffer.cpp", "tier1/utlbuffer.cpp",
"tier1/utlmap.cpp", "tier1/utlmap.cpp",

13
tier1/appinit.cpp Normal file
View File

@@ -0,0 +1,13 @@
#include "tier1/appinit.h"
#include "tier1/utlstring.h"
#include "tier0/platform.h"
void AppInitializePath()
{
const char *szPath = Plat_GetExecutablePath();
CUtlString szEnv = Plat_GetEnv("PATH");
printf("%s\n",szEnv.GetString());
szEnv.AppendTail(":");
szEnv.AppendTail(szPath);
Plat_SetEnv("PATH", szEnv);
}

View File

@@ -27,3 +27,8 @@ void *CreateInterface( const char *szName, int *pReturnCode )
*pReturnCode = 1; *pReturnCode = 1;
return 0; return 0;
} }
CreateInterfaceFn Plat_GetInterfaceFactory( void *lib )
{
return (CreateInterfaceFn)Plat_GetProc(lib, "CreateInterface");
}

View File

@@ -62,16 +62,83 @@ void CUtlString::AppendAt( size_t nPosition, const char *psz )
void CUtlString::RemoveTail( size_t nCount ) void CUtlString::RemoveTail( size_t nCount )
{ {
m_data.RemoveTail(nCount);
m_data[m_data.GetSize()-1] = 0;
} }
void CUtlString::RemoveHead( size_t nCount ) void CUtlString::RemoveHead( size_t nCount )
{ {
m_data.RemoveHead(nCount);
} }
void CUtlString::RemoveAt( size_t nPosition, size_t nCount ) void CUtlString::RemoveAt( size_t nPosition, size_t nCount )
{ {
} }
CUtlString CUtlString::GetFileName()
{
CUtlString szFileName = GetString();
char *pLast = &m_data[GetLenght()-1];
while (pLast != m_data.GetData())
{
if (*pLast=='/')
break;
pLast--;
}
return pLast;
}
CUtlString CUtlString::GetDirectory()
{
if (GetLenght() == 0)
return NULL;
size_t iNumDeleted = 0;
char *pLast = &m_data[GetLenght()-1];
CUtlString szDirectory = GetString();
while (pLast != m_data.GetData())
{
if (*pLast=='/')
{
iNumDeleted++;
break;
}
pLast--;
iNumDeleted++;
}
szDirectory.RemoveTail(iNumDeleted);
return szDirectory;
}
CUtlString CUtlString::RemoveHeadFile()
{
size_t iLenght = GetLenght();
size_t iNumDeleted = 0;
char *pc = GetString();
CUtlString szDirectory = pc;
if (GetLenght() == 0)
return NULL;
while ( iNumDeleted < iLenght )
{
if (*pc == '/')
goto remove_slashes;
pc++;
iNumDeleted++;
}
return NULL;
remove_slashes:
while ( iNumDeleted < iLenght )
{
if (*pc != '/')
{
szDirectory.RemoveHead(iNumDeleted);
return szDirectory;
}
pc++;
iNumDeleted++;
}
return NULL;
}
char *CUtlString::GetString( void ) char *CUtlString::GetString( void )
{ {

View File

@@ -94,6 +94,12 @@ public:
return buffer; return buffer;
} }
virtual const char *ReadString( IFileHandle *pFile ) override {
char *szString = (char*)V_malloc(Size(pFile)+1);
Read(pFile, szString, Size(pFile));
szString[Size(pFile)] = 0;
return szString;
};
}; };

View File

@@ -1,6 +1,7 @@
#include "tier2/ifilesystem.h" #include "tier2/ifilesystem.h"
#include "tier1/interface.h" #include "tier1/interface.h"
#include "tier0/lib.h" #include "tier0/lib.h"
#include "errno.h"
class CLIBCFileHandle : public IFileHandle class CLIBCFileHandle : public IFileHandle
{ {
@@ -29,6 +30,9 @@ public:
case FILEMODE_READ: case FILEMODE_READ:
szOperation = "rb"; szOperation = "rb";
break; break;
case FILEMODE_WRITE:
szOperation = "wb";
break;
default: default:
V_printf("Operation is not supported\n"); V_printf("Operation is not supported\n");
break; break;
@@ -36,7 +40,10 @@ public:
pFile = V_fopen(szFileName, szOperation); pFile = V_fopen(szFileName, szOperation);
if (!pFile) if (!pFile)
{
Plat_FatalErrorFunc("Failed to open %s: %s\n",strerror(errno));
return NULL; return NULL;
}
pHandle = new CLIBCFileHandle; pHandle = new CLIBCFileHandle;
pHandle->m_pFileSystem = this; pHandle->m_pFileSystem = this;
@@ -48,7 +55,10 @@ public:
} }
virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override
{ {
return 0; CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
if (!pHandle)
return 0;
return V_fwrite( pData, 1, nDataSize, pHandle->m_pFile);
} }
virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override
{ {
@@ -109,6 +119,7 @@ public:
} }
virtual CUtlBuffer<unsigned char> Read( IFileHandle *pFile ) override { return NULL; }; virtual CUtlBuffer<unsigned char> Read( IFileHandle *pFile ) override { return NULL; };
virtual const char *ReadString( IFileHandle *pFile ) override { return NULL; };
}; };
EXPOSE_FILESYSTEM(CLIBCFileSystem, "sysfs"); EXPOSE_FILESYSTEM(CLIBCFileSystem, "sysfs");