Files
funnygame/materialsystem/vulkan/rendercontext.cpp
2025-08-20 01:27:25 +03:00

275 lines
8.4 KiB
C++

#include "SDL3/SDL_vulkan.h"
#include "materialsystem/materialsystem.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#define VK_NO_PROTOTYPES
#include "vulkan/vulkan_core.h"
#include "vulkan_state.h"
#include "igamewindow.h"
#define REQUIRED_EXTENSION(ext) ext##_EXTENSION_NAME,
#define OPTIONAL_EXTENSION(ext) ext##_EXTENSION_NAME,
const char *g_vkDeviceExtensions[] = {
#include "device_extensions.h"
};
#undef REQUIRED_EXTENSION
#undef OPTIONAL_EXTENSION
class CVkRenderContext: public IRenderContext
{
public:
virtual void Init() override;
virtual void Frame( float fDeltaTime ) override;
virtual void Shutdown() override;
virtual IVertexBuffer *CreateVertexBuffer( uint32_t nSize ) override;
virtual IIndexBuffer *CreateIndexBuffer( uint32_t nSize ) override;
virtual IImage *CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) override;
virtual IImage *CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType ) override;
virtual void DestroyBuffer( IBuffer *pBuffer ) override;
virtual void DestroyImage( IImage *pImage ) override;
private:
IBuffer *CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage );
IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage );
VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices );
void CreateSwapchain();
void DestroySwapchain();
};
//-----------------------------------------------------------------------------
// Creates vertex buffer. Wrapper over CreateBuffer
//-----------------------------------------------------------------------------
IVertexBuffer *CVkRenderContext::CreateVertexBuffer( uint32_t nSize )
{
return (IVertexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT);
}
//-----------------------------------------------------------------------------
// Creates index buffer. Wrapper over CreateBuffer
//-----------------------------------------------------------------------------
IIndexBuffer *CVkRenderContext::CreateIndexBuffer( uint32_t nSize )
{
return (IIndexBuffer*)CreateBuffer(nSize, VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT);
}
//-----------------------------------------------------------------------------
// Creates basic vulkan buffer
//-----------------------------------------------------------------------------
IBuffer *CreateBuffer( uint32_t nSize, VkBufferUsageFlags2 eUsage )
{
}
//-----------------------------------------------------------------------------
// Creates vulkan buffer aligned to the nAlignment
// Useful for everything eg: ray tracing, which requires them to be aligned
// to the groupBaseAlignment.
//-----------------------------------------------------------------------------
IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage )
{
}
IImage *CVkRenderContext::CreateRenderTarget( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType )
{
}
IImage *CVkRenderContext::CreateStorageImage( uint32_t x, uint32_t y, EImageFormat eFormat, EMultisampleType eMultisampleType )
{
}
void CVkRenderContext::DestroyBuffer( IBuffer *pBuffer )
{
}
void CVkRenderContext::DestroyImage( IImage *pImage )
{
}
CVkRenderContext s_vkRenderContext;
IRenderContext *g_pVkRenderContext = &s_vkRenderContext;
uint32_t g_iDrawFamily;
uint32_t g_iPresentFamily;
VkInstance g_vkInstance;
VkPhysicalDevice g_vkPhysicalDevice;
VkDevice g_vkDevice;
VkSwapchainKHR g_vkSwapchain;
void CVkRenderContext::Init()
{
VkResult r;
int nExtensionCount;
CUtlVector<const char *> extensions = {};
uint32_t nPhysicalDevicesCount;
CUtlVector<VkPhysicalDevice> physicalDevices;
uint32_t nNumQueueFamilies = 0;
CUtlVector<VkQueueFamilyProperties> queueFamilyProperties;
VkApplicationInfo stApplicationInfo = {};
VkInstanceCreateInfo stInstanceCreateInfo = {};
VkDeviceQueueCreateInfo stDeviceQueueCreateInfo = {};
VkDeviceCreateInfo stDeviceCreateInfo = {};
float fPriority = 1.0;
r = volkInitialize();
VULKAN_RESULT_PRINT(r, volkInitialize)
// Get extensions required by game window
nExtensionCount = gamewindow->GetVulkanInstanceExtensionCount();
extensions.Resize(nExtensionCount);
V_memcpy(extensions.GetData(), gamewindow->GetVulkanInstanceExtensions(), extensions.GetSize()*sizeof(const char*));
// Create instance
stApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
stApplicationInfo.apiVersion = VK_API_VERSION_1_4;
stApplicationInfo.pApplicationName = "funny";
stApplicationInfo.pEngineName = "funny";
stInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
stInstanceCreateInfo.pApplicationInfo = &stApplicationInfo;
stInstanceCreateInfo.enabledExtensionCount = extensions.GetSize();
stInstanceCreateInfo.ppEnabledExtensionNames = extensions.GetData();
r = vkCreateInstance(&stInstanceCreateInfo, NULL, &g_vkInstance);
VULKAN_RESULT_PRINT(r, vkCreateInstance)
// volk requires to load instance this way
volkLoadInstance(g_vkInstance);
// Get amount of physical devices
r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, NULL);
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices)
physicalDevices.Resize(nPhysicalDevicesCount);
// Read all physical devices
r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, physicalDevices.GetData());
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices)
g_vkPhysicalDevice = SelectPhysicalDevice(physicalDevices);
// Get all queues
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL);
queueFamilyProperties.Resize(nNumQueueFamilies);
uint32_t i = 0;
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, queueFamilyProperties.GetData());
for (auto &family: queueFamilyProperties)
{
if (family.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
g_iDrawFamily = i;
g_iPresentFamily = i;
}
i++;
}
// Create device
stDeviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
stDeviceQueueCreateInfo.queueCount = 1;
stDeviceQueueCreateInfo.pQueuePriorities = &fPriority;
stDeviceQueueCreateInfo.queueFamilyIndex = g_iDrawFamily;
stDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
stDeviceCreateInfo.queueCreateInfoCount = 1;
stDeviceCreateInfo.pQueueCreateInfos = &stDeviceQueueCreateInfo;
vkCreateDevice(g_vkPhysicalDevice, &stDeviceCreateInfo, NULL, &g_vkDevice);
CreateSwapchain();
}
void CVkRenderContext::Frame( float fDeltaTime )
{
}
void CVkRenderContext::CreateSwapchain()
{
gamewindow->CreateVulkanSurface(g_vkInstance);
}
void CVkRenderContext::DestroySwapchain()
{
vkDestroySwapchainKHR(g_vkDevice, g_vkSwapchain, NULL);
gamewindow->DestroyVulkanSurface(g_vkInstance);
}
//-----------------------------------------------------------------------------
// TODO: Move to the rendering context
//-----------------------------------------------------------------------------
void CVkRenderContext::Shutdown()
{
vkDestroyInstance(g_vkInstance, NULL);
}
//-----------------------------------------------------------------------------
// Selects best device to be used in rendering.
// We want to get the best perfomance out of the GPU, so we need to select the
// best driver.
//-----------------------------------------------------------------------------
VkPhysicalDevice CVkRenderContext::SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices )
{
uint32_t uMaxScore = 0;
VkPhysicalDevice selectedDevice = 0;
VkResult r;
for (auto &device: physicalDevices)
{
uint32_t nExtensionCount;
CUtlVector<VkExtensionProperties> extensions;
VkPhysicalDeviceFeatures stPhysicalDeviceFeatures;
VkPhysicalDeviceProperties stPhysicalDeviceProperties;
uint32_t uScore = 0;
r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, NULL);
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices)
extensions.Resize(nExtensionCount);
r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, extensions.GetData());
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices)
vkGetPhysicalDeviceProperties(device, &stPhysicalDeviceProperties);
vkGetPhysicalDeviceFeatures(device, &stPhysicalDeviceFeatures);
if (stPhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
uScore += 1000;
if (stPhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
uScore += 500;
if (uScore >= uMaxScore)
{
selectedDevice = device;
uMaxScore = uScore;
}
}
return selectedDevice;
}