mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-17 09:42:04 +00:00
- added initial support of Vulkan renderer to Cocoa backend
This commit is contained in:
parent
c30b1a1f4a
commit
965acde9c0
3 changed files with 214 additions and 34 deletions
|
@ -65,6 +65,8 @@ public:
|
||||||
static void SetWindowVisible(bool visible);
|
static void SetWindowVisible(bool visible);
|
||||||
static void SetWindowTitle(const char* title);
|
static void SetWindowTitle(const char* title);
|
||||||
|
|
||||||
|
void SetWindow(CocoaWindow* window) { m_window = window; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SystemBaseFrameBuffer() {}
|
SystemBaseFrameBuffer() {}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gl_load/gl_load.h"
|
#include "gl_load/gl_load.h"
|
||||||
|
|
||||||
|
#define VK_USE_PLATFORM_MACOS_MVK
|
||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
|
|
||||||
#include "i_common.h"
|
#include "i_common.h"
|
||||||
|
@ -54,6 +56,8 @@
|
||||||
#include "gl/system/gl_framebuffer.h"
|
#include "gl/system/gl_framebuffer.h"
|
||||||
#include "gl/textures/gl_samplers.h"
|
#include "gl/textures/gl_samplers.h"
|
||||||
|
|
||||||
|
#include "vulkan/system/vk_framebuffer.h"
|
||||||
|
|
||||||
|
|
||||||
@implementation NSWindow(ExitAppOnClose)
|
@implementation NSWindow(ExitAppOnClose)
|
||||||
|
|
||||||
|
@ -200,19 +204,51 @@ namespace
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class CocoaVideo : public IVideo
|
@interface VulkanCocoaView : NSView
|
||||||
{
|
{
|
||||||
public:
|
NSCursor* m_cursor;
|
||||||
virtual DFrameBuffer* CreateFrameBuffer() override
|
}
|
||||||
{
|
|
||||||
auto fb = new OpenGLRenderer::OpenGLFrameBuffer(nullptr, fullscreen);
|
|
||||||
|
|
||||||
fb->SetMode(fullscreen, vid_hidpi);
|
- (void)setCursor:(NSCursor*)cursor;
|
||||||
fb->SetSize(fb->GetClientWidth(), fb->GetClientHeight());
|
|
||||||
|
|
||||||
return fb;
|
@end
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@implementation VulkanCocoaView
|
||||||
|
|
||||||
|
- (void)resetCursorRects
|
||||||
|
{
|
||||||
|
[super resetCursorRects];
|
||||||
|
|
||||||
|
NSCursor* const cursor = nil == m_cursor
|
||||||
|
? [NSCursor arrowCursor]
|
||||||
|
: m_cursor;
|
||||||
|
|
||||||
|
[self addCursorRect:[self bounds]
|
||||||
|
cursor:cursor];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setCursor:(NSCursor*)cursor
|
||||||
|
{
|
||||||
|
m_cursor = cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) wantsUpdateLayer
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
+(Class) layerClass
|
||||||
|
{
|
||||||
|
return NSClassFromString(@"CAMetalLayer");
|
||||||
|
}
|
||||||
|
|
||||||
|
-(CALayer*) makeBackingLayer
|
||||||
|
{
|
||||||
|
return [self.class.layerClass layer];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -273,12 +309,122 @@ NSOpenGLPixelFormat* CreatePixelFormat()
|
||||||
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetupOpenGLView(CocoaWindow* window)
|
||||||
|
{
|
||||||
|
NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat();
|
||||||
|
|
||||||
|
if (nil == pixelFormat)
|
||||||
|
{
|
||||||
|
I_FatalError("Cannot create OpenGL pixel format, graphics hardware is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create OpenGL context and view
|
||||||
|
|
||||||
|
const NSRect contentRect = [window contentRectForFrameRect:[window frame]];
|
||||||
|
OpenGLCocoaView* glView = [[OpenGLCocoaView alloc] initWithFrame:contentRect
|
||||||
|
pixelFormat:pixelFormat];
|
||||||
|
[[glView openGLContext] makeCurrentContext];
|
||||||
|
|
||||||
|
[window setContentView:glView];
|
||||||
|
|
||||||
|
// To be able to use OpenGL functions in SetMode()
|
||||||
|
ogl_LoadFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class CocoaVideo : public IVideo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CocoaVideo()
|
||||||
|
{
|
||||||
|
ms_isVulkanSupported = true; // todo
|
||||||
|
}
|
||||||
|
|
||||||
|
~CocoaVideo()
|
||||||
|
{
|
||||||
|
delete m_vulkanDevice;
|
||||||
|
|
||||||
|
[ms_window dealloc];
|
||||||
|
ms_window = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual DFrameBuffer* CreateFrameBuffer() override
|
||||||
|
{
|
||||||
|
assert(ms_window == nil);
|
||||||
|
ms_window = CreateWindow(STYLE_MASK_WINDOWED);
|
||||||
|
|
||||||
|
SystemBaseFrameBuffer *fb = nullptr;
|
||||||
|
|
||||||
|
if (ms_isVulkanSupported)
|
||||||
|
{
|
||||||
|
const NSRect contentRect = [ms_window contentRectForFrameRect:[ms_window frame]];
|
||||||
|
|
||||||
|
NSView* vulkanView = [[VulkanCocoaView alloc] initWithFrame:contentRect];
|
||||||
|
[vulkanView setWantsLayer:YES];
|
||||||
|
|
||||||
|
[ms_window setContentView:vulkanView];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetupOpenGLView(ms_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_vulkanDevice = new VulkanDevice();
|
||||||
|
fb = new VulkanFrameBuffer(nullptr, fullscreen, m_vulkanDevice);
|
||||||
|
}
|
||||||
|
catch (std::exception const&)
|
||||||
|
{
|
||||||
|
ms_isVulkanSupported = false;
|
||||||
|
|
||||||
|
SetupOpenGLView(ms_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fb == nullptr)
|
||||||
|
{
|
||||||
|
fb = new OpenGLRenderer::OpenGLFrameBuffer(0, fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
fb->SetWindow(ms_window);
|
||||||
|
fb->SetMode(fullscreen, vid_hidpi);
|
||||||
|
fb->SetSize(fb->GetClientWidth(), fb->GetClientHeight());
|
||||||
|
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CocoaWindow* GetWindow()
|
||||||
|
{
|
||||||
|
return ms_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsVulkanSupported()
|
||||||
|
{
|
||||||
|
return ms_isVulkanSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VulkanDevice *m_vulkanDevice = nullptr;
|
||||||
|
|
||||||
|
static CocoaWindow* ms_window;
|
||||||
|
|
||||||
|
static bool ms_isVulkanSupported;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CocoaWindow* CocoaVideo::ms_window;
|
||||||
|
|
||||||
|
bool CocoaVideo::ms_isVulkanSupported;
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
static SystemBaseFrameBuffer* frameBuffer;
|
static SystemBaseFrameBuffer* frameBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
@ -286,7 +432,7 @@ SystemBaseFrameBuffer::SystemBaseFrameBuffer(void*, const bool fullscreen)
|
||||||
: DFrameBuffer(vid_defwidth, vid_defheight)
|
: DFrameBuffer(vid_defwidth, vid_defheight)
|
||||||
, m_fullscreen(false)
|
, m_fullscreen(false)
|
||||||
, m_hiDPI(false)
|
, m_hiDPI(false)
|
||||||
, m_window(CreateWindow(STYLE_MASK_WINDOWED))
|
, m_window(nullptr)
|
||||||
{
|
{
|
||||||
SetFlash(0, 0);
|
SetFlash(0, 0);
|
||||||
|
|
||||||
|
@ -308,8 +454,6 @@ SystemBaseFrameBuffer::~SystemBaseFrameBuffer()
|
||||||
[nc removeObserver:m_window
|
[nc removeObserver:m_window
|
||||||
name:NSWindowDidEndLiveResizeNotification
|
name:NSWindowDidEndLiveResizeNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
[m_window dealloc];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemBaseFrameBuffer::IsFullscreen()
|
bool SystemBaseFrameBuffer::IsFullscreen()
|
||||||
|
@ -491,24 +635,6 @@ void SystemBaseFrameBuffer::SetWindowTitle(const char* title)
|
||||||
SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen)
|
SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen)
|
||||||
: SystemBaseFrameBuffer(hMonitor, fullscreen)
|
: SystemBaseFrameBuffer(hMonitor, fullscreen)
|
||||||
{
|
{
|
||||||
NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat();
|
|
||||||
|
|
||||||
if (nil == pixelFormat)
|
|
||||||
{
|
|
||||||
I_FatalError("Cannot create OpenGL pixel format, graphics hardware is not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create OpenGL context and view
|
|
||||||
|
|
||||||
const NSRect contentRect = [m_window contentRectForFrameRect:[m_window frame]];
|
|
||||||
OpenGLCocoaView* glView = [[OpenGLCocoaView alloc] initWithFrame:contentRect
|
|
||||||
pixelFormat:pixelFormat];
|
|
||||||
[[glView openGLContext] makeCurrentContext];
|
|
||||||
|
|
||||||
[m_window setContentView:glView];
|
|
||||||
|
|
||||||
// To be able to use OpenGL functions in SetMode()
|
|
||||||
ogl_LoadFunctions();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -692,15 +818,62 @@ void I_SetWindowTitle(const char* title)
|
||||||
|
|
||||||
void I_GetVulkanDrawableSize(int *width, int *height)
|
void I_GetVulkanDrawableSize(int *width, int *height)
|
||||||
{
|
{
|
||||||
assert(!"Not implemented");
|
NSWindow* const window = CocoaVideo::GetWindow();
|
||||||
|
assert(window != nil);
|
||||||
|
|
||||||
|
const NSSize size = I_GetContentViewSize(window);
|
||||||
|
|
||||||
|
if (width != nullptr)
|
||||||
|
{
|
||||||
|
*width = int(size.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height != nullptr)
|
||||||
|
{
|
||||||
|
*height = int(size.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names)
|
bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names)
|
||||||
{
|
{
|
||||||
assert(!"Not implemented");
|
static const char* extensions[] =
|
||||||
|
{
|
||||||
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||||
|
VK_MVK_MACOS_SURFACE_EXTENSION_NAME
|
||||||
|
};
|
||||||
|
static const unsigned int extensionCount = static_cast<unsigned int>(sizeof extensions / sizeof extensions[0]);
|
||||||
|
|
||||||
|
if (count == nullptr && names == nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (names == nullptr)
|
||||||
|
{
|
||||||
|
*count = extensionCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const bool result = *count >= extensionCount;
|
||||||
|
*count = std::min(*count, extensionCount);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < *count; ++i)
|
||||||
|
{
|
||||||
|
names[i] = extensions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface)
|
bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface)
|
||||||
{
|
{
|
||||||
assert(!"Not implemented");
|
VkMacOSSurfaceCreateInfoMVK windowCreateInfo;
|
||||||
|
windowCreateInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||||
|
windowCreateInfo.pNext = nullptr;
|
||||||
|
windowCreateInfo.flags = 0;
|
||||||
|
windowCreateInfo.pView = [[CocoaVideo::GetWindow() contentView] layer];
|
||||||
|
|
||||||
|
const VkResult result = vkCreateMacOSSurfaceMVK(instance, &windowCreateInfo, nullptr, surface);
|
||||||
|
return result == VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
5
src/rendering/vulkan/thirdparty/volk/volk.c
vendored
5
src/rendering/vulkan/thirdparty/volk/volk.c
vendored
|
@ -2,6 +2,11 @@
|
||||||
#define VK_USE_PLATFORM_WIN32_KHR
|
#define VK_USE_PLATFORM_WIN32_KHR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define VK_USE_PLATFORM_MACOS_MVK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* This file is part of volk library; see volk.h for version/license details */
|
/* This file is part of volk library; see volk.h for version/license details */
|
||||||
#include "volk.h"
|
#include "volk.h"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue