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

View File

@@ -31,17 +31,18 @@ VkQueue g_vkDrawQueue;
VkQueue g_vkPresentQueue;
VkInstance g_vkInstance;
VmaAllocator g_vkAllocator;
VkPhysicalDevice g_vkPhysicalDevice;
VkDevice g_vkDevice;
VkSwapchainKHR g_vkSwapchain;
CUtlVector<VkFence> g_vkFences;
CUtlVector<VkSemaphore> g_vkGraphicsSemaphores;
CUtlVector<VkSemaphore> g_vkPresentSemaphores;
CUtlVector<VkFence> g_vkFences = {};
CUtlVector<VkSemaphore> g_vkGraphicsSemaphores = {};
CUtlVector<VkSemaphore> g_vkPresentSemaphores = {};
CUtlVector<VkCommandPool> g_vkCommandPools;
CUtlVector<VkCommandPool> g_vkCommandPools = {};
CUtlVector<IImage*> g_vkSwapchainImages;
CUtlVector<IImage*> g_vkSwapchainImages = {};
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();
}
@@ -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()
@@ -159,6 +182,28 @@ EMultisampleType CVkImage::GetMultisampleType()
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()
@@ -169,12 +214,10 @@ CVkBuffer::~CVkBuffer()
void CVkBuffer::SetDebugName( const char *szName )
{
}
void CVkBuffer::Lock()
{
}
void CVkBuffer::Unlock()
@@ -184,21 +227,22 @@ void CVkBuffer::Unlock()
void *CVkBuffer::Map()
{
void *pData;
pData = NULL;
vmaMapMemory(g_vkAllocator, m_allocation, &pData);
return pData;
}
void CVkBuffer::Unmap()
{
vmaUnmapMemory(g_vkAllocator, m_allocation);
}
uint32_t CVkBuffer::GetSize()
{
return m_nSize;
}
class CVkRenderContext: public IRenderContext
{
public:
@@ -206,8 +250,17 @@ public:
virtual void Frame( float fDeltaTime ) 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 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 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 );
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 void DestroyMaterial( IMaterial *pMaterial ) override;
virtual void SetMaterial( IMaterial *pMaterial ) override;
virtual void SetVertexBuffer( 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 IRenderCommandList *CreateCommandList() override;
virtual void DestroyCommandList( IRenderCommandList *pCommandList ) override;
virtual void SubmitCommandList(IRenderCommandList *pList) override;
private:
VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices );
CUtlVector<const char *> GetDeviceExtensions();
@@ -236,17 +287,45 @@ private:
void CreateSwapchain();
void DestroySwapchain();
};
CVkRenderContext s_vkRenderContext;
IRenderContext *g_pVkRenderContext = &s_vkRenderContext;
IImage *m_pOutputImage = NULL;
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
//-----------------------------------------------------------------------------
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 )
{
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
//-----------------------------------------------------------------------------
IBuffer *CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage )
IBuffer *CVkRenderContext::CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage )
{
CVkBuffer *pBuffer = new CVkBuffer(nSize, eUsage, 0);
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
// 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 )
{
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 )
{
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 )
{
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 )
{
return new CVkMaterial(pShader);
}
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 )
{
}
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;
VkPipelineLayout g_pLibraryEmptyLayout;
static IVkCommandBuffer *s_pPresentCommandBuffer;
void CVkRenderContext::Init()
{
@@ -436,21 +553,48 @@ void CVkRenderContext::Init()
VkPhysicalDeviceVulkan13Features vk13Features = {};
vk13Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
vk13Features.synchronization2 = VK_TRUE;
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.queueCreateInfoCount = 1;
stDeviceCreateInfo.pQueueCreateInfos = &stDeviceQueueCreateInfo;
stDeviceCreateInfo.enabledExtensionCount = enabledDeviceExtensions.GetSize();
stDeviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.GetData();
stDeviceCreateInfo.pNext = &vk13Features;
stDeviceCreateInfo.pNext = &vk12Features;
r = vkCreateDevice(g_vkPhysicalDevice, &stDeviceCreateInfo, NULL, &g_vkDevice);
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
for (auto &extension: enabledDeviceExtensions)
V_printf("%s\n", extension);
vkGetDeviceQueue(g_vkDevice, g_iDrawFamily, 0, &g_vkDrawQueue);
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();
@@ -468,37 +612,12 @@ void CVkRenderContext::Init()
g_pCommandBufferManager = (IVkCommandBufferManager*)CreateInterface(VULKAN_COMMAND_BUFFER_MANAGER_INTERFACE_NAME, NULL);
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");
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->AddCommand(pPresentCommand);
s_pPresentCommandBuffer->Render();
@@ -507,8 +626,7 @@ void CVkRenderContext::Init()
void CVkRenderContext::Frame( float fDeltaTime )
{
vkDeviceWaitIdle(g_vkDevice);
pCommandBuffer->Render();
s_pPresentCommandBuffer->Render();
m_bOutputImageOutdated = false;
static uint32_t s_nImageIndex = 0;
uint32_t nImageIndex = 0;
@@ -518,9 +636,7 @@ void CVkRenderContext::Frame( float fDeltaTime )
vkResetFences(g_vkDevice, 1, &g_vkFences[s_nImageIndex]);
g_vkCommandBuffers = {};
pCommandBuffer->Submit(nImageIndex);
s_pPresentCommandBuffer->Submit(nImageIndex);
VkPipelineStageFlags uPipelineStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
@@ -550,6 +666,7 @@ void CVkRenderContext::Frame( float fDeltaTime )
vkQueuePresentKHR(g_vkPresentQueue, &stPresentInfo);
s_nImageIndex = (s_nImageIndex + 1) % g_vkSwapchainImages.GetSize();
g_vkCommandBuffers = {};
}
void CVkRenderContext::CreateSwapchain()