SDL Vulkan support.

This commit is contained in:
Dario 2024-12-23 00:52:43 -03:00
parent 67422c3b64
commit 76df0b4d9e
5 changed files with 88 additions and 3 deletions

View File

@ -3258,7 +3258,7 @@ namespace RT64 {
D3D12MA::ALLOCATOR_DESC allocatorDesc = {};
allocatorDesc.pDevice = d3d;
allocatorDesc.pAdapter = adapter;
allocatorDesc.Flags = D3D12MA::ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED;
allocatorDesc.Flags = D3D12MA::ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED | D3D12MA::ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED;
res = D3D12MA::CreateAllocator(&allocatorDesc, &allocator);
if (FAILED(res)) {

View File

@ -121,6 +121,8 @@ namespace RT64 {
SDL_GetWindowWMInfo(sdlWindow, &wmInfo);
# if defined(_WIN32)
windowHandle = wmInfo.info.win.window;
# elif defined(RT64_SDL_WINDOW_VULKAN)
windowHandle = sdlWindow;
# elif defined(__ANDROID__)
static_assert(false && "Android unimplemented");
# elif defined(__linux__)
@ -236,6 +238,21 @@ namespace RT64 {
if ((refreshRate % 10) == 9) {
refreshRate++;
}
# elif defined(RT64_SDL_WINDOW_VULKAN)
int displayIndex = SDL_GetWindowDisplayIndex(windowHandle);
if (displayIndex < 0) {
fprintf(stderr, "SDL_GetWindowDisplayIndex failed. Error: %s.\n", SDL_GetError());
return;
}
SDL_DisplayMode displayMode = {};
int modeResult = SDL_GetCurrentDisplayMode(displayIndex, &displayMode);
if (modeResult != 0) {
fprintf(stderr, "SDL_GetCurrentDisplayMode failed. Error: %s.\n", SDL_GetError());
return;
}
refreshRate = displayMode.refresh_rate;
# elif defined(__linux__)
// Sourced from: https://stackoverflow.com/a/66865623
XRRScreenResources *screenResources = XRRGetScreenResources(windowHandle.display, windowHandle.window);
@ -287,6 +304,8 @@ namespace RT64 {
GetWindowRect(windowHandle, &rect);
newWindowLeft = rect.left;
newWindowTop = rect.top;
# elif defined(RT64_SDL_WINDOW_VULKAN)
SDL_GetWindowPosition(windowHandle, &newWindowLeft, &newWindowTop);
# elif defined(__linux__)
XWindowAttributes attributes;
XGetWindowAttributes(windowHandle.display, windowHandle.window, &attributes);

View File

@ -26,10 +26,16 @@
typedef struct _NSWindow NSWindow;
#endif
#ifdef RT64_SDL_WINDOW_VULKAN
#include <SDL_vulkan.h>
#endif
namespace RT64 {
#if defined(_WIN64)
// Native HWND handle to the target window.
typedef HWND RenderWindow;
#elif defined(RT64_SDL_WINDOW_VULKAN)
typedef SDL_Window *RenderWindow;
#elif defined(__ANDROID__)
typedef ANativeWindow* RenderWindow;
#elif defined(__linux__)

View File

@ -1921,6 +1921,13 @@ namespace RT64 {
fprintf(stderr, "vkCreateWin32SurfaceKHR failed with error code 0x%X.\n", res);
return;
}
# elif defined(RT64_SDL_WINDOW_VULKAN)
VulkanInterface *renderInterface = commandQueue->device->renderInterface;
SDL_bool sdlRes = SDL_Vulkan_CreateSurface(renderWindow, renderInterface->instance, &surface);
if (sdlRes == SDL_FALSE) {
fprintf(stderr, "SDL_Vulkan_CreateSurface failed with error %s.\n", SDL_GetError());
return;
}
# elif defined(__ANDROID__)
assert(renderWindow != nullptr);
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
@ -2056,6 +2063,12 @@ namespace RT64 {
}
bool VulkanSwapChain::present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) {
constexpr uint64_t MaxFrameDelay = 1;
if (commandQueue->device->capabilities.presentWait && (currentPresentId > MaxFrameDelay)) {
constexpr uint64_t waitTimeout = 100000000;
vkWaitForPresentKHR(commandQueue->device->vk, vk, currentPresentId - MaxFrameDelay, waitTimeout);
}
thread_local std::vector<VkSemaphore> waitSemaphoresVector;
waitSemaphoresVector.clear();
for (uint32_t i = 0; i < waitSemaphoreCount; i++) {
@ -2070,6 +2083,15 @@ namespace RT64 {
presentInfo.pImageIndices = &textureIndex;
presentInfo.pWaitSemaphores = !waitSemaphoresVector.empty() ? waitSemaphoresVector.data() : nullptr;
presentInfo.waitSemaphoreCount = uint32_t(waitSemaphoresVector.size());
VkPresentIdKHR presentId = {};
if (commandQueue->device->capabilities.presentWait) {
currentPresentId++;
presentId.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR;
presentId.pPresentIds = &currentPresentId;
presentId.swapchainCount = 1;
presentInfo.pNext = &presentId;
}
VkResult res;
{
@ -2228,6 +2250,8 @@ namespace RT64 {
GetClientRect(renderWindow, &rect);
dstWidth = rect.right - rect.left;
dstHeight = rect.bottom - rect.top;
# elif defined(RT64_SDL_WINDOW_VULKAN)
SDL_GetWindowSize(renderWindow, (int *)(&dstWidth), (int *)(&dstHeight));
# elif defined(__ANDROID__)
dstWidth = ANativeWindow_getWidth(renderWindow);
dstHeight = ANativeWindow_getHeight(renderWindow);
@ -3968,7 +3992,11 @@ namespace RT64 {
// VulkanInterface
#if RT64_SDL_WINDOW_VULKAN
VulkanInterface::VulkanInterface(RenderWindow sdlWindow) {
#else
VulkanInterface::VulkanInterface() {
#endif
VkResult res = volkInitialize();
if (res != VK_SUCCESS) {
fprintf(stderr, "volkInitialize failed with error code 0x%X.\n", res);
@ -3995,11 +4023,31 @@ namespace RT64 {
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, availableExtensions.data());
std::unordered_set<std::string> missingRequiredExtensions = RequiredInstanceExtensions;
std::unordered_set<std::string> requiredExtensions = RequiredInstanceExtensions;
std::unordered_set<std::string> supportedOptionalExtensions;
# if DLSS_ENABLED
const std::unordered_set<std::string> dlssExtensions = DLSS::getRequiredInstanceExtensionsVulkan();
# endif
# if RT64_SDL_WINDOW_VULKAN
// Push the extensions specified by SDL as required.
// SDL2 has this awkward requirement for the window to pull the extensions from.
// This can be removed when upgrading to SDL3.
if (sdlWindow != nullptr) {
uint32_t sdlVulkanExtensionCount = 0;
if (SDL_Vulkan_GetInstanceExtensions(sdlWindow, &sdlVulkanExtensionCount, nullptr)) {
std::vector<char *> sdlVulkanExtensions;
sdlVulkanExtensions.resize(sdlVulkanExtensionCount);
if (SDL_Vulkan_GetInstanceExtensions(sdlWindow, &sdlVulkanExtensionCount, (const char **)(sdlVulkanExtensions.data()))) {
for (char *sdlVulkanExtension : sdlVulkanExtensions) {
requiredExtensions.insert(sdlVulkanExtension);
}
}
}
}
# endif
std::unordered_set<std::string> missingRequiredExtensions = requiredExtensions;
for (uint32_t i = 0; i < extensionCount; i++) {
const std::string extensionName(availableExtensions[i].extensionName);
missingRequiredExtensions.erase(extensionName);
@ -4024,7 +4072,7 @@ namespace RT64 {
}
std::vector<const char *> enabledExtensions;
for (const std::string &extension : RequiredInstanceExtensions) {
for (const std::string &extension : requiredExtensions) {
enabledExtensions.push_back(extension.c_str());
}
@ -4087,8 +4135,15 @@ namespace RT64 {
// Global creation function.
#if RT64_SDL_WINDOW_VULKAN
std::unique_ptr<RenderInterface> CreateVulkanInterface(RenderWindow sdlWindow) {
std::unique_ptr<VulkanInterface> createdInterface = std::make_unique<VulkanInterface>(sdlWindow);
return createdInterface->isValid() ? std::move(createdInterface) : nullptr;
}
#else
std::unique_ptr<RenderInterface> CreateVulkanInterface() {
std::unique_ptr<VulkanInterface> createdInterface = std::make_unique<VulkanInterface>();
return createdInterface->isValid() ? std::move(createdInterface) : nullptr;
}
#endif
};

View File

@ -213,6 +213,7 @@ namespace RT64 {
VkPresentModeKHR requiredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
VkCompositeAlphaFlagBitsKHR pickedAlphaFlag = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
std::vector<VulkanTexture> textures;
uint64_t currentPresentId = 0;
bool immediatePresentModeSupported = false;
VulkanSwapChain(VulkanCommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format);
@ -402,7 +403,11 @@ namespace RT64 {
VkApplicationInfo appInfo = {};
RenderInterfaceCapabilities capabilities;
# if RT64_SDL_WINDOW_VULKAN
VulkanInterface(RenderWindow sdlWindow);
#else
VulkanInterface();
# endif
~VulkanInterface() override;
std::unique_ptr<RenderDevice> createDevice() override;
const RenderInterfaceCapabilities &getCapabilities() const override;