Merge pull request 'iOS examples' (#101) from iOS_examples into master

Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/101
This commit is contained in:
Georg Hagen
2024-08-04 14:24:24 +02:00
16 changed files with 251 additions and 48 deletions

View File

@@ -43,3 +43,18 @@ jobs:
run: ctest -C ${{env.BUILD_TYPE}}
#TODO archive executables
build_iOS:
name: Build iOS
runs-on: mac_arm
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Configure CMake
run: mkdir cmake-build && mkdir cmake-build/iOS && cd cmake-build/iOS && cmake ../.. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../../cmake/toolchain/ios.toolchain.cmake -DPLATFORM=OS64 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build & Archive
run: xcodebuild -project ${{github.workspace}}/cmake-build/iOS/openVulkanoCpp.xcodeproj -scheme openVulkanoCpp -configuration ${{env.BUILD_TYPE}} -archivePath ${{github.workspace}}/cmake-build/iOS/app.xcarchive -sdk iphoneos archive

View File

@@ -22,7 +22,7 @@ add_subdirectory(rapidyaml)
add_subdirectory(libarchive)
add_subdirectory(boost)
add_subdirectory(units)
if (NOT IOS)
add_subdirectory(libjpeg-turbo)
if (NOT IOS)
add_subdirectory(curl)
endif()

View File

@@ -31,6 +31,11 @@ endif ()
function(LinkLibJpegTurbo TARGET)
if (IOS)
target_link_libraries(${TARGET} PRIVATE "/opt/libjpeg-turbo-ios/lib/libturbojpeg.a")
target_include_directories(${TARGET} PRIVATE "/opt/libjpeg-turbo-ios/include")
return()
endif ()
if (libjpeg-turbo_BUILT)
FindCmakeConfigDirs("${CMAKE_BINARY_DIR}/deps_ljt/INSTALL/" CMAKE_PREFIX_PATH)
endif()

View File

@@ -41,19 +41,25 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/TryCompileShaders.cmake.in ${CM
execute_process(COMMAND ${BASH_EXECUTABLE} CompileShaders.sh "${SHADER_OUTPUT_DEST}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Scripts)
file(GLOB GENERATED_SHADER_SOURCES "${SHADER_OUTPUT_DEST}/*")
if(APPLE)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "openVulkanoCpp/*.mm" "openVulkanoCpp/*.m" "openVulkanoCpp/*.c" "openVulkanoCpp/*.cpp" "examples/*.hpp" "examples/*.cpp")
add_executable(openVulkanoCpp examples/main.cpp ${resources} ${GENERATED_SHADER_SOURCES})
else()
set(MAIN_FILE examples/main.cpp)
if (IOS)
set(MAIN_FILE examples/Host/iOS/main.mm)
endif ()
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "openVulkanoCpp/*.h" "openVulkanoCpp/*.c" "openVulkanoCpp/*.hpp" "openVulkanoCpp/*.cpp" "examples/*.hpp" "examples/*.cpp")
if(APPLE)
file(GLOB_RECURSE sources_obj CONFIGURE_DEPENDS "openVulkanoCpp/*.mm" "openVulkanoCpp/*.m" "examples/*.m" "examples/*.mm")
list(APPEND sources ${sources_obj})
endif()
file(GLOB SHADER_SRC_FILES ${ROOT_FOLDER}/openVulkanoCpp/Shader/*)
list(FILTER SHADER_SRC_FILES EXCLUDE REGEX ".*\\.(hpp|cpp)$")
add_executable(openVulkanoCpp examples/main.cpp ${SHADER_SRC_FILES} ${GENERATED_SHADER_SOURCES})
if (MSVC)
add_executable(openVulkanoCpp ${MAIN_FILE} ${SHADER_SRC_FILES} ${GENERATED_SHADER_SOURCES})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
source_group("Shaders" FILES ${SHADER_SRC_FILES})
endif()
endif()
FilterPlatformPaths(sources)
SetWarningSettings(openVulkanoCpp)
@@ -69,7 +75,13 @@ if(IOS)
set(MACOSX_BUNDLE_GUI_IDENTIFIER ${APP_BUNDLE_IDENTIFIER})
set(MACOSX_BUNDLE_BUNDLE_NAME ${APP_BUNDLE_IDENTIFIER})
set(CMAKE_OSX_DEPLOYMENT_TARGET "14.1") # The used ARKit features are only available starting with iOS 14
set(CMAKE_OSX_DEPLOYMENT_TARGET "16") # The used ARKit features are only available starting with iOS 16
set(CMAKE_XCODE_EMBED_FRAMEWORKS ON)
set_target_properties(openVulkanoCpp PROPERTIES
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "466MGSD624"
)
endif()
if(APPLE)
LinkAppleFrameworks(openVulkanoCpp)
@@ -107,7 +119,9 @@ endif()
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/deps/INSTALL)
target_link_libraries(openVulkanoCpp PRIVATE magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense Boost::regex units)
if (NOT IOS)
LinkCurl(openVulkanoCpp)
endif()
add_compile_definitions(LIBARCHIVE_STATIC)
add_compile_definitions(NOMINMAX)

View File

@@ -4,8 +4,12 @@ function(LinkAppleFrameworks TARGET)
PUBLIC "-framework Foundation"
PUBLIC "-framework CoreImage"
PUBLIC "-framework CoreVideo"
PUBLIC "-framework CoreGraphics"
PUBLIC "-framework Metal"
PUBLIC "-framework MetalPerformanceShaders"
PUBLIC "-framework MetalKit"
PUBLIC "-framework IOSurface"
PUBLIC "-framework QuartzCore"
PUBLIC "-lstdc++"
PUBLIC c++
PUBLIC c
@@ -31,9 +35,9 @@ function(LinkAppleFrameworks TARGET)
target_link_libraries(${TARGET} PUBLIC ${MOBILECORESERVICES})
else()
target_link_libraries(${TARGET} PUBLIC ${APPKIT})
target_link_libraries(${TARGET} PUBLIC ${IOSURFACE})
target_link_libraries(${TARGET} PUBLIC ${QUARTZ})
endif()
target_link_libraries(${TARGET} PUBLIC ${IOSURFACE})
target_link_libraries(${TARGET} PUBLIC ${FOUNDATION})
target_link_libraries(${TARGET} PUBLIC ${CFNETWORK})
target_link_libraries(${TARGET} PUBLIC ${SYSTEMCONFIGURATION})

View File

@@ -1,5 +1,4 @@
function(FilterPlatformPaths sourcesVar)
if (IOS)
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*GLFW.*")
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*[\\/]Host[\\/]MacOS[\\/].*")

View File

@@ -0,0 +1,23 @@
/*
* 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 "ExampleApps/CubesExampleApp.hpp"
#include "ExampleApps/MovingCubeApp.hpp"
#include "ExampleApps/TexturedCubeExampleApp.hpp"
#include "ExampleApps/BillboardExampleApp.hpp"
#include <vector>
namespace OpenVulkano
{
const std::vector<std::pair<const char*, IGraphicsApp*(*)()>> EXAMPLE_APPS = {
{ "Cubes Example App", &CubesExampleApp::Create },
{ "Moving Cube Example App", &MovingCubeApp::Create },
{ "Textured Cube Example App", &TexturedCubeExampleApp::Create },
{ "Billboard Example App", &BillboardExampleApp::Create }
};
}

View File

@@ -52,7 +52,7 @@ namespace OpenVulkano
m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboardFromSinglePoint");
m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::GEOMETRY, "Shader/billboardFromSinglePoint");
m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basicTexture");
m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic");
m_quadBillboardShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription());
m_quadBillboardShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
m_quadBillboardShader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING);

View File

@@ -0,0 +1,19 @@
/*
* 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
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "Host/iOS/OpenVulkanoViewController.h"
@interface MainMenuViewController : UIViewController
@end
@interface ExampleViewController : OpenVulkanoViewController
@property(nonatomic, strong)OpenVulkanoView* renderView;
@property size_t exampleId;
@end

View File

@@ -0,0 +1,75 @@
/*
* 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 "ExampleViewController.h"
#include "../../ExampleAppList.hpp"
@implementation MainMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
CGFloat buttonHeight = 50;
CGFloat buttonSpacing = 10;
CGFloat topMargin = 50;
int i = 0;
for (const auto& app : OpenVulkano::EXAMPLE_APPS)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(20,
topMargin + i * (buttonHeight + buttonSpacing),
self.view.bounds.size.width - 40,
buttonHeight);
[button setTitle:[NSString stringWithUTF8String:app.first] forState:UIControlStateNormal];
button.tag = i;
[button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
i++;
}
self.view.frame = [UIScreen mainScreen].bounds;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
- (void)buttonPressed:(UIButton *)sender {
ExampleViewController* example = [[ExampleViewController alloc] init];
example.exampleId = sender.tag;
example.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:example animated:true completion:nil];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.view.frame = self.view.superview.bounds;
}
@end
@implementation ExampleViewController
- (void)viewDidLoad {
self.renderView = [[OpenVulkanoView alloc] initWithFrame:self.view.frame];
self.openVulkanoView = self.renderView;
[self.view addSubview:self.renderView];
[super viewDidLoad];
self.view.frame = [UIScreen mainScreen].bounds;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.view.frame = self.view.superview.bounds;
self.renderView.frame = self.view.frame;
}
- (BOOL)prefersStatusBarHidden { return true; }
- (void *)makeGraphicsApp {
return OpenVulkano::EXAMPLE_APPS[self.exampleId].second();
}
@end

57
examples/Host/iOS/main.mm Normal file
View File

@@ -0,0 +1,57 @@
/*
* 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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "ExampleViewController.h"
#import "Host/iOS/OpenVulkanoAppDelegate.h"
#include "Base/Logger.hpp"
@interface SceneDelegate : UIResponder<UIWindowSceneDelegate>
@end
@implementation SceneDelegate
@synthesize window = _window;
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
if ([scene isKindOfClass:[UIWindowScene class]]) {
UIWindowScene* wScene = (UIWindowScene*)scene;
self.window = [[UIWindow alloc] initWithWindowScene:wScene];
MainMenuViewController* rootViewController = [[MainMenuViewController alloc] init];
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
}
}
@end
@interface AppDelegate : OpenVulkanoAppDelegate
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
UISceneConfiguration *configuration = [[UISceneConfiguration alloc] initWithName:nil sessionRole:UIWindowSceneSessionRoleApplication];
configuration.delegateClass = SceneDelegate.class;
return configuration;
}
@end
int main(int argCount, char** args)
{
using namespace OpenVulkano;
Logger::SetupLogger();
@autoreleasepool
{
return UIApplicationMain(argCount, args, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@@ -5,10 +5,7 @@
*/
#include "Host/GraphicsAppManager.hpp"
#include "ExampleApps/CubesExampleApp.hpp"
#include "ExampleApps/MovingCubeApp.hpp"
#include "ExampleApps/TexturedCubeExampleApp.hpp"
#include "ExampleApps/BillboardExampleApp.hpp"
#include "ExampleAppList.hpp"
#include <ftxui/component/captured_mouse.hpp>
#include <ftxui/component/component.hpp>
@@ -22,12 +19,11 @@ using namespace OpenVulkano;
int main(int argc, char** argv)
{
std::vector<std::string> examples = {
"Cubes Example App",
"Moving Cube Example App",
"Textured Cube Example App",
"Billboard Example App"
};
std::vector<std::string> examples;
for (const auto& e : EXAMPLE_APPS)
{
examples.emplace_back(e.first);
}
int selectedExample = 0;
ftxui::MenuOption option;
@@ -37,15 +33,9 @@ int main(int argc, char** argv)
screen.Loop(menu);
std::unique_ptr<IGraphicsApp> app;
switch (selectedExample)
{
case 0: app = CubesExampleApp::CreateUnique(); break;
case 1: app = MovingCubeApp::CreateUnique(); break;
case 2: app = TexturedCubeExampleApp::CreateUnique(); break;
case 3: app = BillboardExampleApp::CreateUnique(); break;
default: throw std::runtime_error("Invalid menu selection!"); break;
}
if (selectedExample >= examples.size()) throw std::runtime_error("Invalid menu selection!");
std::unique_ptr<IGraphicsApp> app( EXAMPLE_APPS[selectedExample].second() );
GraphicsAppManager manager(app.get());
manager.Run();

View File

@@ -52,7 +52,7 @@ namespace OpenVulkano::AR
public:
ArSessionCapabilities() = default;
ArSessionCapabilities(const ArType type, const ArSessionType sessionType, const bool uncompressed, const bool depthSupported, const bool supportsExposureLocking, const bool suppoertWhitebalanceLocking, const bool hasFlash)
ArSessionCapabilities(const ArType type, const ArSessionType sessionType, const bool uncompressed, const bool depthSupported, const bool supportsExposureLocking, const bool supportsWhitebalanceLocking, const bool hasFlash)
: type(type), sessionType(sessionType), uncompressed(uncompressed), depthSupported(depthSupported), supportsExposureLocking(supportsExposureLocking), supportsWhitebalanceLocking(supportsWhitebalanceLocking), hasFlashlight(hasFlash)
{}

View File

@@ -22,9 +22,10 @@ namespace OpenVulkano
{
auto [fileName, fileType] = Utils::SplitAtLastOccurrence(resourceName, '.');
NSString* filePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithUTF8String:fileName.c_str()] ofType:[NSString stringWithUTF8String:fileType.c_str()]];
if (filePath)
return Utils::ReadFile(std::string([filePath UTF8String]));
}
Logger::FILESYS->warn("Failed to find resource: '{}' in bundle", resourceName);
return {0};
return {};
}
}

View File

@@ -8,7 +8,7 @@
namespace OpenVulkano::Scene
{
Texture Texture::PLACEHOLDER = Texture(SamplerConfig::DEFAULT, true);
Texture Texture::PLACEHOLDER = Texture(&SamplerConfig::NEAREST, true);
void Texture::MakePlaceholder(uint32_t width, uint32_t height, Math::Vector4uc color1, Math::Vector4uc color2)
{
@@ -25,5 +25,6 @@ namespace OpenVulkano::Scene
resolution = {width, height, 1};
size = sizeof(Math::Vector4uc) * width * height;
format = DataFormat::B8G8R8A8_UNORM;
m_samplerConfig = &SamplerConfig::NEAREST;
}
}

View File

@@ -34,10 +34,10 @@ namespace OpenVulkano::Scene
Math::Vector3ui resolution = {0,0,0};
DataFormat format = DataFormat::B8G8R8A8_UNORM;
UpdateFrequency updateFrequency = UpdateFrequency::Never;
const SamplerConfig& m_samplerConfig;
const SamplerConfig* m_samplerConfig;
bool updated = true;
Texture(const SamplerConfig& samplerConfig = SamplerConfig::DEFAULT, bool placeholder = false)
Texture(const SamplerConfig* samplerConfig = &SamplerConfig::DEFAULT, bool placeholder = false)
: m_samplerConfig(samplerConfig)
{ if (placeholder) MakePlaceholder(); }