Start refactoring of OpenVulkanoView implementation (#1)

This commit is contained in:
Georg Hagen
2024-06-05 14:17:29 +02:00
parent 58e63b6610
commit cd414c352e
6 changed files with 292 additions and 140 deletions

View File

@@ -0,0 +1,88 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "Base/UI/IVulkanWindow.hpp"
namespace OpenVulkano
{
class MetalViewWindow final : public IVulkanWindow
{
WindowConfiguration windowConf;
IWindowHandler* handler = nullptr;
void* caMetalLayer = nullptr;
bool tickHandler = true;
public:
void Init(RenderAPI::RenderApi renderApi) override {}
void Init(void* metalLayer, Math::Vector2ui size)
{
caMetalLayer = metalLayer;
windowConf.size = size;
}
void SetMetalLayer(void* metalLayer) { caMetalLayer = metalLayer; }
bool HasTitle() override { return false; }
const std::string& GetTitle() override { return windowConf.title; }
void SetTitle(const std::string& title) override {}
WindowMode GetWindowMode() override { return FULLSCREEN; }
void SetWindowMode(WindowMode) override {}
const WindowConfiguration& GetWindowConfiguration() override { return windowConf; }
void SetSize(uint32_t width, uint32_t height) override { windowConf.size = { width, height }; }
void SetSizeLimits(int minWidth, int minHeight, int maxWidth, int maxHeight) override {}
Math::Vector2i GetPosition() override { return { 0, 0 }; }
void SetPosition(int posX, int posY) override {}
void Show() override {}
void Hide() override {}
void Show(bool show) override {}
IWindowHandler* GetWindowHandler() override { return handler; }
void SetWindowHandler(IWindowHandler* handler) override { this->handler = handler; }
uint32_t GetWindowId() const override { return 0; }
IOpenGlWindow* GetOpenGlWindow() override { return nullptr; }
IVulkanWindow* GetVulkanWindow() override { return this; }
bool WindowHasBeenDestroyed() const override { return false; }
void SetWindowHasBeenDestroyed() override
{
//TODO
}
void* GetNativeWindowHandle() override { return caMetalLayer; }
vk::SurfaceKHR CreateSurface(const vk::Instance& instance, const vk::AllocationCallbacks* pAllocator = nullptr) override;
std::vector<std::string> GetRequiredInstanceExtensions() override;
Math::Vector2ui GetSize() override { return windowConf.size; }
void Close() override {}
void OnResize(uint32_t width, uint32_t height);
void TickHandler();
};
}

View File

@@ -0,0 +1,53 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// Makre usre the Molten include is first!
#include <MoltenVK/mvk_vulkan.h>
#include "MetalViewWindow.h"
#include "Base/Logger.hpp"
#include "Host/GraphicsAppManager.hpp"
#import <MetalKit/MTKView.h>
namespace OpenVulkano
{
vk::SurfaceKHR MetalViewWindow::CreateSurface(const vk::Instance& instance, const vk::AllocationCallbacks* pAllocator)
{
VkMetalSurfaceCreateInfoEXT surfaceCreateInfo;
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
surfaceCreateInfo.pNext = NULL;
surfaceCreateInfo.flags = 0;
surfaceCreateInfo.pLayer = (CAMetalLayer*) caMetalLayer;
VkSurfaceKHR surface;
auto err = vkCreateMetalSurfaceEXT(static_cast<VkInstance>(instance), &surfaceCreateInfo, NULL, &surface);
return {surface};
}
std::vector<std::string> MetalViewWindow::GetRequiredInstanceExtensions()
{
return {}; //TODO
}
void MetalViewWindow::OnResize(uint32_t newWidth, uint32_t newHeight)
{
Logger::WINDOW->debug("Window (id: {0}) resized (width: {1}, height: {2})", GetWindowId(), newWidth, newHeight);
if (handler)
handler->OnWindowResize(this, newWidth, newHeight);
}
void MetalViewWindow::TickHandler()
{
if (tickHandler)
{
if (auto graphApp = dynamic_cast<GraphicsAppManager*>(handler))
{
graphApp->LoopTick();
}
}
}
}

View File

@@ -14,4 +14,11 @@
//@interface OpenVulkanoView : UIView //@interface OpenVulkanoView : UIView
@interface OpenVulkanoView : MTKView @interface OpenVulkanoView : MTKView
-(void*)GetWindow;
-(void)WillAppear;
-(void)DidAppear;
-(void)WillDisappear;
-(void)DidDisappear;
-(void)DidUnload;
@end @end

View File

@@ -8,21 +8,57 @@
#include "Input/Touch/InputDeviceTouch.hpp" #include "Input/Touch/InputDeviceTouch.hpp"
#include "Input/InputManager.hpp" #include "Input/InputManager.hpp"
#include "MetalViewWindow.h"
#include <map> #include <map>
#import <MetalKit/MTKView.h>
using namespace OpenVulkano;
#pragma mark MetalViewDelegate
@interface MetalViewDelegate : NSObject<MTKViewDelegate>
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size;
- (void) drawInMTKView:(MTKView *) view;
@end
@implementation MetalViewDelegate
{
MetalViewWindow* window;
}
- (id)initWithWindow:(MetalViewWindow*)win
{
window = win;
return self;
}
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size
{
window->OnResize(size.width, size.height);
}
- (void) drawInMTKView:(MTKView *) view
{
@autoreleasepool {
window->TickHandler();
}
}
@end
#pragma mark - #pragma mark -
#pragma mark OpenVulkanoView #pragma mark OpenVulkanoView
using namespace OpenVulkano;
@interface OpenVulkanoView() @interface OpenVulkanoView()
{ {
CADisplayLink * m_displayLink; CADisplayLink* m_displayLink;
MetalViewDelegate* m_mtdelegate;
std::map<UITouch*, int32_t> m_touchToIdMap; std::map<UITouch*, int32_t> m_touchToIdMap;
Input::InputDeviceTouch m_touchDevice; Input::InputDeviceTouch m_touchDevice;
MetalViewWindow m_window;
} }
@end @end
#pragma mark OpenVulkanoView Implementation
@implementation OpenVulkanoView @implementation OpenVulkanoView
/** Returns a Metal-compatible layer. */ /** Returns a Metal-compatible layer. */
+(Class) layerClass { return [CAMetalLayer class]; } +(Class) layerClass { return [CAMetalLayer class]; }
@@ -45,8 +81,28 @@ using namespace OpenVulkano;
- (void)commonInit { - (void)commonInit {
[self setMultipleTouchEnabled:YES]; [self setMultipleTouchEnabled:YES];
self.contentScaleFactor = UIScreen.mainScreen.nativeScale / 1.5f;
auto size = self.bounds.size;
auto sizeX = size.width * self.contentScaleFactor;
auto sizeY = size.height * self.contentScaleFactor;
m_window.Init(self.layer, {sizeX, sizeY});
m_touchDevice.Init(); //TODO link window m_touchDevice.Init(); //TODO link window
Input::InputManager::GetInstance()->RegisterInputDevice(&m_touchDevice); Input::InputManager::GetInstance()->RegisterInputDevice(&m_touchDevice);
if ([self isKindOfClass:[MTKView class]]) {
MTKView* mtkView = (MTKView*)(self);
m_mtdelegate = [[MetalViewDelegate alloc] initWithWindow:&m_window];
[mtkView setDelegate:m_mtdelegate];
mtkView.preferredFramesPerSecond = 60;
} else {
m_displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderLoop)];
[m_displayLink setPreferredFramesPerSecond: 60];
[m_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode];
m_displayLink.paused = YES;
}
} }
- (void)dealloc { - (void)dealloc {
@@ -55,9 +111,23 @@ using namespace OpenVulkano;
} }
Input::InputManager::GetInstance()->UnregisterInputDevice(&m_touchDevice); Input::InputManager::GetInstance()->UnregisterInputDevice(&m_touchDevice);
m_touchDevice.Close(); m_touchDevice.Close();
[m_displayLink release];
[m_mtdelegate release];
[super dealloc]; [super dealloc];
} }
- (void)layoutSubviews {
[super layoutSubviews];
if (m_displayLink)
{ // Only use this update method if we use display link instead of metal delegate
auto size = self.bounds.size;
auto sizeX = size.width * self.contentScaleFactor;
auto sizeY = size.height * self.contentScaleFactor;
m_window.OnResize(sizeX, sizeY);
}
}
- (Math::Vector2f)getTouchPosition:(UITouch*)touch - (Math::Vector2f)getTouchPosition:(UITouch*)touch
{ {
CGPoint uitouchLocation = [touch locationInView:touch.view]; CGPoint uitouchLocation = [touch locationInView:touch.view];
@@ -121,5 +191,44 @@ using namespace OpenVulkano;
} }
} }
-(void*)GetWindow
{
return &m_window;
}
-(void) renderLoop
{
m_window.TickHandler();
}
-(void)WillAppear
{
if (m_displayLink) m_displayLink.paused = NO;
}
-(void)DidAppear
{
if (m_displayLink) m_displayLink.paused = NO;
}
-(void)WillDisappear
{
if (m_displayLink) m_displayLink.paused = YES;
}
-(void)DidDisappear
{
if (m_displayLink) m_displayLink.paused = YES;
}
-(void)DidUnload
{
if (m_displayLink)
{
[m_displayLink invalidate];
[m_displayLink release];
m_displayLink = nil;
}
}
@end @end

