Merge branch 'master' into project_setup_refactor

# Conflicts:
#	3rdParty/CMakeLists.txt
#	3rdParty/libarchive/CMakeLists.txt
#	CMakeLists.txt
This commit is contained in:
Georg Hagen
2024-08-04 18:05:50 +02:00
70 changed files with 1096 additions and 274 deletions

View File

@@ -12,23 +12,11 @@ env:
jobs:
build:
name: Build desktop
runs-on: ${{matrix.config.os}}
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Windows",
os: windows_x64
}
- {
name: "Linux",
os: ubuntu-latest
}
# - {
# name: "macOS",
# os: macos-latest
# }
os: [ windows_x64, ubuntu-latest, mac_arm ]
steps:
- name: Checkout
@@ -36,13 +24,13 @@ jobs:
with:
submodules: true
- name: Install Vulkan SDK
if: matrix.config.os == 'ubuntu-latest'
if: matrix.os == 'ubuntu-latest'
uses: humbletim/install-vulkan-sdk@v1.1.1
with:
version: 1.3.250.1
cache: true
- name: Install Dev Packages
if: matrix.config.os == 'ubuntu-latest'
if: matrix.os == 'ubuntu-latest'
run: >
sudo apt update && sudo apt install -y extra-cmake-modules libwayland-dev libxkbcommon-dev xorg-dev libarchive-dev libassimp-dev ninja-build glslang-tools glslang-dev unzip
&& sudo wget https://sourceforge.net/projects/bin2c/files/1.1/bin2c-1.1.zip && sudo unzip bin2c-1.1.zip && cd bin2c && sudo gcc -o bin2c bin2c.c && sudo mv bin2c /usr/bin
@@ -55,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 OpenVulkano_Examples -configuration ${{env.BUILD_TYPE}} -archivePath ${{github.workspace}}/cmake-build/iOS/app.xcarchive -sdk iphoneos archive

View File

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

View File

@@ -13,5 +13,8 @@ FetchContent_Declare(
)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
if(APPLE)
set(GLFW_VULKAN_STATIC ON CACHE BOOL "" FORCE)
endif()
FetchContent_MakeAvailable(glfw)
set(glfw_FOUND ON PARENT_SCOPE)

View File

@@ -28,12 +28,21 @@ function(LinkLibArchive TARGET)
find_package(zstd QUIET)
find_package(BZip2 QUIET)
find_package(LibLZMA QUIET)
find_package(LibXml2 QUIET)
find_package(EXPAT QUIET)
target_include_directories(${TARGET} PUBLIC ${LibArchive_INCLUDE_DIR})
target_link_libraries(${TARGET} PUBLIC ${LibArchive_LIBRARIES} ${ZLIB_LIBRARIES} ${zstd_LIBRARIES} ${LZ4_LIBRARIES})
if (BZIP2_LIBRARIES)
target_link_libraries(${TARGET} PUBLIC ${BZIP2_LIBRARIES})
endif()
if (LIBLZMA_LIBRARIES)
target_link_libraries(${TARGET} PUBLIC ${LIBLZMA_LIBRARIES})
endif()
if (LibXml2_FOUND)
target_link_libraries(${TARGET} PUBLIC ${LIBXML2_LIBRARIES})
endif()
if (EXPAT_FOUND)
target_link_libraries(${TARGET} PUBLIC ${EXPAT_LIBRARIES})
endif()
endfunction()

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

@@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.28 FATAL_ERROR)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(CMAKE_CXX_STANDARD 20)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
if(LINUX)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
@@ -45,3 +47,5 @@ endif()
if(ENABLE_EXAMPLE)
add_subdirectory(examples)
endif()
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT openVulkanoCpp)

View File

@@ -27,8 +27,8 @@ check_return_code() {
fi
}
rm -f *.spv
mkdir -p "$GENERATED_DATA_PATH"
rm -f "$GENERATED_DATA_PATH/*.spv"
touch "$GENERATED_DATA_PATH"/GeneratedShaderData.h
touch "$GENERATED_DATA_PATH"/GeneratedShaderData.c
@@ -48,13 +48,13 @@ for unique_name in ${unique_file_names[@]} ; do
same_files=$(find $SHADER_PATH/ -type f -name "${unique_name}.*")
for same_file in ${same_files[@]} ; do
filename_with_ext_no_path=$(basename -- "$same_file")
glslangValidator -V $same_file -o $filename_with_ext_no_path.spv
glslangValidator -V $same_file -o "$GENERATED_DATA_PATH/$filename_with_ext_no_path.spv"
check_return_code
done
bin2c -t -d "$GENERATED_DATA_PATH"/$unique_name.h -o "$GENERATED_DATA_PATH"/$unique_name.c *.spv
(cd "$GENERATED_DATA_PATH" && bin2c -t -d $unique_name.h -o $unique_name.c *.spv)
check_return_code
rm *.spv
rm "$GENERATED_DATA_PATH"/*.spv
echo -e "#include \"${unique_name}.h\"" >> "$GENERATED_DATA_PATH"/GeneratedShaderData.c
filename_no_ext_first_upper=$(echo $unique_name | awk '{print toupper(substr($0,1,1))substr($0,2)}')

View File

@@ -4,14 +4,20 @@ function(LinkAppleFrameworks TARGET)
PUBLIC "-framework Foundation"
PUBLIC "-framework CoreImage"
PUBLIC "-framework CoreVideo"
PUBLIC "-framework CoreGraphics"
PUBLIC "-framework Metal"
PUBLIC "-framework MetalPerformanceShaders"
PUBLIC "-framework ARKit"
PUBLIC "-framework MetalKit"
PUBLIC "-framework IOSurface"
PUBLIC "-framework QuartzCore"
PUBLIC "-lstdc++"
PUBLIC c++
PUBLIC c
)
if(IOS)
target_link_libraries(${TARGET} PUBLIC "-framework ARKit")
endif()
# Locate system libraries on iOS
find_library(UIKIT UIKit)
@@ -19,11 +25,20 @@ function(LinkAppleFrameworks TARGET)
find_library(MOBILECORESERVICES MobileCoreServices)
find_library(CFNETWORK CFNetwork)
find_library(SYSTEMCONFIGURATION SystemConfiguration)
find_library(APPKIT AppKit)
find_library(IOSURFACE IOSurface)
find_library(QUARTZ Quartz)
# link the frameworks located above
if(IOS)
target_link_libraries(${TARGET} PUBLIC ${UIKIT})
target_link_libraries(${TARGET} PUBLIC ${FOUNDATION})
target_link_libraries(${TARGET} PUBLIC ${MOBILECORESERVICES})
else()
target_link_libraries(${TARGET} PUBLIC ${APPKIT})
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})
endfunction()

View File

@@ -1,9 +1,13 @@
function(FilterPlatformPaths sourcesVar)
if (IOS)
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*GLFW.*")
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*[\\/]Host[\\/]MacOS[\\/].*")
else ()
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*[\\/]Host[\\/]iOS[\\/].*")
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*[\\/]AR[\\/]Provider[\\/]ArKit[\\/].*")
endif ()
if (NOT APPLE)
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*[\\/]Host[\\/]Apple[\\/].*")
endif ()
if (NOT LINUX)
list(FILTER ${sourcesVar} EXCLUDE REGEX ".*[\\/]Host[\\/]Linux[\\/].*")

View File

@@ -3,15 +3,42 @@ cmake_minimum_required(VERSION 3.28 FATAL_ERROR)
include(SetupVulkan)
include(Utils)
file(GLOB_RECURSE SUBDIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp")
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SUBDIRECTORIES})
add_executable(examples main.cpp ${SUBDIRECTORIES})
file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp")
if (IOS)
file(GLOB_RECURSE SRC_IOS "${CMAKE_CURRENT_SOURCE_DIR}/Host/iOS/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Host/iOS/*.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/Host/iOS/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Host/iOS/*.m" "${CMAKE_CURRENT_SOURCE_DIR}/Host/iOS/*.mm")
list(APPEND SOURCES ${SRC_IOS})
endif ()
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SOURCES})
target_include_directories(examples PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
set(MAIN_FILE main.cpp)
if (IOS)
set(MAIN_FILE Host/iOS/main.mm)
endif ()
add_executable(OpenVulkano_Examples ${MAIN_FILE} ${SOURCES})
set_property(TARGET OpenVulkano_Examples PROPERTY CXX_STANDARD 20)
target_include_directories(examples PRIVATE openVulkanoCpp)
target_link_libraries(examples PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,openVulkanoCpp>")
SetupVulkan(examples)
SetGlmDefines(examples)
SetWarningSettings(examples)
LinkCurl(openVulkanoCpp)
# Setup IOS
if(IOS)
set(APP_BUNDLE_IDENTIFIER "eu.georgh93.openVulkano")
set(MACOSX_BUNDLE_INFO_STRING ${APP_BUNDLE_IDENTIFIER})
set(MACOSX_BUNDLE_GUI_IDENTIFIER ${APP_BUNDLE_IDENTIFIER})
set(MACOSX_BUNDLE_BUNDLE_NAME ${APP_BUNDLE_IDENTIFIER})
set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET})
set(CMAKE_XCODE_EMBED_FRAMEWORKS ON)
set_target_properties(OpenVulkano_Examples PROPERTIES XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "466MGSD624")
endif()
if(APPLE)
LinkAppleFrameworks(OpenVulkano_Examples)
endif ()
target_include_directories(OpenVulkano_Examples PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(OpenVulkano_Examples PRIVATE openVulkanoCpp)
target_link_libraries(OpenVulkano_Examples PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,openVulkanoCpp>")
SetupVulkan(OpenVulkano_Examples)
SetGlmDefines(OpenVulkano_Examples)
SetWarningSettings(OpenVulkano_Examples)

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

@@ -7,6 +7,8 @@
#include "ArFrame.hpp"
#include "ArSession.hpp"
#include "ArRecorder.hpp"
#include <iostream>
#include <fstream>
namespace OpenVulkano::AR
{
@@ -26,6 +28,11 @@ namespace OpenVulkano::AR
void ArFrame::SaveToFile(const std::filesystem::path& path, bool downsample)
{
m_session->GetRecorder().SaveToFile(shared_from_this(), path, downsample);
std::string metaContent = GetFrameMetadata().ToXML();
std::string metaPath = path.string() + std::string(".meta");
std::ofstream file (metaPath, std::ios::out);
file << metaContent;
file.close();
}
const Scene::Texture* ArFrame::GetImageTexture()

View File

@@ -122,7 +122,20 @@ namespace OpenVulkano::AR
[[nodiscard]] ArTrackingState GetTrackingState() const { return frameMetadata.trackingState; };
[[nodiscard]] virtual Math::PoseF GetPose() const { return Math::PoseF(); }; //TODO
[[nodiscard]] virtual Math::PoseF GetPose() const { return Math::PoseF(frameMetadata.transformation); };
[[nodiscard]] virtual Math::Vector3f GetEulerAngle() const {
return {
asin(-frameMetadata.transformation[2][1]),
atan2(frameMetadata.transformation[2][0], frameMetadata.transformation[2][2]),
atan2(frameMetadata.transformation[0][1], frameMetadata.transformation[1][1])
};
}
[[nodiscard]] virtual const Math::Vector3f_SIMD& GetPosition() const
{
return reinterpret_cast<const Math::Vector3f_SIMD&>(frameMetadata.transformation[3]);
}
[[nodiscard]] Math::Timestamp GetTimestamp() const { return frameMetadata.timestamp; };

View File

@@ -8,8 +8,13 @@
#include "Provider/Playback/ArSessionPlayback.hpp"
#include "Provider/Network/ArSessionStream.h"
#ifdef __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_IOS == 1
#include "Provider/ArKit/ArSessionArKit.h"
#else
#include "Provider/ArSessionNull.hpp"
#endif
#else
#ifdef ANDROID
#include "Provider/ArCore/ArSessionArCore.h"
#else

View File

@@ -45,16 +45,22 @@ namespace OpenVulkano::AR
ArSessionType sessionType = ArSessionType::NATIVE;
bool uncompressed = true;
bool depthSupported = false;
bool supportsExposureLocking = false;
bool supportsWhitebalanceLocking = false;
bool hasFlashlight = false;
public:
ArSessionCapabilities() = default;
ArSessionCapabilities(const ArType type, const ArSessionType sessionType, const bool uncompressed, const bool depthSupported)
: type(type), sessionType(sessionType), uncompressed(uncompressed), depthSupported(depthSupported)
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)
{}
[[nodiscard]] bool IsUncompressed() const { return uncompressed; }
[[nodiscard]] bool IsDepthSupported() const { return depthSupported; }
[[nodiscard]] bool IsExposureLockSupported() const { return supportsExposureLocking; }
[[nodiscard]] bool IsWhitebalanceLockSupported() const { return supportsWhitebalanceLocking; }
[[nodiscard]] bool HasFlashlight() const { return hasFlashlight; }
[[nodiscard]] bool IsNative() const { return sessionType == ArSessionType::NATIVE; }
[[nodiscard]] bool IsPlayback() const { return sessionType == ArSessionType::PLAYBACK; }
[[nodiscard]] bool IsStream() const { return sessionType == ArSessionType::NETWORK_STREAM; }
@@ -214,6 +220,12 @@ namespace OpenVulkano::AR
*/
virtual void SetRenderer(IRenderer* renderer) = 0;
virtual void LockExposureTime(bool locked) {};
virtual void LockWhitebalance(bool locked) {};
virtual void SetFlashlightOn(bool on) {};
/**
* Gets the capabilities for this ArSession.
* @return The capabilities for the current AR session.

View File

@@ -14,7 +14,7 @@ namespace OpenVulkano::AR::ArKit
ArSessionCapabilities QueryNativeCapabilities()
{
bool supportsDepth = [ARWorldTrackingConfiguration supportsFrameSemantics:ARFrameSemanticSceneDepth];
ArSessionCapabilities capabilities(ArType::AR_KIT, ArSessionType::NATIVE, true, supportsDepth);
ArSessionCapabilities capabilities(ArType::AR_KIT, ArSessionType::NATIVE, true, supportsDepth, true, true, true);
return capabilities;
}
}

View File

@@ -51,6 +51,10 @@ namespace OpenVulkano::AR::ArKit
void SetRenderer(IRenderer* renderer) override;
void LockExposureTime(bool locked) override;
void LockWhitebalance(bool locked) override;
void SetFlashlightOn(bool on) override;
protected:
Scene::Texture * MakeTexture(ArFrame *frame) override;
@@ -66,6 +70,9 @@ namespace OpenVulkano::AR::ArKit
#else*/
SpintexProtectedObject<std::shared_ptr<ArFrame>> m_frame;
//#endif
std::atomic_size_t m_frameId;
std::atomic_size_t m_frameId = 0;
bool m_lockedConfiguration = false;
bool m_lockedExposure = false;
bool m_lockedWhitebalance = false;
};
}

View File

@@ -22,6 +22,7 @@
#import <ARKit/ARConfiguration.h>
#import <ARKit/ARCamera.h>
#import <ARKit/ARKit.h>
#import <AVFoundation/AVCaptureDevice.h>
#import <CoreVideo/CoreVideo.h>
#import "ArKitDelegate.h"
@@ -138,6 +139,11 @@ namespace OpenVulkano::AR::ArKit
void ArSessionArKitInternal::Stop()
{
if (m_lockedConfiguration)
{
m_lockedConfiguration = false;
[[ARWorldTrackingConfiguration configurableCaptureDeviceForPrimaryCamera] unlockForConfiguration];
}
OnStopped();
[m_arSession pause];
/*#if (__cplusplus >= 202002L)
@@ -184,6 +190,27 @@ namespace OpenVulkano::AR::ArKit
}
}
void ArSessionArKitInternal::LockExposureTime(bool locked)
{
AVCaptureDevice* dev = [ARWorldTrackingConfiguration configurableCaptureDeviceForPrimaryCamera];
if (!m_lockedConfiguration) m_lockedConfiguration |=[dev lockForConfiguration:nil];
[dev setExposureMode: locked ? AVCaptureExposureModeLocked : AVCaptureExposureModeContinuousAutoExposure];
}
void ArSessionArKitInternal::LockWhitebalance(bool locked)
{
AVCaptureDevice* dev = [ARWorldTrackingConfiguration configurableCaptureDeviceForPrimaryCamera];
if (!m_lockedConfiguration) m_lockedConfiguration |=[dev lockForConfiguration:nil];
[dev setWhiteBalanceMode: locked ? AVCaptureWhiteBalanceModeLocked : AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];
}
void ArSessionArKitInternal::SetFlashlightOn(bool on)
{
AVCaptureDevice* dev = [ARWorldTrackingConfiguration configurableCaptureDeviceForPrimaryCamera];
if (!m_lockedConfiguration) m_lockedConfiguration |=[dev lockForConfiguration:nil];
[dev setTorchMode: on ? AVCaptureTorchModeOn : AVCaptureTorchModeOff];
}
// AR Kit delegate events
void ArSessionArKitInternal::OnArNewFrame(ARSession* session, ARFrame* frame)

View File

@@ -17,7 +17,7 @@ namespace OpenVulkano::AR::Playback
ArSessionPlayback::ArSessionPlayback(const std::string& recordingPath, bool autoAdvance)
: ArSession(ArSessionMetadata(recordingPath)), recordingPath(recordingPath), autoAdvance(autoAdvance), playbackReader(recordingPath)
{
capabilities = ArSessionCapabilities(metadata.type, ArSessionType::PLAYBACK, false, metadata.depthFormat != ArDepthFormat::UNAVAILABLE);
capabilities = ArSessionCapabilities(metadata.type, ArSessionType::PLAYBACK, false, metadata.depthFormat != ArDepthFormat::UNAVAILABLE, false, false, false);
constants = { Math::Matrix4f(1), metadata.confidenceRange };
m_playbackReaderThread = std::thread([this](){ReadWorker();});

View File

@@ -227,12 +227,30 @@ namespace OpenVulkano
{}
void Notify(Arguments... args) const override
{
NotifyImpl(std::forward<Arguments>(args)...);
}
void NotifyImpl(Arguments... args) const
{
if (INamedEventProcessor::HasProcessor())
{
std::vector<INamedEventProcessor::Parameters> attributes;
attributes.reserve(sizeof...(Arguments));
if constexpr (!std::conjunction_v<std::is_enum<std::remove_reference_t<Arguments>>...>)
{
(attributes.emplace_back(args), ...);
}
else
{
auto fill = [&](auto&& arg) {
if constexpr (std::is_enum_v<std::remove_reference_t<decltype(arg)>>)
attributes.emplace_back(static_cast<int>(arg));
else
attributes.emplace_back(std::forward<decltype(arg)>(arg));
};
(fill(std::forward<Arguments>(args)), ...);
}
INamedEventProcessor::NotifyAll(m_name, attributes);
}
}

View File

@@ -32,14 +32,14 @@ namespace OpenVulkano
{}
Observable(T&& initValue, const std::string& observableName)
: object(std::forward(initValue)), OnChange(observableName)
: object(initValue), OnChange(observableName)
{}
template<typename = std::enable_if_t<std::is_copy_assignable_v<T>>>
auto& operator = (const T& val) { object = val; Notify(); return *this; }
template<typename = std::enable_if_t<std::is_move_assignable_v<T>>>
auto& operator = (T&& val) { object = std::forward(val); Notify(); return *this; }
auto& operator = (T&& val) { object = val; Notify(); return *this; }
template<typename = std::enable_if_t<std::is_copy_assignable_v<T>>>
operator T() const { return object; }
@@ -54,7 +54,9 @@ namespace OpenVulkano
bool operator >=(const T& other) const { return object >= other; }
bool operator !() const { return !object; }
operator bool() const { return object.operator bool(); }
template<std::enable_if<std::is_convertible_v<T, bool>>>
operator bool() const { return static_cast<bool>(object); }
auto& operator ++() { ++object; Notify(); return *this; }
auto& operator --() { --object; Notify(); return *this; }
auto& operator ++(int) { object++; Notify(); return *this; }

View File

@@ -35,5 +35,8 @@ namespace OpenVulkano
virtual Scene::UI::Ui* GetActiveUi() = 0;
virtual IResourceManager* GetIResourceManager() = 0;
virtual float GetLastQueriedDepthValue() = 0;
virtual void SetQueryDepthValue(const Math::Vector2f& depthCoordinates) = 0;
};
}

View File

@@ -84,6 +84,9 @@ namespace OpenVulkano
[[nodiscard]] virtual uint32_t GetWindowId() const = 0;
virtual void* GetNativeWindowHandle() = 0;
virtual float GetContentScale() const { return 1; }
virtual float GetInterfaceOrientation() const { return 0; }
protected:
static uint32_t CreateWindowId()
{

View File

@@ -46,6 +46,12 @@ namespace OpenVulkano
return result;
}
template<typename T, typename... N>
static auto MakeStdArray(N&&... args) -> std::array<T, sizeof...(args)>
{
return { std::forward<N>(args)... };
}
template<typename T, typename U>
static bool GetFlag(T var, U flag)
{

View File

@@ -15,22 +15,19 @@ configure_file(${CMAKE_SOURCE_DIR}/cmake/TryCompileShaders.cmake.in ${CMAKE_BINA
execute_process(COMMAND ${BASH_EXECUTABLE} CompileShaders.sh "${SHADER_OUTPUT_DEST}" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Scripts)
file(GLOB GENERATED_SHADER_SOURCES "${SHADER_OUTPUT_DEST}/*")
if(IOS)
set(CMAKE_Swift_LANGUAGE_VERSION 5.0)
enable_language(Swift)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.mm" "${CMAKE_CURRENT_SOURCE_DIR}/*.m" "${CMAKE_CURRENT_SOURCE_DIR}/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.swift")
add_library(openVulkanoCpp STATIC main.m ${resources} ${GENERATED_SHADER_SOURCES})
else()
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
if (APPLE)
file(GLOB_RECURSE sources_obj CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.mm" "${CMAKE_CURRENT_SOURCE_DIR}/*.m")
list(APPEND sources ${sources_obj})
endif ()
file(GLOB SHADER_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Shader/*)
list(FILTER SHADER_SRC_FILES EXCLUDE REGEX ".*\\.(hpp|cpp)$")
add_library(openVulkanoCpp STATIC main.cpp ${SHADER_SRC_FILES} ${GENERATED_SHADER_SOURCES})
if (MSVC)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
add_library(openVulkanoCpp ${MAIN_FILE} ${SHADER_SRC_FILES} ${GENERATED_SHADER_SOURCES})
set_property(TARGET openVulkanoCpp PROPERTY CXX_STANDARD 20)
source_group("Shaders" FILES ${SHADER_SRC_FILES})
endif()
endif()
FilterPlatformPaths(sources)
SetWarningSettings(openVulkanoCpp)
@@ -39,25 +36,12 @@ SetGlmDefines(openVulkanoCpp)
target_sources(openVulkanoCpp PRIVATE ${sources})
target_include_directories(openVulkanoCpp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${SHADER_OUTPUT_DEST})
# Setup IOS
if(IOS)
set(APP_BUNDLE_IDENTIFIER "eu.georgh93.openVulkano")
set(MACOSX_BUNDLE_INFO_STRING ${APP_BUNDLE_IDENTIFIER})
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
if(APPLE)
LinkAppleFrameworks(openVulkanoCpp)
endif ()
if (WIN32)
# Ws2
target_link_libraries(openVulkanoCpp PRIVATE Ws2_32)
set(CURL_STATIC_LIBS ${CMAKE_BINARY_DIR}/deps_curl/deps_curl)
file(GLOB_RECURSE LIBS "${CURL_STATIC_LIBS}/*.lib")
target_link_libraries(openVulkanoCpp PRIVATE ${LIBS})
endif ()
SetupVulkan(openVulkanoCpp)
@@ -68,22 +52,15 @@ SetShaderDependency(openVulkanoCpp
if (NOT ANDROID AND NOT IOS)
target_link_libraries(openVulkanoCpp PUBLIC glfw pugixml)
target_link_libraries(openVulkanoCpp PUBLIC ftxui::screen ftxui::dom ftxui::component)
LinkCurl(openVulkanoCpp)
endif()
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/deps/INSTALL)
target_link_libraries(openVulkanoCpp PUBLIC magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense Boost::regex)
LinkCurl(openVulkanoCpp)
add_compile_definitions(LIBARCHIVE_STATIC)
add_compile_definitions(NOMINMAX)
add_compile_definitions("DEBUG=$<CONFIG:Debug>")
SetGlmDefines(openVulkanoCpp)
target_link_libraries(openVulkanoCpp PUBLIC magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense units)
LinkAssimp(openVulkanoCpp)
LinkLibArchive(openVulkanoCpp)
LinkLibJpegTurbo(openVulkanoCpp)
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT openVulkanoCpp)
SetGlmDefines(openVulkanoCpp)
add_compile_definitions(LIBARCHIVE_STATIC)
add_compile_definitions(NOMINMAX)
add_compile_definitions("DEBUG=$<CONFIG:Debug>")

View File

@@ -62,8 +62,8 @@ namespace OpenVulkano
if (vec != Math::Vector3f_SIMD (0))
{
if (Math::Utils::length2(vec) > 1.0f)
{
vec = Math::Utils::normalize(vec);
{ //TODO only do this for keyboards
//vec = Math::Utils::normalize(vec);
}
const float timeScale = CURRENT_FRAME.frameTime; //TODO
vec = vec * timeScale * 3.0f; // scale vector
@@ -149,12 +149,12 @@ namespace OpenVulkano
{
m_actionForward->BindKey(Input::InputKey::Controller::AXIS_LEFT_Y);
m_actionForward->BindAxisButtons(Input::InputKey::Keyboard::KEY_W, Input::InputKey::Keyboard::KEY_S);
m_actionForward->BindKey(Input::InputKey::Touch::AXIS_PINCH, 0.2f);
m_actionForward->BindKey(Input::InputKey::Touch::AXIS_PINCH, 0.3f);
m_actionSide->BindKey(Input::InputKey::Controller::AXIS_LEFT_X);
m_actionSide->BindAxisButtons(Input::InputKey::Keyboard::KEY_D, Input::InputKey::Keyboard::KEY_A);
m_actionSide->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_X, -0.03f);
m_actionSide->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_X, -0.05f);
m_actionUp->BindAxisButtons(Input::InputKey::Keyboard::KEY_SPACE, Input::InputKey::Keyboard::KEY_LEFT_CONTROL);
m_actionUp->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_Y, 0.03f);
m_actionUp->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_Y, 0.05f);
m_actionLookUp->BindKey(Input::InputKey::Controller::AXIS_RIGHT_Y);
m_actionLookUp->BindAxisButtons(Input::InputKey::Keyboard::KEY_DOWN, Input::InputKey::Keyboard::KEY_UP);
m_actionLookUp->BindKey(Input::InputKey::Touch::AXIS_PAN_Y, -0.001f);

View File

@@ -48,6 +48,7 @@ namespace OpenVulkano
Math::Matrix4f camTransformation = Math::Utils::toMat4(rot);
camTransformation[3] = Math::Vector4f(m_position, 1);
GetCamera()->SetMatrix(camTransformation);
CURRENT_FRAME.needsRedraw = true;
}
void FreeCamCameraController::SetDefaultKeybindings()

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

@@ -16,6 +16,8 @@ namespace OpenVulkano
IWindowHandler* handler = nullptr;
void* caMetalLayer = nullptr;
bool tickHandler = true;
float contentScale = 1;
float orientation = 0;
public:
void Init(RenderAPI::RenderApi renderApi) override {}
@@ -83,6 +85,14 @@ namespace OpenVulkano
void OnResize(uint32_t width, uint32_t height);
virtual float GetContentScale() const override { return contentScale; }
virtual float GetInterfaceOrientation() const override { return orientation; }
void SetContentScale(float scale) { contentScale = scale; }
void SetOrientation(float orientation) { this->orientation = orientation; }
void TickHandler();
};
}

View File

@@ -159,12 +159,12 @@ namespace OpenVulkano
}
else
{
Logger::MANAGER->error("Cannot find constructor for named event %s", eventName);
Logger::MANAGER->error("Cannot find constructor for named event {}", eventName);
}
}
else
{
Logger::MANAGER->debug("Cannot find implementation for named event %s", eventName);
Logger::MANAGER->debug("Cannot find implementation for named event {}", eventName);
}
}
}

View File

@@ -45,7 +45,7 @@ namespace OpenVulkano
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);*/
io.DisplaySize = { static_cast<float>(m_window->GetWidth()), static_cast<float>(m_window->GetHeight()) };
io.DisplayFramebufferScale = { 1, 1 };
io.DisplayFramebufferScale = { m_window->GetContentScale(), m_window->GetContentScale() };
//if (bd->WantUpdateMonitors)
//ImGui_ImplGlfw_UpdateMonitors();

View File

@@ -0,0 +1,183 @@
/*
* 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/.
*/
#include "Host/SystemInfo.hpp"
#include "Base/Logger.hpp"
#include <sstream>
#include <mach/mach.h>
#include <os/proc.h>
#import <Foundation/NSString.h>
#import <Foundation/NSProcessInfo.h>
namespace OpenVulkano
{
Event<> SystemInfo::OnLowPowerModeChanged;
Event<> SystemInfo::OnBatteryStateChanged;
Event<> SystemInfo::OnBatteryLevelChanged;
Event<> SystemInfo::OnDeviceOrientationChanged;
size_t SystemInfo::GetSystemRam()
{
return [NSProcessInfo processInfo].physicalMemory;
}
size_t SystemInfo::GetSystemRamAvailable()
{
return 0; //TODO
}
size_t SystemInfo::GetAppRamMax()
{
return GetAppRamAvailable() + GetAppRamUsed();
}
size_t SystemInfo::GetAppVirtualMemoryMax()
{
return INT64_MAX;
}
size_t SystemInfo::GetAppRamAvailable()
{
return 0; //TODO
}
size_t SystemInfo::GetAppRamUsed()
{
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
if( kerr == KERN_SUCCESS )
{
return info.resident_size;
}
Logger::PERF->error("Failed to read memory consumption: {}", mach_error_string(kerr));
return 0;
}
std::string SystemInfo::GetUserName()
{
return "";
}
std::string SystemInfo::GetHostName()
{
return [[NSProcessInfo processInfo].hostName UTF8String];
}
std::string SystemInfo::GetDeviceName()
{
return "Mac"; //TODO
}
std::string SystemInfo::GetDeviceVendorName()
{
return "Apple";
}
std::string SystemInfo::GetDeviceModelName()
{
return ""; //TODO
}
std::string SystemInfo::GetOsName()
{
return ""; //TODO
}
OsVersion SystemInfo::GetOsVersion()
{
NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion;
return { static_cast<int>(osVersion.majorVersion), static_cast<int>(osVersion.minorVersion), static_cast<int>(osVersion.patchVersion), 0 };
}
std::string SystemInfo::GetOsNameHumanReadable()
{
std::stringstream name;
name << GetOsName() << ' ' << GetOsVersion().major;
return name.str();
}
DeviceType SystemInfo::GetDeviceType()
{
return DeviceType::PC;
}
size_t SystemInfo::GetCpuCoreCount()
{
return [NSProcessInfo processInfo].processorCount;
}
size_t SystemInfo::GetCpuThreadCount()
{
return [NSProcessInfo processInfo].activeProcessorCount;
}
int32_t SystemInfo::GetCpuTemperature()
{
switch([NSProcessInfo processInfo].thermalState)
{
case NSProcessInfoThermalStateNominal: return 20;
case NSProcessInfoThermalStateFair: return 50;
case NSProcessInfoThermalStateSerious: return 80;
case NSProcessInfoThermalStateCritical: return 100;
}
return -1;
}
CpuThermalState SystemInfo::GetCpuThermalState()
{
switch([NSProcessInfo processInfo].thermalState)
{
case NSProcessInfoThermalStateNominal: return CpuThermalState::Normal;
case NSProcessInfoThermalStateFair: return CpuThermalState::Fair;
case NSProcessInfoThermalStateSerious: return CpuThermalState::Serious;
case NSProcessInfoThermalStateCritical: return CpuThermalState::Critical;
}
return CpuThermalState::Normal;
}
bool SystemInfo::IsDeviceInLowPowerMode()
{
return [NSProcessInfo processInfo].lowPowerModeEnabled;
}
void SystemInfo::EnableEnergyEvents()
{
//TODO
}
BatteryState SystemInfo::GetDeviceBatteryState()
{
return BatteryState::Unavailable; //TODO
}
float SystemInfo::GetDeviceBatteryLevel()
{
return 0; //TODO
}
bool SystemInfo::IsMultitaskingSupported()
{
return true;
}
DeviceOrientation SystemInfo::GetDeviceOrientation()
{
return DeviceOrientation::LandscapeRight;
}
void SystemInfo::EnableDeviceOrientationEvents()
{
//TODO?
}
InterfaceOrientation SystemInfo::GetInterfaceOrientation()
{
return InterfaceOrientation::Landscape; //TODO?
}
}

View File

@@ -11,7 +11,7 @@
@implementation OpenVulkanoOrientationLockableViewController
-(id)init {
[super init];
self = [super init];
_rotationLockedView = nil;
return self;
}

View File

@@ -21,4 +21,6 @@
-(void)WillDisappear;
-(void)DidDisappear;
-(void)DidUnload;
-(void)SetInterfaceOrientation:(float)orientation;
@end

View File

@@ -9,7 +9,7 @@
#include "Base/Logger.hpp"
#include "Input/Touch/InputDeviceTouch.hpp"
#include "Input/InputManager.hpp"
#include "MetalViewWindow.h"
#include "Host/Apple/MetalViewWindow.h"
#include <map>
#import <MetalKit/MTKView.h>
@@ -35,6 +35,7 @@ using namespace OpenVulkano;
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size
{
window->SetContentScale(UIScreen.mainScreen.nativeScale);
window->OnResize(size.width, size.height);
}
@@ -83,8 +84,7 @@ using namespace OpenVulkano;
- (void)commonInit {
[self setMultipleTouchEnabled:YES];
self.contentScaleFactor = UIScreen.mainScreen.nativeScale / 1.5f;
self.contentScaleFactor = UIScreen.mainScreen.nativeScale;
auto size = self.bounds.size;
auto sizeX = size.width * self.contentScaleFactor;
auto sizeY = size.height * self.contentScaleFactor;
@@ -126,10 +126,17 @@ using namespace OpenVulkano;
auto size = self.bounds.size;
auto sizeX = size.width * self.contentScaleFactor;
auto sizeY = size.height * self.contentScaleFactor;
m_window.SetContentScale(self.contentScaleFactor);
m_window.OnResize(sizeX, sizeY);
}
}
- (void)SetInterfaceOrientation:(float)orientation
{
m_window.SetOrientation(orientation);
}
- (Math::Vector2f)getTouchPosition:(UITouch*)touch
{
CGPoint uitouchLocation = [touch locationInView:touch.view];

View File

@@ -17,7 +17,7 @@ namespace OpenVulkano::Scene
{
public:
ICloseable* renderCamera = nullptr;
static constexpr inline size_t SIZE = sizeof(Math::Matrix4f) * 3 + sizeof(Math::Vector4f) + sizeof(float) * 8 + 16;
static constexpr inline size_t SIZE = sizeof(Math::Matrix4f) * 3 + sizeof(Math::Vector4f) + sizeof(float) * 12;
static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_UNIFORM_BUFFER_DYNAMIC, 1, ShaderProgramType::ALL_GRAPHICS };
protected:
@@ -26,7 +26,8 @@ namespace OpenVulkano::Scene
float m_nearPlane, m_farPlane, m_width, m_height;
float m_fov = 0, m_aspect = 0, m_scaleFactor = 0, m_perPixelScaleFactor = 0;
float m_contentScaleFactor = 1, m_zoom = 1; // For use with ortho camera
std::array<uint8_t, 8> m_userData{};
float m_interfaceOrientation = 0;
float m_padding = 0; //Unused
Camera() : m_nearPlane(0), m_farPlane(0), m_width(0), m_height(0) {}
@@ -55,32 +56,19 @@ namespace OpenVulkano::Scene
virtual void SetSize(const float width, const float height)
{
if (m_width == width && m_height == height) return;
if (m_width == width && m_height == height) [[likely]] return;
m_width = width;
m_height = height;
UpdateProjectionMatrix();
}
void SetNearPlane(float nearPlane)
{
m_nearPlane = nearPlane;
}
void SetNearPlane(float nearPlane) { m_nearPlane = nearPlane; }
void SetFarPlane(float farPlane)
{
m_farPlane = farPlane;
}
void SetFarPlane(float farPlane) { m_farPlane = farPlane; }
[[nodiscard]] float NearPlane() const { return m_nearPlane; }
[[nodiscard]] float NearPlane() const
{
return m_nearPlane;
}
[[nodiscard]] float FarPlane() const
{
return m_farPlane;
}
[[nodiscard]] float FarPlane() const { return m_farPlane; }
void SetContentScaleFactor(float contentScale = 1)
{
@@ -89,6 +77,10 @@ namespace OpenVulkano::Scene
[[nodiscard]] float GetContentScaleFactor() const { return 1.0f / m_contentScaleFactor; }
void SetInterfaceOrientation(float orientation) { m_interfaceOrientation = orientation; }
float GetInterfaceOrientation() const { return m_interfaceOrientation; }
void SetZoom(float zoom) { m_zoom = 1.0f / zoom; }
[[nodiscard]] float GetZoom() const { return 1.0f / m_zoom; }
@@ -126,10 +118,7 @@ namespace OpenVulkano::Scene
return m_viewProjection;
}
[[nodiscard]] const Math::Vector4f& GetPosition() const
{
return m_camPosition;
}
[[nodiscard]] const Math::Vector4f& GetPosition() const { return m_camPosition; }
[[nodiscard]] Math::Vector3f GetRightVector() const
{
@@ -150,22 +139,19 @@ namespace OpenVulkano::Scene
[[nodiscard]] const Math::Matrix4f& GetViewMatrix() const { return m_view; }
[[nodiscard]] Math::Frustum GetFrustum() const
{
return {m_viewProjection};
}
[[nodiscard]] const Math::Matrix4f& GetProjectionMatrix() const { return m_projection; }
/**
* The 16 byte of user data can be used to transmit additional data about the camera to the shader.
* @return reference to the custom data array
*/
[[nodiscard]] std::array<uint8_t, 8>& GetUserData() { return m_userData; }
[[nodiscard]] Math::Frustum GetFrustum() const { return {m_viewProjection}; }
[[nodiscard]] float GetScaleFactor() const { return m_scaleFactor; }
[[nodiscard]] float GetPixelScaleFactor() const { return m_perPixelScaleFactor; }
[[nodiscard]] virtual bool IsPerspective() const { return false; }
[[nodiscard]] virtual bool IsOrtho() const { return false; }
float GetWidth() const { return m_width; }
float GetHeight() const { return m_height; }
Math::Vector2f GetSize() const { return { m_width, m_height }; }
};
class PerspectiveCamera : public Camera
@@ -202,6 +188,7 @@ namespace OpenVulkano::Scene
void SetSize(const float width, const float height) override
{
if (m_width == width && m_height == height) [[likely]] return;
m_aspect = width / height;
Camera::SetSize(width, height);
m_perPixelScaleFactor = m_height / m_scaleFactor;
@@ -235,20 +222,14 @@ namespace OpenVulkano::Scene
m_perPixelScaleFactor = m_height / m_scaleFactor;
}
[[nodiscard]] float GetFov() const
{
return Math::Utils::degrees(m_fov);
}
[[nodiscard]] float GetFov() const { return Math::Utils::degrees(m_fov); }
[[nodiscard]] float GetFovX() const
{
return 2.0f * atanf(tanf(GetFov() * 0.5f) * m_aspect);
}
[[nodiscard]] float GetFovRad() const
{
return m_fov;
}
[[nodiscard]] float GetFovRad() const { return m_fov; }
[[nodiscard]] float GetFovXRad() const
{

View File

@@ -307,4 +307,48 @@ namespace OpenVulkano::Scene
return result;
}
Geometry GeometryFactory::MakeArchStrip(float radius, float width, float endRadius, int segments, const Math::Vector4f& color, float endVCoord, bool indexBuffer)
{
Geometry result;
segments = std::max(2, segments);
result.Init(2 * segments, indexBuffer ? 6 * segments : 0);
const float segmentAngle = endRadius / static_cast<float>(segments - 1);
width /= 2;
const float segmentV = endVCoord / (segments - 1);
float segV = 0;
for(int i = 0, seg = 0; seg < segments; seg++)
{
float angle = seg * segmentAngle;
float z = std::cos(angle) * radius;
float y = std::sin(angle) * radius;
//TODO normals
result.vertices[i].color = color;
result.vertices[i++].Set(width, y, z, +0, +0, +1, +1, +segV);
result.vertices[i].color = color;
result.vertices[i++].Set(-width, y, z, +0, +0, +1, +0, +segV);
segV += segmentV;
}
if (indexBuffer)
{
uint32_t* indices = new uint32_t[result.GetIndexCount()];
for (uint32_t i = 0, segment = 0; segment < segments; ++segment)
{
uint32_t first = segment * 2;
uint32_t second = first + 1;
indices[i++] = first;
indices[i++] = second;
indices[i++] = first + 2;
indices[i++] = first + 2;
indices[i++] = second;
indices[i++] = second + 2;
}
result.SetIndices(indices, result.GetIndexCount());
}
return result;
}
}

View File

@@ -20,5 +20,6 @@ namespace OpenVulkano::Scene
static Geometry MakeTriangle(const Math::Vector3f& p1, const Math::Vector3f& p2, const Math::Vector3f& p3, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry MakeCylinder(float radius, float height, uint32_t segments, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry MakePyramid(float baseLength = 1, float height = 1, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry MakeArchStrip(float radius = 1, float width = 0.2, float endRadius = std::numbers::pi, int segments = 16, const Math::Vector4f& color = Math::Vector4f(1), float endVCoord = 1, bool indexBuffer = true);
};
}

View File

@@ -25,6 +25,7 @@ namespace OpenVulkano::Scene
m_shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/background");
m_shader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING);
m_shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
m_shader.depthCompareOp = CompareOp::LESS_OR_EQUAL;
SetShader(&m_shader);
m_intrinsicsBuffer.Init(sizeof(Math::CameraIntrinsicWithResolution), &FALLBACK_INTRINSICS);
m_intrinsicsBuffer.updateFrequency = UpdateFrequency::Always;

View File

@@ -16,6 +16,8 @@ namespace OpenVulkano::Scene
m_shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/grid");
m_shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/grid");
m_shader.alphaBlend = true;
m_shader.depthTest = true;
m_shader.depthWrite = false;
SetShader(&m_shader);
}

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/.
*/
#include "SamplerConfig.hpp"
namespace OpenVulkano::Scene
{
const SamplerConfig SamplerConfig::DEFAULT;
const SamplerConfig SamplerConfig::NEAREST(TextureSamplerFilter::NEAREST, TextureSamplerFilter::NEAREST);
const SamplerConfig SamplerConfig::LINEAR(TextureSamplerFilter::LINEAR, TextureSamplerFilter::NEAREST);
const SamplerConfig SamplerConfig::BILINEAR(TextureSamplerFilter::LINEAR, TextureSamplerFilter::LINEAR);
const SamplerConfig SamplerConfig::TIRILINEAR(TextureSamplerFilter::LINEAR, TextureSamplerFilter::LINEAR, TextureSamplerMipmapMode::LINEAR);
const SamplerConfig SamplerConfig::ANISOTROPIC_LOW(TextureSamplerFilter::LINEAR, TextureSamplerFilter::LINEAR, TextureSamplerMipmapMode::LINEAR, true, 4);
const SamplerConfig SamplerConfig::ANISOTROPIC_HIGH(TextureSamplerFilter::LINEAR, TextureSamplerFilter::LINEAR, TextureSamplerMipmapMode::LINEAR, true, 16);
const SamplerConfig SamplerConfig::ANISOTROPIC_PRO(TextureSamplerFilter::LINEAR, TextureSamplerFilter::LINEAR, TextureSamplerMipmapMode::LINEAR, true, 32);
}

View File

@@ -0,0 +1,104 @@
/*
* 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 <cinttypes>
#include <compare>
namespace OpenVulkano::Scene
{
enum class TextureSamplerFilter : int
{
NEAREST = 0,
LINEAR = 1,
CUBIC = 1000015000
};
enum class TextureSamplerEdgeMode : int
{
REPEAT = 0,
MIRRORED_REPEAT = 1,
CLAMP_TO_EDGE = 2,
CLAMP_TO_BORDER = 3,
MIRROR_CLAMP_TO_EDGE = 4
};
enum class TextureSamplerMipmapMode : int
{
NEAREST = 0,
LINEAR = 1
};
class SamplerConfig final
{
public:
using bool32_t = uint32_t;
private:
uint32_t type = 31; // To allow casting to vulkan struct
const void* next = nullptr; // To allow casting to vulkan struct
public:
uint32_t flags = 0;
TextureSamplerFilter magFilter = TextureSamplerFilter::NEAREST;
TextureSamplerFilter minFilter = TextureSamplerFilter::NEAREST;
TextureSamplerMipmapMode mipmapMode = TextureSamplerMipmapMode::NEAREST;
TextureSamplerEdgeMode edgeModeU = TextureSamplerEdgeMode::REPEAT;
TextureSamplerEdgeMode edgeModeV = TextureSamplerEdgeMode::REPEAT;
TextureSamplerEdgeMode edgeModeW = TextureSamplerEdgeMode::REPEAT;
float mipLoadBias = 0;
bool32_t anisotropyEnabled = false;
float maxAnisotropy = 0;
bool32_t compareEnabled = false;
uint32_t compareOp = 0; //TODO
float minLod = 0, maxLod = 0;
uint32_t borderColor = 0;
bool32_t unnormalizedCoordinates = false;
SamplerConfig(TextureSamplerEdgeMode edgeMode, TextureSamplerMipmapMode mipmapMode = TextureSamplerMipmapMode::NEAREST,
TextureSamplerFilter magFilter = TextureSamplerFilter::NEAREST, TextureSamplerFilter minFilter = TextureSamplerFilter::NEAREST)
: magFilter(magFilter), minFilter(minFilter), mipmapMode(mipmapMode), edgeModeU(edgeMode), edgeModeV(edgeMode), edgeModeW(edgeMode)
{}
SamplerConfig(uint32_t flags = 0, TextureSamplerFilter magFilter = TextureSamplerFilter::LINEAR,
TextureSamplerFilter minFilter = TextureSamplerFilter::LINEAR,
TextureSamplerMipmapMode mipmapMode = TextureSamplerMipmapMode::NEAREST,
TextureSamplerEdgeMode edgeModeU = TextureSamplerEdgeMode::REPEAT,
TextureSamplerEdgeMode edgeModeV = TextureSamplerEdgeMode::REPEAT,
TextureSamplerEdgeMode edgeModeW = TextureSamplerEdgeMode::REPEAT,
float mipLoadBias = 0, bool32_t anisotropyEnabled = false, float maxAnisotropy = 0,
bool32_t compareEnabled = false, uint32_t compareOp = 0, //TODO
float minLod = 0, float maxLod = 0, uint32_t borderColor = 0, bool32_t unnormalizedCoordinates = false)
: flags(flags), magFilter(magFilter), minFilter(minFilter), mipmapMode(mipmapMode)
, edgeModeU(edgeModeU), edgeModeV(edgeModeV), edgeModeW(edgeModeW)
, mipLoadBias(mipLoadBias), anisotropyEnabled(anisotropyEnabled), maxAnisotropy(maxAnisotropy)
, compareEnabled(compareEnabled), compareOp(compareOp)
, minLod(minLod), maxLod(maxLod), borderColor(borderColor), unnormalizedCoordinates(unnormalizedCoordinates)
{}
SamplerConfig(TextureSamplerFilter magFilter, TextureSamplerFilter minFilter = TextureSamplerFilter::LINEAR,
TextureSamplerMipmapMode mipmapMode = TextureSamplerMipmapMode::NEAREST,
bool32_t anisotropyEnabled = false, float maxAnisotropy = 0)
: magFilter(magFilter), minFilter(minFilter), mipmapMode(mipmapMode), anisotropyEnabled(anisotropyEnabled), maxAnisotropy(maxAnisotropy)
{}
auto operator <=>(const SamplerConfig& other) const = default;
public:
// Default configs
static const SamplerConfig DEFAULT;
static const SamplerConfig NEAREST;
static const SamplerConfig LINEAR;
static const SamplerConfig BILINEAR;
static const SamplerConfig TIRILINEAR;
static const SamplerConfig ANISOTROPIC_LOW;
static const SamplerConfig ANISOTROPIC_HIGH;
// Not supported on most consumer grphics cards!
static const SamplerConfig ANISOTROPIC_PRO;
};
}

View File

@@ -40,6 +40,18 @@ namespace OpenVulkano::Scene
PATCH_LIST
};
enum class CompareOp : uint32_t
{
NEVER = 0,
LESS = 1,
EQUAL = 2,
LESS_OR_EQUAL = 3,
GREATER = 4,
NOT_EQUAL = 5,
GREATER_OR_EQUAL = 6,
ALWAYS = 7
};
struct ShaderProgram
{
ShaderProgramType type;
@@ -77,12 +89,14 @@ namespace OpenVulkano::Scene
Topology topology = Topology::TRIANGLE_LIST;
CullMode cullMode = CullMode::BACK;
ICloseable* renderShader = nullptr;
CompareOp depthCompareOp = CompareOp::LESS;
bool alphaBlend = false; // TODO allow fine control over blending
bool depthTest = true;
bool depthWrite = true;
bool dynamicViewport = true; // If disabled the swapchains fullscreen viewport will always be used, regardless of framebuffer or viewport
Shader() = default;
~Shader() override { /*if (renderShader) Shader::Close();*/ }
~Shader() override { if (renderShader) Shader::Close(); }
Shader& AddShaderProgram(const ShaderProgram& shaderProgram)
{

View File

@@ -8,7 +8,7 @@
namespace OpenVulkano::Scene
{
Texture Texture::PLACEHOLDER = Texture(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

@@ -7,6 +7,7 @@
#pragma once
#include "UpdateFrequency.hpp"
#include "SamplerConfig.hpp"
#include "Base/ICloseable.hpp"
#include "Math/Math.hpp"
#include "DataFormat.hpp"
@@ -32,10 +33,13 @@ namespace OpenVulkano::Scene
size_t size = 0;
Math::Vector3ui resolution = {0,0,0};
DataFormat format = DataFormat::B8G8R8A8_UNORM;
bool updated = true;
UpdateFrequency updateFrequency = UpdateFrequency::Never;
const SamplerConfig* m_samplerConfig;
bool updated = true;
Texture(bool placeholder = false) { if (placeholder) MakePlaceholder(); }
Texture(const SamplerConfig* samplerConfig = &SamplerConfig::DEFAULT, bool placeholder = false)
: m_samplerConfig(samplerConfig)
{ if (placeholder) MakePlaceholder(); }
~Texture()
{

View File

@@ -27,10 +27,9 @@ layout(set = 2, binding = 0) uniform RealCameraData
layout(location = 0) out vec2 textureCoordinates;
layout(location = 1) out float scaleOut;
const float FLOAT_MAX_LESS_THAN_1 = 0.999999940395355224609;
// Background plane positions are in clipped space
const vec4 PLANE[4] = vec4[](
vec4(1, -1, FLOAT_MAX_LESS_THAN_1, 1), vec4(-1, -1, FLOAT_MAX_LESS_THAN_1, 1), vec4(1, 1, FLOAT_MAX_LESS_THAN_1, 1), vec4(-1, 1, FLOAT_MAX_LESS_THAN_1, 1)
vec4(1, -1, 1, 1), vec4(-1, -1, 1, 1), vec4(1, 1, 1, 1), vec4(-1, 1, 1, 1)
);
const vec2 TEX_COORDS[4] = vec2[](
vec2(1, 0), vec2(0, 0), vec2(1, 1), vec2(0, 1)

View File

@@ -0,0 +1,96 @@
/*
* 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/.
*/
#include "DepthBufferQuery.hpp"
#include "Renderer.hpp"
#include <vulkan/vulkan.hpp>
//TODO resize
namespace OpenVulkano::Vulkan
{
void DepthBufferQuery::Init()
{
auto device = renderer.GetContext().device->device;
vk::BufferCreateInfo bufferInfo = { {}, 25 * sizeof(float), vk::BufferUsageFlagBits::eTransferDst };
bufferDepth = device.createBuffer(bufferInfo);
const vk::MemoryRequirements memRequirements = device.getBufferMemoryRequirements(bufferDepth);
size_t size = memRequirements.size;
const vk::MemoryAllocateInfo memAllocInfo = { size, renderer.GetContext().device->GetMemoryType(memRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible) };
memory = device.allocateMemory(memAllocInfo);
cpuDepthBuffer = static_cast<float*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE, {}));
device.bindBufferMemory(bufferDepth, memory, 0);
}
void DepthBufferQuery::Close()
{
auto device = renderer.GetContext().device->device;
device.destroy(bufferDepth);
device.unmapMemory(memory);
device.free(memory);
cpuDepthBuffer = nullptr;
}
void DepthBufferQuery::Resize(uint32_t width, uint32_t height)
{
//TODO
}
float DepthBufferQuery::GetQueriedValue() const
{
if (cpuDepthBuffer[0] == -2) return -2;
if (cpuDepthBuffer[12] > 0 && cpuDepthBuffer[12] < 1) return cpuDepthBuffer[12];
double val = 0;
int validCount = 0;
for (int i = 0; i < 25; i++)
{
float f = cpuDepthBuffer[i];
if (f > 0 && f < 1)
{
val += f;
validCount++;
}
}
if (validCount == 0) return 1; // Prevent divide by 0
return val / validCount;
}
vk::Offset3D DepthBufferQuery::GetCopyOffset() const
{
vk::Extent3D depthExtent = renderer.GetContext().swapChain.GetCurrentDepthBuffer().extent;
int32_t x = static_cast<int32_t>(depthQueryCoordinates.x * depthExtent.width);
x = std::min<int32_t>(depthExtent.width - 5, std::max(0, x));
int32_t y = static_cast<int32_t>(depthQueryCoordinates.y * depthExtent.height);
y = std::min<int32_t>(depthExtent.height - 5, std::max(0, y));
return { x, y, 0 };
}
void DepthBufferQuery::Encode(vk::CommandBuffer& commandBuffer)
{
if (!copyDepthBuffer) return;
copyDepthBuffer = false;
std::fill(cpuDepthBuffer, cpuDepthBuffer + 25, -2.0f); // Invalidate data in buffer to allow detecting if copy is done
const vk::ImageAspectFlags aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil;
const Image& depthBufferImage = renderer.GetContext().swapChain.GetCurrentDepthBuffer();
constexpr vk::Extent3D copySize = { 5, 5, 1 };
const vk::ImageSubresourceLayers layout = { vk::ImageAspectFlagBits::eDepth, 0, 0, 1 };
vk::BufferImageCopy imgCopy = { 0, 5, 5, layout, GetCopyOffset(), copySize };
const vk::ImageMemoryBarrier imgMemBarrier({}, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal, 0, 0, depthBufferImage.image, vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1));
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, imgMemBarrier);
commandBuffer.copyImageToBuffer(depthBufferImage.image, vk::ImageLayout::eTransferSrcOptimal, bufferDepth, 1, &imgCopy);
depthBufferImage.SetLayout(commandBuffer, aspectMask, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal);
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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 "Math/Math.hpp"
#include "Vulkan/Image.hpp"
namespace OpenVulkano::Vulkan
{
class Renderer;
class DepthBufferQuery final
{
Renderer& renderer;
vk::DeviceMemory memory;
vk::Buffer bufferDepth;
float* cpuDepthBuffer = nullptr;
Math::Vector2f depthQueryCoordinates = { 0.5f, 0.5f };
bool copyDepthBuffer = true;
vk::Offset3D GetCopyOffset() const;
public:
DepthBufferQuery(Renderer& renderer): renderer(renderer) {}
~DepthBufferQuery() { if (cpuDepthBuffer != nullptr) Close(); }
void Init();
void Close();
void Encode(vk::CommandBuffer& commandBuffer);
void Resize(uint32_t width, uint32_t height);
float GetQueriedValue() const;
void SetQueryCoordinates(const Math::Vector2f& coords)
{
copyDepthBuffer = true;
depthQueryCoordinates = coords;
}
};
}

View File

@@ -18,6 +18,8 @@ void OpenVulkano::Vulkan::FrameBuffer::Init(Device* device, vk::Extent3D size, b
depthBufferFormat = FindDepthFormat();
CreateDepthStencil();
}
fullscreenViewport = vk::Viewport{ 0, 0, (float)size.width, (float)size.height, 0, 1 };
fullscreenScissor = vk::Rect2D{ { 0, 0 }, { size.width, size.height } };
}
void OpenVulkano::Vulkan::FrameBuffer::RegisterRenderPass(RenderPass* renderPass)
@@ -44,6 +46,8 @@ void OpenVulkano::Vulkan::FrameBuffer::Resize(vk::Extent3D size)
{
renderPass->Resize(size);
}
fullscreenViewport = vk::Viewport{ 0, 0, (float)size.width, (float)size.height, 0, 1 };
fullscreenScissor = vk::Rect2D{ { 0, 0 }, { size.width, size.height } };
}
void OpenVulkano::Vulkan::FrameBuffer::CreateDepthStencil()

View File

@@ -24,8 +24,10 @@ namespace OpenVulkano::Vulkan
vk::Format depthBufferFormat = vk::Format::eUndefined, colorFormat = vk::Format::eUndefined;
vk::Extent3D size;
std::vector<RenderPass*> renderPasses;
bool useDepthBuffer;
vk::Viewport fullscreenViewport;
vk::Rect2D fullscreenScissor;
Device* device = nullptr;
bool useDepthBuffer;
protected:
uint32_t currentFrameBufferId = 0;
@@ -38,15 +40,9 @@ namespace OpenVulkano::Vulkan
void Init(Device* device, vk::Extent3D size, bool useDepthBuffer = true);
void SetCurrentFrameId(uint32_t id)
{
currentFrameBufferId = id;
}
void SetCurrentFrameId(uint32_t id) { currentFrameBufferId = id; }
uint32_t GetCurrentFrameId() const
{
return currentFrameBufferId;
}
[[nodiscard]] uint32_t GetCurrentFrameId() const { return currentFrameBufferId; }
public:
void RegisterRenderPass(RenderPass* renderPass);
@@ -69,44 +65,32 @@ namespace OpenVulkano::Vulkan
void DestroyFrameBuffer();
virtual vk::Format FindColorFormat() = 0;
[[nodiscard]] virtual vk::Format FindColorFormat() = 0;
virtual vk::Format FindDepthFormat()
[[nodiscard]] virtual vk::Format FindDepthFormat()
{
return device->GetSupportedDepthFormat();
}
public:
virtual vk::Format GetColorFormat()
{
return colorFormat;
}
[[nodiscard]] vk::Format GetColorFormat() const { return colorFormat; }
virtual vk::Format GetDepthFormat()
{
return depthBufferFormat;
}
[[nodiscard]] vk::Format GetDepthFormat() const { return depthBufferFormat; }
virtual std::vector<IImage*> GetImages() = 0;
[[nodiscard]] virtual std::vector<IImage*> GetImages() = 0;
bool UseDepthBuffer() const
{
return useDepthBuffer;
}
[[nodiscard]] bool UseDepthBuffer() const { return useDepthBuffer; }
vk::Extent3D GetSize3D() const
{
return size;
}
[[nodiscard]] const vk::Extent3D& GetSize3D() const { return size; }
vk::Extent2D GetSize2D() const
{
return { size.width, size.height };
}
[[nodiscard]] vk::Extent2D GetSize2D() const { return { size.width, size.height }; }
vk::Framebuffer& GetCurrentFrameBuffer()
{
return frameBuffers[currentFrameBufferId];
}
[[nodiscard]] vk::Framebuffer& GetCurrentFrameBuffer() { return frameBuffers[currentFrameBufferId]; }
[[nodiscard]] const vk::Viewport& GetFullscreenViewport() const { return fullscreenViewport; }
[[nodiscard]] const vk::Rect2D& GetFullscreenScissor() const { return fullscreenScissor; }
[[nodiscard]] const Image& GetCurrentDepthBuffer() { return depthBuffer; }
};
}

View File

@@ -54,7 +54,7 @@ namespace OpenVulkano::Vulkan
}
m_vulkanTexture.view = m_vulkanTexture.device.createImageView(imgViewCreateInfo);
m_vulkanTexture.m_sampler = resManager->CreateSampler(VulkanTexture::DEFAULT_SAMPLER_CONFIG);
m_vulkanTexture.m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(Scene::SamplerConfig::DEFAULT));
m_vulkanTexture.SetDescriptorSet(resManager, resManager->GetDescriptorLayoutSet(binding), binding);
renderTexture = &m_vulkanTexture;

View File

@@ -57,7 +57,7 @@ namespace OpenVulkano::Vulkan
if (m_frameBuffer->UseDepthBuffer())
{ // Depth attachment
attachments.emplace_back(vk::AttachmentDescriptionFlags(), m_frameBuffer->GetDepthFormat(), vk::SampleCountFlagBits::e1,
m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eDontCare, m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eStore, m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eDepthStencilAttachmentOptimal);
depthReference = new vk::AttachmentReference(1, vk::ImageLayout::eDepthStencilAttachmentOptimal);
}

View File

@@ -18,6 +18,11 @@
namespace OpenVulkano::Vulkan
{
Renderer::Renderer()
: depthBufferQuery(*this)
{
}
void Renderer::Init(IGraphicsAppManager* graphicsAppManager, IWindow* window)
{
logger = Logger::RENDER;
@@ -62,6 +67,8 @@ namespace OpenVulkano::Vulkan
}
}
depthBufferQuery.Init();
logger->info("Vulkan renderer initialized");
}
@@ -69,6 +76,8 @@ namespace OpenVulkano::Vulkan
{
currentImageId = context.swapChain.AcquireNextImage();
scene->GetCamera()->SetSize(context.window->GetWidth(), context.window->GetHeight());
scene->GetCamera()->SetContentScaleFactor(context.window->GetContentScale());
scene->GetCamera()->SetInterfaceOrientation(context.window->GetInterfaceOrientation());
Render();
}
@@ -85,6 +94,7 @@ namespace OpenVulkano::Vulkan
closeables.pop_back();
closeable->Close();
}
depthBufferQuery.Close();
uiRenderer.Close();
resourceManager.Close();
commands.clear();
@@ -104,7 +114,7 @@ namespace OpenVulkano::Vulkan
resourceManager.Resize();
}
CommandHelper* Renderer::GetCommandData(uint32_t poolId)
CommandHelper* Renderer::GetCommandData(size_t poolId)
{
return &commands[poolId][currentImageId];
}
@@ -136,6 +146,7 @@ namespace OpenVulkano::Vulkan
CommandHelper* cmdHelper = GetCommandData(commands.size() - 1);
cmdHelper->cmdBuffer.executeCommands(submitBuffers[currentImageId].size(), submitBuffers[currentImageId].data());
context.swapChainRenderPass.End(cmdHelper->cmdBuffer);
depthBufferQuery.Encode(cmdHelper->cmdBuffer);
uiRenderer.DrawUiFrame(cmdHelper->cmdBuffer);
cmdHelper->cmdBuffer.end();
std::array<vk::PipelineStageFlags, 2> stateFlags = { vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput), vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput) };
@@ -162,12 +173,14 @@ namespace OpenVulkano::Vulkan
Submit();
}
void Renderer::RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t poolId)
void Renderer::RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, size_t poolId)
{
CommandHelper* cmdHelper = GetCommandData(poolId);
cmdHelper->Reset();
vk::CommandBufferInheritanceInfo inheritance = { context.swapChainRenderPass.renderPass, 0, context.swapChainRenderPass.GetFrameBuffer()->GetCurrentFrameBuffer() };
cmdHelper->cmdBuffer.begin(vk::CommandBufferBeginInfo{ vk::CommandBufferUsageFlagBits::eOneTimeSubmit | vk::CommandBufferUsageFlagBits::eRenderPassContinue, &inheritance });
cmdHelper->cmdBuffer.setViewport(0, 1, &context.swapChainRenderPass.GetFrameBuffer()->GetFullscreenViewport());
cmdHelper->cmdBuffer.setScissor(0, 1, &context.swapChainRenderPass.GetFrameBuffer()->GetFullscreenScissor());
Scene::Drawable** drawablePointer;
VulkanDrawContext drawContext { poolId, currentImageId, cmdHelper->cmdBuffer, this };

View File

@@ -16,6 +16,7 @@
#include "CommandHelper.hpp"
#include "Base/EngineConfiguration.hpp"
#include "Resources/ResourceManager.hpp"
#include "DepthBufferQuery.hpp"
#include <vector>
#include <thread>
@@ -40,9 +41,10 @@ namespace OpenVulkano::Vulkan
std::vector<std::vector<vk::CommandBuffer>> submitBuffers;
UiRenderer uiRenderer;
std::vector<ICloseable*> closeables;
DepthBufferQuery depthBufferQuery;
public:
Renderer() = default;
Renderer();
~Renderer() override = default;
void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) override;
@@ -63,7 +65,7 @@ namespace OpenVulkano::Vulkan
Scene::UI::Ui* GetActiveUi() override { return uiRenderer.GetActiveUi(); }
CommandHelper* GetCommandData(uint32_t poolId);
CommandHelper* GetCommandData(size_t poolId);
static void RunThread(Renderer* renderer, Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t id);
@@ -75,7 +77,7 @@ namespace OpenVulkano::Vulkan
void Render();
void RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t poolId);
void RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, size_t poolId);
ResourceManager& GetResourceManager() { return resourceManager; }
@@ -86,5 +88,9 @@ namespace OpenVulkano::Vulkan
void UnregisterCloseable(ICloseable* closeable) { Utils::Remove(closeables, closeable); }
IResourceManager* GetIResourceManager() override { return &resourceManager; }
float GetLastQueriedDepthValue() override { return depthBufferQuery.GetQueriedValue(); }
void SetQueryDepthValue(const Math::Vector2f& depthCoordinates) override { depthBufferQuery.SetQueryCoordinates(depthCoordinates); }
};
}

View File

@@ -55,7 +55,7 @@ namespace OpenVulkano::Vulkan
* \return The pointer to the mapped buffer.
*/
template <typename T = void>
T* Map(size_t offset = 0, vk::DeviceSize size = VK_WHOLE_SIZE, bool longTermMapping = true)
T* Map(vk::DeviceSize offset = 0, vk::DeviceSize size = VK_WHOLE_SIZE, bool longTermMapping = true)
{
if (!mapped)
{
@@ -106,7 +106,7 @@ namespace OpenVulkano::Vulkan
}
}
void Copy(const void* data, uint32_t size, uint32_t offset)
void Copy(const void* data, vk::DeviceSize size, vk::DeviceSize offset)
{
if(mapped) memcpy(static_cast<char*>(mapped) + offset, data, size);
else

View File

@@ -53,6 +53,7 @@ namespace OpenVulkano::Vulkan
ResourceManager::ResourceManager()
{
static_assert(sizeof(DescriptorSetLayoutBinding) == sizeof(vk::DescriptorSetLayoutBinding));
static_assert(sizeof(Scene::SamplerConfig) == sizeof(vk::SamplerCreateInfo));
}
ResourceManager::~ResourceManager() noexcept

View File

@@ -17,8 +17,15 @@ namespace OpenVulkano::Vulkan
VulkanShader::~VulkanShader()
{
if (!shader) return;
Close();
if (shader) Close();
device.destroyPipeline(pipeline);
for(auto& shaderModule : shaderModules)
{
device.destroyShaderModule(shaderModule);
}
device.destroyPipelineLayout(pipelineLayout);
for(auto& descriptorSetLayout : descriptorSetLayouts)
device.destroyDescriptorSetLayout(descriptorSetLayout);
}
void VulkanShader::Init(Context* context, Scene::Shader* shader, IShaderOwner* owner)
@@ -63,12 +70,12 @@ namespace OpenVulkano::Vulkan
if (shader->vertexInputDescriptions.size() == 1)
{ // Reuse already existing vertex attribute description
static_assert(sizeof(VertexInputParameter) == sizeof(vk::VertexInputAttributeDescription));
attributeDescriptionsSize = shader->vertexInputDescriptions[0].inputParameters.size();
attributeDescriptionsSize = static_cast<uint32_t>(shader->vertexInputDescriptions[0].inputParameters.size());
attributeDescriptionsData = reinterpret_cast<vk::VertexInputAttributeDescription*>(shader->vertexInputDescriptions[0].inputParameters.data());
}
else
{
attributeDescriptionsSize = attributeDescriptions.size();
attributeDescriptionsSize = static_cast<uint32_t>(attributeDescriptions.size());
attributeDescriptionsData = attributeDescriptions.data();
}
@@ -80,7 +87,7 @@ namespace OpenVulkano::Vulkan
vk::PipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.cullMode = static_cast<vk::CullModeFlagBits>(shader->cullMode);
vk::PipelineMultisampleStateCreateInfo msaa = {};
vk::PipelineDepthStencilStateCreateInfo depth = { {}, shader->depthTest, shader->depthWrite, vk::CompareOp::eLess };
vk::PipelineDepthStencilStateCreateInfo depth = { {}, shader->depthTest, shader->depthWrite, static_cast<vk::CompareOp>(shader->depthCompareOp) };
depth.maxDepthBounds = 1;
vk::PipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eA | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eR;
@@ -100,8 +107,14 @@ namespace OpenVulkano::Vulkan
CreatePipelineLayout();
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = { {}, static_cast<uint32_t>(shaderStageCreateInfo.size()), shaderStageCreateInfo.data(), &pipelineVertexInputStateCreateInfo, &inputAssembly,
nullptr, &viewportStateCreateInfo, &rasterizer, &msaa, &depth, &colorInfo, nullptr, pipelineLayout, context->swapChainRenderPass.renderPass };
const auto dynSates = Utils::MakeStdArray<vk::DynamicState>( vk::DynamicState::eViewport, vk::DynamicState::eScissor );
vk::PipelineDynamicStateCreateInfo dynStateInfo { {}, dynSates.size(), dynSates.data() };
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = { {}, static_cast<uint32_t>(shaderStageCreateInfo.size()),
shaderStageCreateInfo.data(), &pipelineVertexInputStateCreateInfo,
&inputAssembly, nullptr, &viewportStateCreateInfo, &rasterizer,
&msaa, &depth, &colorInfo, shader->dynamicViewport ? &dynStateInfo : nullptr, pipelineLayout,
context->swapChainRenderPass.renderPass };
pipeline = this->device.createGraphicsPipeline({}, pipelineCreateInfo).value;
}
@@ -119,16 +132,9 @@ namespace OpenVulkano::Vulkan
void VulkanShader::Close()
{
shader->renderShader = nullptr;
device.destroyPipeline(pipeline);
for(auto& shaderModule : shaderModules)
{
device.destroyShaderModule(shaderModule);
}
device.destroyPipelineLayout(pipelineLayout);
for(auto& descriptorSetLayout : descriptorSetLayouts)
device.destroyDescriptorSetLayout(descriptorSetLayout);
shader = nullptr;
if (owner) owner->RemoveShader(this);
owner = nullptr;
}
void VulkanShader::CreatePipelineLayout()

View File

@@ -19,7 +19,6 @@ namespace OpenVulkano::Vulkan
class VulkanTexture : public Scene::RenderTexture, public IRecordable, public Image
{
public:
static inline vk::SamplerCreateInfo DEFAULT_SAMPLER_CONFIG {};
vk::Sampler m_sampler;
vk::DescriptorSet m_descriptorSet;
@@ -30,7 +29,7 @@ namespace OpenVulkano::Vulkan
resManager->CopyDataToImage(m_texture->size, m_texture->textureBuffer, this);
texture->updated = false;
m_sampler = resManager->CreateSampler(DEFAULT_SAMPLER_CONFIG);
m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(texture->m_samplerConfig));
SetDescriptorSet(resManager, descriptorSetLayout, binding);
texture->renderTexture = this;
@@ -43,7 +42,7 @@ namespace OpenVulkano::Vulkan
texture->updated = false;
texture->textureBuffer = Map();
m_sampler = resManager->CreateSampler(DEFAULT_SAMPLER_CONFIG);
m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(texture->m_samplerConfig));
SetDescriptorSet(resManager, descriptorSetLayout, binding);
texture->renderTexture = this;

View File

@@ -59,7 +59,7 @@ namespace OpenVulkano::Vulkan
{
if(uBuffer->updated) //TODO fix
{
//uBuffer->updated = false;
uBuffer->updated = false;
buffer->Update(uBuffer->data, uBuffer->size, context->currentImageId);
}
buffer->Record(context);

View File

@@ -118,8 +118,6 @@ namespace OpenVulkano::Vulkan
for (size_t i = 0; i < images.size() + 1; i++)
imageAvailableSemaphores.emplace_back(device->device.createSemaphore({}));
fullscreenViewport = vk::Viewport{ 0, 0, (float)size.width, (float)size.height, 0, 1 };
fullscreenScissor = vk::Rect2D{ {0,0}, size };
Logger::RENDER->debug("Swap chain for window {0} created", window->GetWindowId());
}

View File

@@ -43,8 +43,6 @@ namespace OpenVulkano
IVulkanWindow* window = nullptr;
vk::SurfaceFormatKHR surfaceFormat;
vk::PresentModeKHR presentMode;
vk::Viewport fullscreenViewport;
vk::Rect2D fullscreenScissor;
std::vector<vk::Semaphore> imageAvailableSemaphores;
uint32_t currentSemaphoreId = 0;
vk::Extent2D size{ 0, 0 };
@@ -61,20 +59,7 @@ namespace OpenVulkano
void Resize(uint32_t newWidth, uint32_t newHeight);
[[nodiscard]] vk::Extent2D GetSize() const
{
return size;
}
[[nodiscard]] const vk::Viewport& GetFullscreenViewport() const
{
return fullscreenViewport;
}
[[nodiscard]] const vk::Rect2D& GetFullscreenScissor() const
{
return fullscreenScissor;
}
[[nodiscard]] vk::Extent2D GetSize() const { return size; }
uint32_t AcquireNextImage(const vk::Fence& fence = vk::Fence());
@@ -93,10 +78,7 @@ namespace OpenVulkano
}
}
[[nodiscard]] uint32_t GetImageCount() const
{
return images.size();
}
[[nodiscard]] uint32_t GetImageCount() const { return images.size(); }
vk::Semaphore& GetCurrentSemaphore() { return imageAvailableSemaphores[currentSemaphoreId]; }
@@ -108,10 +90,7 @@ namespace OpenVulkano
void DestroySwapChain();
protected:
vk::Format FindColorFormat() override
{
return surfaceFormat.format;
}
[[nodiscard]] vk::Format FindColorFormat() override { return surfaceFormat.format; }
virtual vk::PresentModeKHR ChosePresentMode();

0
tests/placeholder.cpp Normal file
View File