Files
OpenVulkano/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm

179 lines
4.9 KiB
Plaintext

/*
* 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/.
*/
#import "OpenVulkanoViewController.h"
#include <MoltenVK/mvk_vulkan.h>
#include "Host/GraphicsAppManager.hpp"
#include "ExampleApps/CubesExampleApp.hpp"
#include "Base/UI/IVulkanWindow.hpp"
#pragma mark -
#pragma mark OpenVulkanoViewController
using namespace openVulkanoCpp;
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 {}
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; }
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;
}
- (id)initWithGAM:(GraphicsAppManager*)gam
{
manager = gam;
return self;
}
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size
{}
- (void) drawInMTKView:(MTKView *) view
{
manager->LoopTick();
}
@end
@implementation OpenVulkanoViewController {
CADisplayLink* _displayLink;
GraphicsAppManager* manager;
ViewWindow window;
std::unique_ptr<IGraphicsApp> app;
MetalViewDelegate* mtdelegate;
}
-(void*) makeGraphicsApp {
return CubesExampleApp::Create();
}
-(void) dealloc {
manager->ShutDown();
[_displayLink release];
[super dealloc];
}
/** Since this is a single-view app, init Vulkan when the view is loaded. */
-(void) viewDidLoad {
[super viewDidLoad];
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
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
IGraphicsApp* appPtr = static_cast<IGraphicsApp*>(self.makeGraphicsApp);
if (!appPtr) throw std::runtime_error("Failed to create graphics app");
app = std::unique_ptr<IGraphicsApp>(appPtr);
manager = new GraphicsAppManager(app.get(), &window);
manager->StartUp();
OpenVulkanoView* mtkView = (OpenVulkanoView*)(self.view);
mtdelegate = [[MetalViewDelegate alloc] initWithGAM:manager];
[mtkView setDelegate:mtdelegate];
mtkView.preferredFramesPerSecond = 60;
}
-(void) renderLoop {
manager->LoopTick();
}
// Allow device rotation to resize the swapchain
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
manager->OnWindowResize(&window, size.width, size.height);
}
- (BOOL)prefersHomeIndicatorAutoHidden {
return true;
}
@end
#pragma mark -
#pragma mark OpenVulkanoView
@implementation OpenVulkanoView
/** Returns a Metal-compatible layer. */
+(Class) layerClass { return [CAMetalLayer class]; }
@end