added swapchain

This commit is contained in:
2025-08-21 20:51:27 +03:00
parent 9816455d31
commit a772ab51de
3 changed files with 108 additions and 18 deletions

View File

@@ -1,2 +1,4 @@
REQUIRED_EXTENSION(VK_KHR_SWAPCHAIN) REQUIRED_EXTENSION(VK_KHR_SWAPCHAIN)
OPTIONAL_EXTENSION(VK_KHR_RAY_TRACING_PIPELINE) OPTIONAL_EXTENSION(VK_KHR_RAY_TRACING_PIPELINE)
OPTIONAL_EXTENSION(VK_KHR_ACCELERATION_STRUCTURE)
OPTIONAL_EXTENSION(VK_KHR_DEFERRED_HOST_OPERATIONS)

View File

@@ -1,5 +1,6 @@
#include "SDL3/SDL_vulkan.h" #include "SDL3/SDL_vulkan.h"
#include "materialsystem/materialsystem.h" #include "materialsystem/materialsystem.h"
#include "tier0/lib.h"
#include "tier0/platform.h" #include "tier0/platform.h"
#include "tier1/utlstring.h" #include "tier1/utlstring.h"
#include "tier1/utlvector.h" #include "tier1/utlvector.h"
@@ -17,6 +18,7 @@ const char *g_vkDeviceExtensions[] = {
#undef REQUIRED_EXTENSION #undef REQUIRED_EXTENSION
#undef OPTIONAL_EXTENSION #undef OPTIONAL_EXTENSION
SupportedVulkanExtensions_t g_vkAvailableExtensions;
class CVkRenderContext: public IRenderContext class CVkRenderContext: public IRenderContext
@@ -38,6 +40,7 @@ private:
IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage ); IBuffer *CreateBufferAligned( uint32_t nSize, uint32_t nAlignment, VkBufferUsageFlags2 eUsage );
VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices ); VkPhysicalDevice SelectPhysicalDevice( CUtlVector<VkPhysicalDevice> physicalDevices );
CUtlVector<const char *> GetDeviceExtensions();
void CreateSwapchain(); void CreateSwapchain();
void DestroySwapchain(); void DestroySwapchain();
@@ -117,7 +120,9 @@ void CVkRenderContext::Init()
VkResult r; VkResult r;
int nExtensionCount; int nExtensionCount;
CUtlVector<const char *> extensions = {};
CUtlVector<const char *> enabledInstanceExtensions;
CUtlVector<const char *> enabledDeviceExtensions;
uint32_t nPhysicalDevicesCount; uint32_t nPhysicalDevicesCount;
CUtlVector<VkPhysicalDevice> physicalDevices; CUtlVector<VkPhysicalDevice> physicalDevices;
@@ -134,12 +139,12 @@ void CVkRenderContext::Init()
float fPriority = 1.0; float fPriority = 1.0;
r = volkInitialize(); r = volkInitialize();
VULKAN_RESULT_PRINT(r, volkInitialize) VULKAN_RESULT_PRINT(r, volkInitialize);
// Get extensions required by game window // Get extensions required by game window
nExtensionCount = gamewindow->GetVulkanInstanceExtensionCount(); nExtensionCount = gamewindow->GetVulkanInstanceExtensionCount();
extensions.Resize(nExtensionCount); enabledInstanceExtensions.Resize(nExtensionCount);
V_memcpy(extensions.GetData(), gamewindow->GetVulkanInstanceExtensions(), extensions.GetSize()*sizeof(const char*)); V_memcpy(enabledInstanceExtensions.GetData(), gamewindow->GetVulkanInstanceExtensions(), enabledInstanceExtensions.GetSize()*sizeof(const char*));
// Create instance // Create instance
stApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; stApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -149,11 +154,11 @@ void CVkRenderContext::Init()
stInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; stInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
stInstanceCreateInfo.pApplicationInfo = &stApplicationInfo; stInstanceCreateInfo.pApplicationInfo = &stApplicationInfo;
stInstanceCreateInfo.enabledExtensionCount = extensions.GetSize(); stInstanceCreateInfo.enabledExtensionCount = enabledInstanceExtensions.GetSize();
stInstanceCreateInfo.ppEnabledExtensionNames = extensions.GetData(); stInstanceCreateInfo.ppEnabledExtensionNames = enabledInstanceExtensions.GetData();
r = vkCreateInstance(&stInstanceCreateInfo, NULL, &g_vkInstance); r = vkCreateInstance(&stInstanceCreateInfo, NULL, &g_vkInstance);
VULKAN_RESULT_PRINT(r, vkCreateInstance) VULKAN_RESULT_PRINT(r, vkCreateInstance);
// volk requires to load instance this way // volk requires to load instance this way
volkLoadInstance(g_vkInstance); volkLoadInstance(g_vkInstance);
@@ -161,15 +166,17 @@ void CVkRenderContext::Init()
// Get amount of physical devices // Get amount of physical devices
r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, NULL); r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, NULL);
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
physicalDevices.Resize(nPhysicalDevicesCount); physicalDevices.Resize(nPhysicalDevicesCount);
// Read all physical devices // Read all physical devices
r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, physicalDevices.GetData()); r = vkEnumeratePhysicalDevices(g_vkInstance, &nPhysicalDevicesCount, physicalDevices.GetData());
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
g_vkPhysicalDevice = SelectPhysicalDevice(physicalDevices); g_vkPhysicalDevice = SelectPhysicalDevice(physicalDevices);
enabledDeviceExtensions = GetDeviceExtensions();
// Get all queues // Get all queues
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL); vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL);
@@ -198,6 +205,8 @@ void CVkRenderContext::Init()
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.ppEnabledExtensionNames = enabledDeviceExtensions.GetData();
vkCreateDevice(g_vkPhysicalDevice, &stDeviceCreateInfo, NULL, &g_vkDevice); vkCreateDevice(g_vkPhysicalDevice, &stDeviceCreateInfo, NULL, &g_vkDevice);
CreateSwapchain(); CreateSwapchain();
@@ -210,15 +219,61 @@ void CVkRenderContext::Frame( float fDeltaTime )
void CVkRenderContext::CreateSwapchain() void CVkRenderContext::CreateSwapchain()
{ {
uint32_t numSurfaceFormats = 0;
CUtlVector<VkSurfaceFormatKHR> surfaceFormats; CUtlVector<VkSurfaceFormatKHR> surfaceFormats;
VkSurfaceCapabilitiesKHR surfaceCapatibilities = {};
uint32_t nSurfacePresentModes = 0;
CUtlVector<VkPresentModeKHR> surfacePresentModes;
gamewindow->CreateVulkanSurface(g_vkInstance); gamewindow->CreateVulkanSurface(g_vkInstance);
VkSwapchainCreateInfoKHR stSwapchainCreateInfo = {};
stSwapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
stSwapchainCreateInfo.surface = (VkSurfaceKHR)gamewindow->GetVulkanSurface();
vkCreateSwapchainKHR(g_vkDevice, &stSwapchainCreateInfo, NULL, &g_vkSwapchain); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vkPhysicalDevice, (VkSurfaceKHR)gamewindow->GetVulkanSurface(), &surfaceCapatibilities);
const VkFormat preferedSurfaceFormats[] = {
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM,
};
vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, (VkSurfaceKHR)gamewindow->GetVulkanSurface(), &numSurfaceFormats, NULL);
surfaceFormats.Resize(numSurfaceFormats);
vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, (VkSurfaceKHR)gamewindow->GetVulkanSurface(), &numSurfaceFormats, surfaceFormats.GetData());
VkSurfaceFormatKHR selectedFormat = surfaceFormats[0];
for (auto &format: surfaceFormats)
{
for (int i = 0; i < sizeof(preferedSurfaceFormats)/sizeof(VkFormat); i++)
{
if (format.format == preferedSurfaceFormats[i])
{
selectedFormat = format;
goto formatPicked;
}
}
}
formatPicked:
vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, (VkSurfaceKHR)gamewindow->GetVulkanSurface(), &nSurfacePresentModes, NULL);
surfacePresentModes.Resize(nSurfacePresentModes);
vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, (VkSurfaceKHR)gamewindow->GetVulkanSurface(), &nSurfacePresentModes, surfacePresentModes.GetData());
VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.surface = (VkSurfaceKHR)gamewindow->GetVulkanSurface();
swapchainCreateInfo.imageFormat = selectedFormat.format;
swapchainCreateInfo.imageColorSpace = selectedFormat.colorSpace;
swapchainCreateInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
swapchainCreateInfo.preTransform = surfaceCapatibilities.currentTransform;
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapchainCreateInfo.imageArrayLayers = 1;
swapchainCreateInfo.imageExtent = surfaceCapatibilities.minImageExtent;
swapchainCreateInfo.minImageCount = surfaceCapatibilities.minImageCount;
vkCreateSwapchainKHR(g_vkDevice, &swapchainCreateInfo, NULL, &g_vkSwapchain);
} }
@@ -257,11 +312,11 @@ VkPhysicalDevice CVkRenderContext::SelectPhysicalDevice( CUtlVector<VkPhysicalDe
uint32_t uScore = 0; uint32_t uScore = 0;
r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, NULL); r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, NULL);
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
extensions.Resize(nExtensionCount); extensions.Resize(nExtensionCount);
r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, extensions.GetData()); r = vkEnumerateDeviceExtensionProperties(device, NULL, &nExtensionCount, extensions.GetData());
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices) VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
vkGetPhysicalDeviceProperties(device, &stPhysicalDeviceProperties); vkGetPhysicalDeviceProperties(device, &stPhysicalDeviceProperties);
vkGetPhysicalDeviceFeatures(device, &stPhysicalDeviceFeatures); vkGetPhysicalDeviceFeatures(device, &stPhysicalDeviceFeatures);
@@ -281,4 +336,37 @@ VkPhysicalDevice CVkRenderContext::SelectPhysicalDevice( CUtlVector<VkPhysicalDe
return selectedDevice; return selectedDevice;
} }
CUtlVector<const char *> CVkRenderContext::GetDeviceExtensions()
{
VkResult r;
int i;
uint32_t nExtensionCount;
CUtlVector<VkExtensionProperties> extensions;
CUtlVector<const char *> enabledExtensions;
const char *szExtensionName;
r = vkEnumerateDeviceExtensionProperties(g_vkPhysicalDevice, NULL, &nExtensionCount, NULL);
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
extensions.Resize(nExtensionCount);
r = vkEnumerateDeviceExtensionProperties(g_vkPhysicalDevice, NULL, &nExtensionCount, extensions.GetData());
VULKAN_RESULT_PRINT(r, vkEnumeratePhysicalDevices);
#define REQUIRED_EXTENSION(ext) if (!V_strcmp(extension.extensionName, ext##_EXTENSION_NAME)) { g_vkAvailableExtensions.bIsSupported_##ext = true; enabledExtensions.AppendTail(ext##_EXTENSION_NAME); continue; };
#define OPTIONAL_EXTENSION(ext) REQUIRED_EXTENSION(ext);
for ( auto extension: extensions )
{
#include "device_extensions.h"
}
#undef REQUIRED_EXTENSION
#undef OPTIONAL_EXTENSION
return enabledExtensions;
}

View File

@@ -10,10 +10,10 @@
#define REQUIRED_EXTENSION(ext) bool bIsSupported_##ext; #define REQUIRED_EXTENSION(ext) bool bIsSupported_##ext;
#define OPTIONAL_EXTENSION(ext) bool bIsSupported_##ext; #define OPTIONAL_EXTENSION(ext) bool bIsSupported_##ext;
struct SupportedVulkanExtensions_t extern struct SupportedVulkanExtensions_t
{ {
#include "device_extensions.h" #include "device_extensions.h"
}; } g_vkAvailableExtensions;
#undef REQUIRED_EXTENSION #undef REQUIRED_EXTENSION
#undef OPTIONAL_EXTENSION #undef OPTIONAL_EXTENSION
@@ -52,6 +52,6 @@ extern IVkCommandBuffer *vkcommandbuffer;
#define VULKAN_RESULT_PRINT(r, func) \ #define VULKAN_RESULT_PRINT(r, func) \
if (r != VK_SUCCESS) \ if (r != VK_SUCCESS) \
Plat_FatalErrorFunc(#func " failed: %s\n", string_VkResult(r)); Plat_FatalErrorFunc(#func " failed: %s\n", string_VkResult(r))
#endif #endif