View File

@@ -4,12 +4,19 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#pragma once
#import "OpenVulkanoView.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#pragma mark - #pragma mark -
#pragma mark OpenVulkanoViewController #pragma mark OpenVulkanoViewController
@interface OpenVulkanoViewController : UIViewController @interface OpenVulkanoViewController : UIViewController
{
@public OpenVulkanoView* openVulkanoView;
@public BOOL fixOpenVulkanoViewOrientation;
}
-(void*) makeGraphicsApp; -(void*) makeGraphicsApp;
@end @end

View File

@@ -11,128 +11,32 @@
#include "Base/UI/IVulkanWindow.hpp" #include "Base/UI/IVulkanWindow.hpp"
#import <MetalKit/MTKView.h> #import <MetalKit/MTKView.h>
#import "OpenVulkanoView.h"
#pragma mark - #pragma mark -
#pragma mark OpenVulkanoViewController #pragma mark OpenVulkanoViewController
using namespace OpenVulkano; using namespace OpenVulkano;
class ViewWindow final : public IVulkanWindow
{
WindowConfiguration windowConf;
IWindowHandler* handler = nullptr;
void* caMetalLayer = nullptr;
public:
void Init(RenderAPI::RenderApi renderApi) override {}
void Init(void* metalLayer, Math::Vector2ui size)
{
caMetalLayer = metalLayer;
windowConf.size = size;
}
void SetMetalLayer(void* metalLayer) { caMetalLayer = metalLayer; }
bool HasTitle() override { return false; }
const std::string& GetTitle() override { return windowConf.title; }
void SetTitle(const std::string& title) override {}
WindowMode GetWindowMode() override { return FULLSCREEN; }
void SetWindowMode(WindowMode) override {}
const WindowConfiguration & GetWindowConfiguration() override { return windowConf; }
void SetSize(uint32_t width, uint32_t height) override { windowConf.size = { width, height }; }
void SetSizeLimits(int minWidth, int minHeight, int maxWidth, int maxHeight) override {}
Math::Vector2i GetPosition() override { return { 0,0 }; }
void SetPosition(int posX, int posY) override {}
void Show() override {}
void Hide() override {}
void Show(bool show) override {}
IWindowHandler * GetWindowHandler() override { return handler; }
void SetWindowHandler(IWindowHandler *handler) override { this->handler = handler; }
uint32_t GetWindowId() const override { return 0; }
IOpenGlWindow * GetOpenGlWindow() override { return nullptr; }
IVulkanWindow * GetVulkanWindow() override { return this; }
bool WindowHasBeenDestroyed() const override { return false; }
void SetWindowHasBeenDestroyed() override {}
void* GetNativeWindowHandle() override { return caMetalLayer; }
vk::SurfaceKHR CreateSurface(const vk::Instance &instance, const vk::AllocationCallbacks *pAllocator = nullptr) override
{
VkMetalSurfaceCreateInfoEXT surfaceCreateInfo;
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
surfaceCreateInfo.pNext = NULL;
surfaceCreateInfo.flags = 0;
surfaceCreateInfo.pLayer = (CAMetalLayer*)caMetalLayer;
VkSurfaceKHR surface;
auto err = vkCreateMetalSurfaceEXT(static_cast<VkInstance>(instance), &surfaceCreateInfo, NULL, &surface);
return { surface };
}
std::vector<std::string> GetRequiredInstanceExtensions() override
{
return {};
}
Math::Vector2ui GetSize() override { return windowConf.size;}
void Close() override {}
};
@interface MetalViewDelegate : NSObject<MTKViewDelegate>
- (id)initWithGAM:(GraphicsAppManager*)gam;
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size;
- (void) drawInMTKView:(MTKView *) view;
@end
@implementation MetalViewDelegate
{
GraphicsAppManager* manager;
IWindow* window;
}
- (id)initWithGAM:(GraphicsAppManager*)gam win:(IWindow*)win
{
manager = gam;
window = win;
return self;
}
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size
{
manager->OnWindowResize(window, size.width, size.height);
}
- (void) drawInMTKView:(MTKView *) view
{
@autoreleasepool {
manager->LoopTick();
}
}
@end
@implementation OpenVulkanoViewController { @implementation OpenVulkanoViewController {
CADisplayLink* _displayLink;
GraphicsAppManager* manager; GraphicsAppManager* manager;
ViewWindow window;
std::unique_ptr<IGraphicsApp> app; std::unique_ptr<IGraphicsApp> app;
MetalViewDelegate* mtdelegate;
} }
-(void*) makeGraphicsApp { -(void*) makeGraphicsApp {
return nullptr; return nullptr;
} }
-(id)init {
[super init];
openVulkanoView = nil;
fixOpenVulkanoViewOrientation = false;
return self;
}
-(void) dealloc { -(void) dealloc {
manager->ShutDown(); manager->ShutDown();
[_displayLink release];
[super dealloc]; [super dealloc];
} }
@@ -140,61 +44,45 @@ public:
-(void) viewDidLoad { -(void) viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale / 1.5f; if (openVulkanoView == nil && [self.view isKindOfClass:[OpenVulkanoView class]]) {
openVulkanoView = (OpenVulkanoView*)self.view;
auto size = self.view.bounds.size; }
auto sizeX = size.width * self.view.contentScaleFactor;
auto sizeY = size.height * self.view.contentScaleFactor;
window.Init(self.view.layer, {sizeX, sizeY});
//TODO check if type is correct //TODO check if type is correct
IGraphicsApp* appPtr = static_cast<IGraphicsApp*>(self.makeGraphicsApp); IGraphicsApp* appPtr = static_cast<IGraphicsApp*>(self.makeGraphicsApp);
if (!appPtr) throw std::runtime_error("Failed to create graphics app"); if (!appPtr) throw std::runtime_error("Failed to create graphics app");
app = std::unique_ptr<IGraphicsApp>(appPtr); app = std::unique_ptr<IGraphicsApp>(appPtr);
manager = new GraphicsAppManager(app.get(), &window); manager = new GraphicsAppManager(app.get(), (IVulkanWindow*)[openVulkanoView GetWindow]);
manager->StartUp(); manager->StartUp();
if ([self.view isKindOfClass:[MTKView class]]) {
MTKView* mtkView = (MTKView*)(self.view);
mtdelegate = [[MetalViewDelegate alloc] initWithGAM:manager win:&window];
[mtkView setDelegate:mtdelegate];
mtkView.preferredFramesPerSecond = 60;
} else {
_displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderLoop)];
[_displayLink setPreferredFramesPerSecond: 60];
[_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode];
}
} }
-(void) viewWillAppear:(BOOL)animated { -(void) viewWillAppear:(BOOL)animated {
if (openVulkanoView != nil) { [openVulkanoView willAppear]; }
[super viewWillAppear:animated]; [super viewWillAppear:animated];
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale / 1.5f; }
auto size = self.view.bounds.size; -(void) viewDidAppear:(BOOL)animated {
auto sizeX = size.width * self.view.contentScaleFactor; if (openVulkanoView != nil) { [openVulkanoView DidAppear]; }
auto sizeY = size.height * self.view.contentScaleFactor; [super viewDidAppear:animated];
manager->OnWindowResize(&window, sizeX, sizeY); }
-(void) viewWillDisappear:(BOOL)animated {
if (openVulkanoView != nil) { [openVulkanoView WillDisappear]; }
[super viewWillDisappear:animated];
} }
-(void) viewDidDisappear:(BOOL)animated { -(void) viewDidDisappear:(BOOL)animated {
[_displayLink release]; if (openVulkanoView != nil) { [openVulkanoView DidDisappear]; }
_displayLink = nil;
[super viewDidDisappear:animated]; [super viewDidDisappear:animated];
} }
-(void) viewDidUnload { -(void) viewDidUnload {
[_displayLink release]; if (openVulkanoView != nil) { [openVulkanoView DidUnload]; }
_displayLink = nil;
[super viewDidUnload]; [super viewDidUnload];
} }
-(void) renderLoop {
manager->LoopTick();
}
// Allow device rotation to resize the swapchain
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { -(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
manager->OnWindowResize(&window, size.width, size.height);
} }
- (BOOL)prefersHomeIndicatorAutoHidden { - (BOOL)prefersHomeIndicatorAutoHidden {