Boot vulkan without a surface

This commit is contained in:
Magnus Norddahl 2025-01-06 07:01:36 +01:00
commit 77b23a58f0
7 changed files with 92 additions and 44 deletions

View file

@ -37,6 +37,7 @@
#endif
#include "i_common.h"
#include "i_interface.h"
#include "v_video.h"
#include "bitmap.h"
@ -357,17 +358,23 @@ public:
VulkanInstanceBuilder builder;
builder.DebugLayer(vk_debug);
builder.RequireExtension(VK_KHR_SURFACE_EXTENSION_NAME); // KHR_surface, required
builder.OptionalExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME); // EXT_metal_surface, optional, preferred
builder.OptionalExtension(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); // MVK_macos_surface, optional, deprecated
if (!RunningAsTool)
{
builder.OptionalExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME); // EXT_metal_surface, optional, preferred
builder.OptionalExtension(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); // MVK_macos_surface, optional, deprecated
}
auto vulkanInstance = builder.Create();
VkSurfaceKHR surfacehandle = nullptr;
if (!I_CreateVulkanSurface(vulkanInstance->Instance, &surfacehandle))
VulkanError("I_CreateVulkanSurface failed");
if (!RunningAsTool)
{
VkSurfaceKHR surfacehandle = nullptr;
if (!I_CreateVulkanSurface(vulkanInstance->Instance, &surfacehandle))
VulkanError("I_CreateVulkanSurface failed");
m_vulkanSurface = std::make_shared<VulkanSurface>(vulkanInstance, surfacehandle);
m_vulkanSurface = std::make_shared<VulkanSurface>(vulkanInstance, surfacehandle);
}
fb = new VulkanRenderDevice(nullptr, vid_fullscreen, m_vulkanSurface);
fb = new VulkanRenderDevice(nullptr, vid_fullscreen, vulkanInstance, m_vulkanSurface);
#else
#error "Vulkan support must be enabled!"
#endif

View file

@ -37,6 +37,7 @@
#include "i_soundinternal.h"
#include "i_system.h"
#include "i_video.h"
#include "i_interface.h"
#include "m_argv.h"
#include "v_video.h"
#include "version.h"
@ -334,22 +335,31 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer ()
unsigned int count = 64;
const char* names[64];
if (!I_GetVulkanPlatformExtensions(&count, names))
VulkanError("I_GetVulkanPlatformExtensions failed");
if (!RunningAsTool)
{
if (!I_GetVulkanPlatformExtensions(&count, names))
VulkanError("I_GetVulkanPlatformExtensions failed");
}
VulkanInstanceBuilder builder;
builder.DebugLayer(vk_debug);
for (unsigned int i = 0; i < count; i++)
builder.RequireExtension(names[i]);
if (!RunningAsTool)
{
for (unsigned int i = 0; i < count; i++)
builder.RequireExtension(names[i]);
}
auto instance = builder.Create();
VkSurfaceKHR surfacehandle = nullptr;
if (!I_CreateVulkanSurface(instance->Instance, &surfacehandle))
VulkanError("I_CreateVulkanSurface failed");
if (!RunningAsTool)
{
VkSurfaceKHR surfacehandle = nullptr;
if (!I_CreateVulkanSurface(instance->Instance, &surfacehandle))
VulkanError("I_CreateVulkanSurface failed");
surface = std::make_shared<VulkanSurface>(instance, surfacehandle);
surface = std::make_shared<VulkanSurface>(instance, surfacehandle);
}
fb = new VulkanRenderDevice(nullptr, vid_fullscreen, surface);
fb = new VulkanRenderDevice(nullptr, vid_fullscreen, instance, surface);
#endif
return fb;

View file

@ -3,6 +3,7 @@
#include "win32basevideo.h"
#include "c_cvars.h"
#include "vulkan/vk_renderdevice.h"
#include "i_interface.h"
#include <zvulkan/vulkansurface.h>
#include <zvulkan/vulkanbuilders.h>
@ -22,26 +23,34 @@ EXTERN_CVAR(Int, vk_device)
class Win32VulkanVideo : public Win32BaseVideo
{
std::shared_ptr<VulkanSurface> surface;
public:
Win32VulkanVideo()
{
unsigned int count = 64;
const char* names[64];
if (!I_GetVulkanPlatformExtensions(&count, names))
VulkanError("I_GetVulkanPlatformExtensions failed");
if (!RunningAsTool)
{
if (!I_GetVulkanPlatformExtensions(&count, names))
VulkanError("I_GetVulkanPlatformExtensions failed");
}
VulkanInstanceBuilder builder;
builder.DebugLayer(vk_debug);
for (unsigned int i = 0; i < count; i++)
builder.RequireExtension(names[i]);
auto instance = builder.Create();
if (!RunningAsTool)
{
for (unsigned int i = 0; i < count; i++)
builder.RequireExtension(names[i]);
}
instance = builder.Create();
VkSurfaceKHR surfacehandle = nullptr;
if (!I_CreateVulkanSurface(instance->Instance, &surfacehandle))
VulkanError("I_CreateVulkanSurface failed");
if (!RunningAsTool)
{
VkSurfaceKHR surfacehandle = nullptr;
if (!I_CreateVulkanSurface(instance->Instance, &surfacehandle))
VulkanError("I_CreateVulkanSurface failed");
surface = std::make_shared<VulkanSurface>(instance, surfacehandle);
surface = std::make_shared<VulkanSurface>(instance, surfacehandle);
}
}
~Win32VulkanVideo()
@ -55,9 +64,11 @@ public:
DFrameBuffer *CreateFrameBuffer() override
{
auto fb = new VulkanRenderDevice(m_hMonitor, vid_fullscreen, surface);
auto fb = new VulkanRenderDevice(m_hMonitor, vid_fullscreen, instance, surface);
return fb;
}
protected:
private:
std::shared_ptr<VulkanInstance> instance;
std::shared_ptr<VulkanSurface> surface;
};

View file

@ -33,16 +33,19 @@ CVAR(Bool, vk_exclusivefullscreen, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
VkFramebufferManager::VkFramebufferManager(VulkanRenderDevice* fb) : fb(fb)
{
SwapChain = VulkanSwapChainBuilder()
.Create(fb->GetDevice());
if (fb->IsSurfaceAvailable())
{
SwapChain = VulkanSwapChainBuilder()
.Create(fb->GetDevice());
SwapChainImageAvailableSemaphore = SemaphoreBuilder()
.DebugName("SwapChainImageAvailableSemaphore")
.Create(fb->GetDevice());
SwapChainImageAvailableSemaphore = SemaphoreBuilder()
.DebugName("SwapChainImageAvailableSemaphore")
.Create(fb->GetDevice());
RenderFinishedSemaphore = SemaphoreBuilder()
.DebugName("RenderFinishedSemaphore")
.Create(fb->GetDevice());
RenderFinishedSemaphore = SemaphoreBuilder()
.DebugName("RenderFinishedSemaphore")
.Create(fb->GetDevice());
}
}
VkFramebufferManager::~VkFramebufferManager()
@ -51,6 +54,9 @@ VkFramebufferManager::~VkFramebufferManager()
void VkFramebufferManager::AcquireImage()
{
if (!SwapChain)
return;
bool exclusiveFullscreen = fb->IsFullscreen() && vk_exclusivefullscreen;
if (SwapChain->Lost() || fb->GetClientWidth() != CurrentWidth || fb->GetClientHeight() != CurrentHeight || fb->GetVSync() != CurrentVSync || CurrentHdr != vk_hdr || CurrentExclusiveFullscreen != exclusiveFullscreen)
{

View file

@ -160,15 +160,19 @@ void VulkanPrintLog(const char* typestr, const std::string& msg)
}
}
VulkanRenderDevice::VulkanRenderDevice(void *hMonitor, bool fullscreen, std::shared_ptr<VulkanSurface> surface) : SystemBaseFrameBuffer(hMonitor, fullscreen)
VulkanRenderDevice::VulkanRenderDevice(void *hMonitor, bool fullscreen, std::shared_ptr<VulkanInstance> instance, std::shared_ptr<VulkanSurface> surface) : SystemBaseFrameBuffer(hMonitor, fullscreen)
{
VulkanDeviceBuilder builder;
builder.OptionalRayQuery();
builder.RequireExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
builder.Surface(surface);
if (surface)
{
HasSurface = true;
builder.Surface(surface);
}
builder.SelectDevice(vk_device);
SupportedDevices = builder.FindDevices(surface->Instance);
mDevice = builder.Create(surface->Instance);
SupportedDevices = builder.FindDevices(instance);
mDevice = builder.Create(instance);
bool supportsBindless =
mDevice->EnabledFeatures.DescriptorIndexing.descriptorBindingPartiallyBound &&

View file

@ -28,7 +28,7 @@ class VkRenderPassSetup;
class VulkanRenderDevice : public SystemBaseFrameBuffer
{
public:
VulkanRenderDevice(void* hMonitor, bool fullscreen, std::shared_ptr<VulkanSurface> surface);
VulkanRenderDevice(void* hMonitor, bool fullscreen, std::shared_ptr<VulkanInstance> instance, std::shared_ptr<VulkanSurface> surface);
~VulkanRenderDevice();
VulkanDevice* GetDevice() { return mDevice.get(); }
@ -98,11 +98,15 @@ public:
const VkPipelineKey& GetLevelMeshPipelineKey(int id) const;
bool IsSurfaceAvailable() { return HasSurface; }
private:
void RenderTextureView(FCanvasTexture* tex, std::function<void(IntRect &)> renderFunc) override;
void PrintStartupLog();
void CopyScreenToBuffer(int w, int h, uint8_t *data) override;
bool HasSurface = false;
std::shared_ptr<VulkanDevice> mDevice;
std::unique_ptr<VkCommandBufferManager> mCommands;
std::unique_ptr<VkBufferManager> mBufferManager;

View file

@ -3538,10 +3538,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector<std::string>& allw
}
if (RunningAsTool)
{
// To do: is enough of the engine initialized now for running tool commandlets?
return 0;
}
if (StartScreen)
{
@ -3852,6 +3849,15 @@ static int D_DoomMain_Internal (void)
iwad_man = NULL;
if (ret != 0) return ret;
if (RunningAsTool)
{
// To do: We got a game loaded and can now process commandlets
Printf("\n");
Printf("Specify " TEXTCOLOR_ORANGE "--help" TEXTCOLOR_NORMAL " for a list of commands\n");
return 0;
}
D_DoAnonStats();
I_UpdateWindowTitle();
D_DoomLoop (); // this only returns if a 'restart' CCMD is given.