This commit is contained in:
xsl
2025-09-04 10:54:47 +08:00
commit 6bc8f61b18
1808 changed files with 208268 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
# Copyright (c) 2023-2024, Thomas Atkinson
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 the "License";
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_subdirectory(core)
if(ANDROID)
add_subdirectory(android)
elseif(WIN32)
add_subdirectory(windows)
elseif(APPLE OR UNIX)
if(IOS)
add_subdirectory(ios)
else ()
add_subdirectory(unix)
endif ()
else()
message(FATAL_ERROR "Unsupported platform")
endif()
add_subdirectory(filesystem)
+74
View File
@@ -0,0 +1,74 @@
////
- Copyright (c) 2023-2025, Thomas Atkinson
- Copyright (c) 2024-2025, The Khronos Group
-
- SPDX-License-Identifier: Apache-2.0
-
- Licensed under the Apache License, Version 2.0 the "License";
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
////
= Components
A component encapsulates all code relating to a specific goal.
Components act as individual compile targets.
This allows CMake to efficiently parallelize the compilation and link stages.
A component should include the minimum amount of dependencies.
Circular dependencies should be avoided.
== Core Component
Common interfaces can be used across the project and multiple components.
These interfaces are defined in `components/core`.
*Core* is the only component which does not follow the component pattern in its entirety.
The only major difference between core and other components is the header prefix used is `core/<sub_dir>` instead of `components/core/<sub_dir>`.
See xref:./core/README.adoc[core documentation] for more information.
== Create a new component
To create a new component add a new folder under `components/`.
The folder name should relate to the components implementation - see current components for inspiration.
The next instructs are to be carried out inside the `components/<component_name>` folder.
. Create a directory named `include/components/<component_name>`.
This contains all public headers which other components will have access too
. Create a directory named `src`.
This contains all private headers and source files.
Components will not be able to include these.
. Create a directory named `tests`.
This contains all test files for this component
. Create a `CMakeLists.txt`
=== Add the Component Compile Target
Registering a component adds the `vkb__<component_name>` compile target.
This target is also linked as a dependency to `vkb__components`.
[,cmake]
----
vkb__register_component(
NAME <component_name>
SRC
src/<some_private_header>.hpp
src/<some_source>.cpp
LINK_LIBS
<some_link_lib>
)
----
=== Compile Components
* To compile all components run cmake with `--target vkb__components`
* To compile a specific component run cmake with `--target vkb__<component_name>`
* To compile all tests run cmake with `--target vkb__tests`
* To compile a specific test run cmake with `--target tests__<test_name>`.
+35
View File
@@ -0,0 +1,35 @@
# Copyright (c) 2023, Thomas Atkinson
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 the "License";
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
vkb__register_component(
NAME android_platform
HEADERS
include/android/context.hpp
SRC
src/context.cpp
src/entrypoint.cpp
LINK_LIBS
vkb__core
)
add_definitions(-DVULKAN_HPP_TYPESAFE_CONVERSION=1)
# Import game-activity static lib inside the game-activity_static prefab module.
find_package(game-activity REQUIRED CONFIG)
target_link_libraries(vkb__android_platform PUBLIC log android game-activity::game-activity_static)
# attach to core
target_link_libraries(vkb__core INTERFACE vkb__android_platform)
@@ -0,0 +1,46 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <vector>
#include <core/platform/context.hpp>
#include <game-activity/native_app_glue/android_native_app_glue.h>
namespace vkb
{
/**
* @brief Android platform context
*
* @warning Use in extreme circumstances with code guarded by the PLATFORM__ANDROID define
*/
class AndroidPlatformContext final : public PlatformContext
{
public:
AndroidPlatformContext(android_app *app);
~AndroidPlatformContext() override = default;
android_app *app{nullptr};
static std::string android_external_storage_directory;
static std::string android_temp_directory;
static std::vector<std::string> android_arguments;
};
} // namespace vkb
+85
View File
@@ -0,0 +1,85 @@
/* Copyright (c) 2023-2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "android/context.hpp"
#include <jni.h>
extern "C"
{
// TODO: Arguments can be parsed from the bundle
JNIEXPORT void JNICALL
Java_com_khronos_vulkan_1samples_SampleLauncherActivity_sendArgumentsToPlatform(JNIEnv *env, jobject thiz, jobjectArray arg_strings)
{
std::vector<std::string> args;
for (int i = 0; i < env->GetArrayLength(arg_strings); i++)
{
jstring arg_string = (jstring) (env->GetObjectArrayElement(arg_strings, i));
const char *arg = env->GetStringUTFChars(arg_string, 0);
args.push_back(std::string(arg));
env->ReleaseStringUTFChars(arg_string, arg);
}
vkb::AndroidPlatformContext::android_arguments = args;
}
}
namespace details
{
std::string get_external_storage_directory(android_app *app)
{
return app->activity->externalDataPath;
}
std::string get_external_cache_directory(android_app *app)
{
JNIEnv *env;
app->activity->vm->AttachCurrentThread(&env, NULL);
jclass cls = env->FindClass("android/app/NativeActivity");
jmethodID getCacheDir = env->GetMethodID(cls, "getCacheDir", "()Ljava/io/File;");
jobject cache_dir = env->CallObjectMethod(app->activity->javaGameActivity, getCacheDir);
jclass fcls = env->FindClass("java/io/File");
jmethodID getPath = env->GetMethodID(fcls, "getPath", "()Ljava/lang/String;");
jstring path_string = (jstring) env->CallObjectMethod(cache_dir, getPath);
const char *path_chars = env->GetStringUTFChars(path_string, NULL);
std::string temp_folder(path_chars);
env->ReleaseStringUTFChars(path_string, path_chars);
app->activity->vm->DetachCurrentThread();
return temp_folder;
}
} // namespace details
namespace vkb
{
std::vector<std::string> AndroidPlatformContext::android_arguments = {};
AndroidPlatformContext::AndroidPlatformContext(android_app *app) :
PlatformContext{}, app{app}
{
_external_storage_directory = details::get_external_storage_directory(app);
_temp_directory = details::get_external_cache_directory(app);
_arguments = android_arguments;
}
} // namespace vkb
+25
View File
@@ -0,0 +1,25 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <core/platform/entrypoint.hpp>
#include "android/context.hpp"
std::unique_ptr<vkb::PlatformContext> create_platform_context(android_app *app)
{
return std::make_unique<vkb::AndroidPlatformContext>(app);
}
+77
View File
@@ -0,0 +1,77 @@
# Copyright (c) 2023-2025, Thomas Atkinson
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 the "License";
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
vkb__register_component(
NAME core
HEADERS
include/core/platform/context.hpp
include/core/platform/entrypoint.hpp
include/core/util/strings.hpp
include/core/util/error.hpp
include/core/util/hash.hpp
include/core/util/logging.hpp
include/core/util/profiling.hpp
SRC
src/strings.cpp
src/logging.cpp
src/profiling.cpp
LINK_LIBS
spdlog::spdlog
)
if (VKB_PROFILING)
target_link_libraries(vkb__core PUBLIC TracyClient)
target_compile_definitions(vkb__core PUBLIC TRACY_ENABLE)
endif()
if(ANDROID)
target_compile_definitions(vkb__core PUBLIC VK_USE_PLATFORM_ANDROID_KHR PLATFORM__ANDROID)
elseif(WIN32)
target_compile_definitions(vkb__core PUBLIC VK_USE_PLATFORM_WIN32_KHR PLATFORM__WINDOWS)
elseif(APPLE)
target_compile_definitions(vkb__core PUBLIC VK_USE_PLATFORM_METAL_EXT PLATFORM__MACOS)
elseif(UNIX)
target_compile_definitions(vkb__core PUBLIC PLATFORM__LINUX)
# Choose WSI based on VKB_WSI_SELECTION
if (VKB_WSI_SELECTION STREQUAL XCB OR VKB_WSI_SELECTION STREQUAL XLIB OR VKB_WSI_SELECTION STREQUAL WAYLAND)
find_package(PkgConfig REQUIRED)
endif()
if (VKB_WSI_SELECTION STREQUAL XCB)
pkg_check_modules(XCB xcb REQUIRED)
if (XCB_FOUND)
target_compile_definitions(vkb__core PUBLIC VK_USE_PLATFORM_XCB_KHR)
endif()
elseif (VKB_WSI_SELECTION STREQUAL XLIB)
pkg_check_modules(X11 x11 REQUIRED)
if (X11_FOUND)
target_compile_definitions(vkb__core PUBLIC VK_USE_PLATFORM_XLIB_KHR)
endif()
elseif (VKB_WSI_SELECTION STREQUAL WAYLAND)
pkg_check_modules(WAYLAND wayland-client REQUIRED)
if (WAYLAND_FOUND)
target_compile_definitions(vkb__core PUBLIC VK_USE_PLATFORM_WAYLAND_KHR)
endif()
elseif (VKB_WSI_SELECTION STREQUAL D2D)
set(DIRECT_TO_DISPLAY TRUE)
set(DIRECT_TO_DISPLAY TRUE PARENT_SCOPE)
target_compile_definitions(vkb__core PUBLIC VK_USE_PLATFORM_DISPLAY_KHR PLATFORM__LINUX_D2D)
else()
message(FATAL_ERROR "Unknown WSI")
endif()
endif()
+61
View File
@@ -0,0 +1,61 @@
////
- Copyright (c) 2023, Thomas Atkinson
-
- SPDX-License-Identifier: Apache-2.0
-
- Licensed under the Apache License, Version 2.0 the "License";
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
////
= Core
Core is a collection of pure interfaces or small utilities which are used across the project.
The core component is the only component which does not follow the component pattern in its entirety.
The only major difference between core and other components is the header prefix used is `core/<sub_dir>` instead of `components/core/<sub_dir>`.
== Platform
A Platform is the name we have given to the physical hardware and operating system that the project is executing on.
We support multiple platforms which can be identified by the following defines
* `PLATFORM__ANDROID`
* `PLATFORM__WINDOWS`
* `PLATFORM__LINUX_D2D`
* `PLATFORM__LINUX`
* `PLATFORM__MACOS`
Using these platforms should be as transparent as possible to a sample.
Components on the other hand may add platform specific code paths if required.
An application can create a cross platform entrypoint by using the `CUSTOM_MAIN(context_name)` macro
[,cpp]
----
#include <core/platform/entrypoint.hpp>
CUSTOM_MAIN(context)
{
context.arguments();
context.external_storage_directory();
context.temp_directory();
// Components using platform specific contexts
FileSystem fs = FileSystem::from_context(context);
}
----
== Utilities
* Error - A collection of error handling macros
* Hash - A collection of hashing functions
* Strings - A collection of string utilities
@@ -0,0 +1,71 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <memory>
#include <string>
#include <vector>
namespace vkb
{
class UnixPlatformContext;
class WindowsPlatformContext;
class AndroidPlatformContext;
/**
* @brief A platform context contains abstract platform specific operations
*
* A platform can be thought as the physical device and operating system configuration that the application
* is running on.
*
* Some platforms can be reused across different hardware configurations, such as Linux and Macos as both
* are POSIX compliant. However, some platforms are more specific such as Android and Windows
*/
class PlatformContext
{
// only allow platform contexts to be created by the platform specific implementations
friend class UnixPlatformContext;
friend class WindowsPlatformContext;
friend class AndroidPlatformContext;
public:
virtual ~PlatformContext() = default;
virtual const std::vector<std::string> &arguments() const
{
return _arguments;
}
virtual const std::string &external_storage_directory() const
{
return _external_storage_directory;
}
virtual const std::string &temp_directory() const
{
return _temp_directory;
}
protected:
std::vector<std::string> _arguments;
std::string _external_storage_directory;
std::string _temp_directory;
PlatformContext() = default;
};
} // namespace vkb
@@ -0,0 +1,74 @@
/* Copyright (c) 2023-2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "core/platform/context.hpp"
// Platform specific entrypoint definitions
// Applications should use CUSTOM_MAIN to define their own main function
// Definitions added by core/CMakeLists.txt
#if defined(PLATFORM__MACOS)
#include <TargetConditionals.h>
#endif
#if defined(PLATFORM__ANDROID)
# include <game-activity/native_app_glue/android_native_app_glue.h>
extern std::unique_ptr<vkb::PlatformContext> create_platform_context(android_app *state);
# define CUSTOM_MAIN(context_name) \
int platform_main(const vkb::PlatformContext &); \
void android_main(android_app *state) \
{ \
auto context = create_platform_context(state); \
platform_main(*context); \
} \
int platform_main(const vkb::PlatformContext &context_name)
#elif defined(PLATFORM__WINDOWS)
# include <Windows.h>
extern std::unique_ptr<vkb::PlatformContext> create_platform_context(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow);
# define CUSTOM_MAIN(context_name) \
int platform_main(const vkb::PlatformContext &); \
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) \
{ \
auto context = create_platform_context(hInstance, hPrevInstance, lpCmdLine, nCmdShow); \
return platform_main(*context); \
} \
int platform_main(const vkb::PlatformContext &context_name)
#elif defined(PLATFORM__LINUX) || defined(PLATFORM__MACOS)
extern std::unique_ptr<vkb::PlatformContext> create_platform_context(int argc, char **argv);
# define CUSTOM_MAIN(context_name) \
int platform_main(const vkb::PlatformContext &); \
int main(int argc, char *argv[]) \
{ \
auto context = create_platform_context(argc, argv); \
return platform_main(*context); \
} \
int platform_main(const vkb::PlatformContext &context_name)
#else
# include <stdexcept>
# define CUSTOM_MAIN(context_name) \
int main(int argc, char *argv[]) \
{ \
throw std::runtime_error{"platform not supported"}; \
} \
int unused(const vkb::PlatformContext &context_name)
#endif
@@ -0,0 +1,69 @@
/* Copyright (c) 2023-2025, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
# define __GCC__ __GNUC__
#endif
#if defined(__clang__)
// CLANG ENABLE/DISABLE WARNING DEFINITION
# define VKBP_DISABLE_WARNINGS() \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wall\"") \
_Pragma("clang diagnostic ignored \"-Wextra\"") \
_Pragma("clang diagnostic ignored \"-Wtautological-compare\"") \
_Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")
# define VKBP_ENABLE_WARNINGS() \
_Pragma("clang diagnostic pop")
#elif defined(__GNUC__) || defined(__GNUG__)
// GCC ENABLE/DISABLE WARNING DEFINITION
# define VKBP_DISABLE_WARNINGS() \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wall\"") \
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
_Pragma("GCC diagnostic ignored \"-Wtautological-compare\"")
# define VKBP_ENABLE_WARNINGS() \
_Pragma("GCC diagnostic pop")
#elif defined(_MSC_VER)
// MSVC ENABLE/DISABLE WARNING DEFINITION
# define VKBP_DISABLE_WARNINGS() \
__pragma(warning(push, 0))
# define VKBP_ENABLE_WARNINGS() \
__pragma(warning(pop))
#endif
// TODO: replace with a direct fmt submodule
#include <fmt/format.h>
#include <stdexcept>
template <typename... Args>
inline void ERRORF(const std::string &format, Args &&...args)
{
throw std::runtime_error(fmt::vformat(format, fmt::make_format_args(args...)));
}
inline void ERRORF(const std::string &message)
{
throw std::runtime_error(message);
}
#define NOT_IMPLEMENTED() ERRORF("not implemented")
@@ -0,0 +1,41 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <functional>
namespace vkb
{
inline void hash_combine(size_t &seed, size_t hash)
{
hash += 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= hash;
}
/**
* @brief Helper function to combine a given hash
* with a generated hash for the input param.
*/
template <class T>
inline void hash_combine(size_t &seed, const T &v)
{
std::hash<T> hasher;
hash_combine(seed, hasher(v));
}
} // namespace vkb
@@ -0,0 +1,37 @@
/* Copyright (c) 2018-2024, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <spdlog/fmt/fmt.h>
#include <spdlog/spdlog.h>
#define LOGGER_FORMAT "[%^%l%$] %v"
#define PROJECT_NAME "VulkanSamples"
#define LOGI(...) spdlog::info(__VA_ARGS__);
#define LOGW(...) spdlog::warn(__VA_ARGS__);
#define LOGE(...) spdlog::error("{}", fmt::format(__VA_ARGS__));
#define LOGD(...) spdlog::debug(__VA_ARGS__);
namespace vkb
{
namespace logging
{
void init();
}
} // namespace vkb
@@ -0,0 +1,130 @@
/* Copyright (c) 2023-2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstdint>
#include <cstdio>
#include <unordered_map>
#include "core/util/error.hpp"
#ifdef TRACY_ENABLE
# include <tracy/Tracy.hpp>
#endif
#ifdef TRACY_ENABLE
// malloc and free are used by Tracy to provide memory profiling
void *operator new(size_t count);
void operator delete(void *ptr) noexcept;
// Tracy a scope
# define PROFILE_SCOPE(name) ZoneScopedN(name)
// Trace a function
# define PROFILE_FUNCTION() ZoneScoped
#else
# define PROFILE_SCOPE(name)
# define PROFILE_FUNCTION()
#endif
// The type of plot to use
enum class PlotType
{
Number,
Percentage,
Memory,
};
// tracy::PlotFormatType is not defined if TRACY_ENABLE is not defined
// so we need to define a function to convert our enum to the tracy enum
#ifdef TRACY_ENABLE
namespace
{
inline tracy::PlotFormatType to_tracy_plot_format(PlotType type)
{
switch (type)
{
case PlotType::Number:
return tracy::PlotFormatType::Number;
case PlotType::Percentage:
return tracy::PlotFormatType::Percentage;
case PlotType::Memory:
return tracy::PlotFormatType::Memory;
default:
return tracy::PlotFormatType::Number;
}
}
} // namespace
# define TO_TRACY_PLOT_FORMAT(name) to_tracy_plot_format(name)
#else
# define TO_TRACY_PLOT_FORMAT(name)
#endif
// Create plots
template <typename T, PlotType PT = PlotType::Number>
class Plot
{
public:
static void plot(const char *name, T value)
{
auto *p = get_instance();
p->plots[name] = value;
update_tracy_plot(name, value);
}
static void increment(const char *name, T amount)
{
auto *p = get_instance();
p->plots[name] += amount;
update_tracy_plot(name, p->plots[name]);
}
static void decrement(const char *name, T amount)
{
auto *p = get_instance();
p->plots[name] -= amount;
update_tracy_plot(name, p->plots[name]);
}
static void reset(const char *name)
{
auto *p = get_instance();
p->plots[name] = T{};
update_tracy_plot(name, p->plots[name]);
}
private:
static void update_tracy_plot(const char *name, T value)
{
#ifdef TRACY_ENABLE
TracyPlot(name, value);
TracyPlotConfig(name, TO_TRACY_PLOT_FORMAT(PT), true, true, 0);
#endif
}
static Plot *get_instance()
{
static_assert((std::is_same<T, int64_t>::value || std::is_same<T, double>::value || std::is_same<T, float>::value), "PlotStore only supports int64_t, double and float");
static Plot instance;
return &instance;
}
std::unordered_map<const char *, T> plots;
};
@@ -0,0 +1,38 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
namespace vkb
{
/**
* @brief Replaces all occurrences of a substring with another substring.
*/
std::string replace_all(std::string str, const std::string &from, const std::string &to);
/**
* @brief Removes all occurrences of a set of characters from the end of a string.
*/
std::string trim_right(const std::string &str, const std::string &chars = " ");
/**
* @brief Removes all occurrences of a set of characters from the beginning of a string.
*/
std::string trim_left(const std::string &str, const std::string &chars = " ");
} // namespace vkb
+52
View File
@@ -0,0 +1,52 @@
/* Copyright (c) 2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/util/logging.hpp"
#include "spdlog/cfg/env.h"
#ifdef PLATFORM__ANDROID
# include "spdlog/sinks/android_sink.h"
#else
# include "spdlog/sinks/stdout_color_sinks.h"
#endif
namespace vkb
{
namespace logging
{
void init()
{
// Taken from "spdlog/cfg/env.h" and renamed SPDLOG_LEVEL to VKB_LOG_LEVEL
auto env_val = spdlog::details::os::getenv("VKB_LOG_LEVEL");
if (!env_val.empty())
{
spdlog::cfg::helpers::load_levels(env_val);
}
#ifdef PLATFORM__ANDROID
auto logger = spdlog::android_logger_mt("vkb", "VulkanSamples");
#else
auto logger = spdlog::stdout_color_mt("vkb");
#endif
logger->set_pattern(LOGGER_FORMAT);
logger->set_level(spdlog::level::trace);
spdlog::set_default_logger(logger);
}
} // namespace logging
} // namespace vkb
+35
View File
@@ -0,0 +1,35 @@
/* Copyright (c) 2023-2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/util/profiling.hpp"
#include <cstdlib>
#ifdef TRACY_ENABLE
void *operator new(size_t count)
{
auto ptr = malloc(count);
TracyAlloc(ptr, count);
return ptr;
}
void operator delete(void *ptr) noexcept
{
TracyFree(ptr);
free(ptr);
}
#endif
+46
View File
@@ -0,0 +1,46 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <core/util/strings.hpp>
namespace vkb
{
std::string replace_all(std::string str, const std::string &from, const std::string &to)
{
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length() - 1;
}
return str;
}
std::string trim_right(const std::string &str, const std::string &chars)
{
std::string result = str;
result.erase(str.find_last_not_of(chars) + 1);
return result;
}
std::string trim_left(const std::string &str, const std::string &chars)
{
std::string result = str;
result.erase(0, str.find_first_not_of(chars));
return result;
}
} // namespace vkb
+37
View File
@@ -0,0 +1,37 @@
# Copyright (c) 2023-2025, Thomas Atkinson
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 the "License";
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
vkb__register_component(
NAME filesystem
HEADERS
include/filesystem/filesystem.hpp
include/filesystem/legacy.h
# private
src/std_filesystem.hpp
SRC
src/legacy.cpp
src/filesystem.cpp
src/std_filesystem.cpp
LINK_LIBS
vkb__core
stb
)
# GCC 9.0 and later has std::filesystem in the stdc++ library
# Earlier versions require linking against stdc++fs
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
target_link_libraries(vkb__filesystem PRIVATE stdc++fs)
endif()
+19
View File
@@ -0,0 +1,19 @@
////
- Copyright (c) 2023-2024, Thomas Atkinson
-
- SPDX-License-Identifier: Apache-2.0
-
- Licensed under the Apache License, Version 2.0 the "License";
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
////
= File System
@@ -0,0 +1,85 @@
/* Copyright (c) 2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <filesystem>
#include <memory>
#include <string>
#include <vector>
#include "core/platform/context.hpp"
#include "core/util/logging.hpp"
namespace vkb
{
namespace filesystem
{
struct FileStat
{
bool is_file;
bool is_directory;
size_t size;
};
using Path = std::filesystem::path;
// A thin filesystem wrapper
class FileSystem
{
public:
FileSystem() = default;
virtual ~FileSystem() = default;
virtual FileStat stat_file(const Path &path) = 0;
virtual bool is_file(const Path &path) = 0;
virtual bool is_directory(const Path &path) = 0;
virtual bool exists(const Path &path) = 0;
virtual bool create_directory(const Path &path) = 0;
virtual std::vector<uint8_t> read_chunk(const Path &path, size_t offset, size_t count) = 0;
virtual void write_file(const Path &path, const std::vector<uint8_t> &data) = 0;
virtual void remove(const Path &path) = 0;
virtual void set_external_storage_directory(const std::string &dir) = 0;
virtual const Path &external_storage_directory() const = 0;
virtual const Path &temp_directory() const = 0;
void write_file(const Path &path, const std::string &data);
// Read the entire file into a string
std::string read_file_string(const Path &path);
// Read the entire file into a vector of bytes
std::vector<uint8_t> read_file_binary(const Path &path);
};
using FileSystemPtr = std::shared_ptr<FileSystem>;
void init();
// Initialize the filesystem with the given context
void init_with_context(const PlatformContext &context);
// Get the filesystem instance
FileSystemPtr get();
namespace helpers
{
std::string filename(const std::string &path);
}
} // namespace filesystem
} // namespace vkb
@@ -0,0 +1,142 @@
/* Copyright (c) 2019-2025, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <unordered_map>
#include <vector>
namespace vkb
{
namespace fs
{
namespace path
{
enum Type
{
// Relative paths
Assets,
Shaders,
Storage,
Screenshots,
Logs,
/* NewFolder */
TotalRelativePathTypes,
// Special paths
ExternalStorage,
Temp
};
extern const std::unordered_map<Type, std::string> relative_paths;
/**
* @brief Gets the absolute path of a given type or a specific file
* @param type The type of file path
* @param file (Optional) The filename
* @throws runtime_error if the platform didn't initialize each path properly, path wasn't found or the path was found but is empty
* @return Path to the directory of a certain type
*/
const std::string get(const Type type, const std::string &file = "");
} // namespace path
/**
* @brief Helper to tell if a given path is a directory
* @param path A path to a directory
* @return True if the path points to a valid directory, false if not
*/
bool is_directory(const std::string &path);
/**
* @brief Checks if a file exists
* @param filename The filename to check
* @return True if the path points to a valid file, false if not
*/
bool is_file(const std::string &filename);
/**
* @brief Platform specific implementation to create a directory
* @param path A path to a directory
*/
void create_directory(const std::string &path);
/**
* @brief Recursively creates a directory
* @param root The root directory that the path is relative to
* @param path A path in the format 'this/is/an/example/path/'
*/
void create_path(const std::string &root, const std::string &path);
/**
* @brief Helper to read an asset file into a byte-array
*
* @param filename The path to the file (relative to the assets directory)
* @return A vector filled with data read from the file
*/
std::vector<uint8_t> read_asset(const std::string &filename);
/**
* @brief Helper to read a text file into a single string
*
* @param filename The path to the file (relative to the assets directory)
* @return A string of the text the file
*/
std::string read_text_file(const std::string &filename);
/**
* @brief Helper to read a shader file into an array of unsigned 32 bit integers
*
* @param filename The path to the file (relative to the assets directory)
* @return A vector filled with data read from the file
*/
std::vector<uint32_t> read_shader_binary_u32(const std::string &filename);
/**
* @brief Helper to read a temporary file into a byte-array
*
* @param filename The path to the file (relative to the temporary storage directory)
* @return A vector filled with data read from the file
*/
std::vector<uint8_t> read_temp(const std::string &filename);
/**
* @brief Helper to write to a file in temporary storage
*
* @param data A vector filled with data to write
* @param filename The path to the file (relative to the temporary storage directory)
* of data will be used.
*/
void write_temp(const std::vector<uint8_t> &data, const std::string &filename);
/**
* @brief Helper to write to a png image in permanent storage
*
* @param data A vector filled with pixel data to write in (R, G, B, A) format
* @param filename The name of the image file without an extension
* @param width The width of the image
* @param height The height of the image
* @param components The number of bytes per element
* @param row_stride The stride in bytes of a row of pixels
*/
void write_image(const uint8_t *data, const std::string &filename, const uint32_t width, const uint32_t height, const uint32_t components, const uint32_t row_stride);
} // namespace fs
} // namespace vkb
+67
View File
@@ -0,0 +1,67 @@
/* Copyright (c) 2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "filesystem/filesystem.hpp"
#include "core/platform/context.hpp"
#include "core/util/error.hpp"
#include "std_filesystem.hpp"
namespace vkb
{
namespace filesystem
{
static FileSystemPtr fs = nullptr;
void init()
{
fs = std::make_shared<StdFileSystem>();
}
void init_with_context(const PlatformContext &context)
{
fs = std::make_shared<StdFileSystem>(
context.external_storage_directory(),
context.temp_directory());
}
FileSystemPtr get()
{
assert(fs && "Filesystem not initialized");
return fs;
}
void FileSystem::write_file(const Path &path, const std::string &data)
{
write_file(path, std::vector<uint8_t>(data.begin(), data.end()));
}
std::string FileSystem::read_file_string(const Path &path)
{
auto bin = read_file_binary(path);
return {bin.begin(), bin.end()};
}
std::vector<uint8_t> FileSystem::read_file_binary(const Path &path)
{
auto stat = stat_file(path);
return read_chunk(path, 0, stat.size);
}
} // namespace filesystem
} // namespace vkb
+141
View File
@@ -0,0 +1,141 @@
/* Copyright (c) 2019-2025, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "filesystem/legacy.h"
#include "core/util/error.hpp"
VKBP_DISABLE_WARNINGS()
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
VKBP_ENABLE_WARNINGS()
#include "filesystem/filesystem.hpp"
namespace vkb
{
namespace fs
{
namespace path
{
const std::unordered_map<Type, std::string> relative_paths = {
{Type::Assets, "assets/"},
{Type::Shaders, "shaders/"},
{Type::Storage, "output/"},
{Type::Screenshots, "output/images/"},
{Type::Logs, "output/logs/"},
};
const std::string get(const Type type, const std::string &file)
{
assert(relative_paths.size() == Type::TotalRelativePathTypes && "Not all paths are defined in filesystem, please check that each enum is specified");
// Check for special cases first
if (type == Type::Temp)
{
return vkb::filesystem::get()->temp_directory().string();
}
// Check for relative paths
auto it = relative_paths.find(type);
if (relative_paths.size() < Type::TotalRelativePathTypes)
{
throw std::runtime_error("Platform hasn't initialized the paths correctly");
}
else if (it == relative_paths.end())
{
throw std::runtime_error("Path enum doesn't exist, or wasn't specified in the path map");
}
else if (it->second.empty())
{
throw std::runtime_error("Path was found, but it is empty");
}
auto fs = vkb::filesystem::get();
auto path = fs->external_storage_directory() / it->second;
if (!is_directory(path))
{
create_path(fs->external_storage_directory().string(), it->second);
}
auto full_path = path / file;
return full_path.string();
}
} // namespace path
bool is_directory(const std::string &path)
{
return vkb::filesystem::get()->is_directory(path);
}
bool is_file(const std::string &filename)
{
return vkb::filesystem::get()->is_file(filename);
}
void create_directory(const std::string &path)
{
vkb::filesystem::get()->create_directory(path);
}
void create_path(const std::string &root, const std::string &path)
{
std::filesystem::path full_path = std::filesystem::path(root) / path;
if (!vkb::filesystem::get()->create_directory(full_path))
{
ERRORF("Failed to create directory: {}", full_path.string());
}
}
std::vector<uint8_t> read_asset(const std::string &filename)
{
return vkb::filesystem::get()->read_file_binary(path::get(path::Type::Assets) + filename);
}
std::string read_text_file(const std::string &filename)
{
return vkb::filesystem::get()->read_file_string(path::get(path::Type::Shaders) + filename);
}
std::vector<uint32_t> read_shader_binary_u32(const std::string &filename)
{
auto buffer = vkb::filesystem::get()->read_file_binary(path::get(path::Type::Shaders) + filename);
assert(buffer.size() % sizeof(uint32_t) == 0);
auto spirv = std::vector<uint32_t>(reinterpret_cast<uint32_t *>(buffer.data()), reinterpret_cast<uint32_t *>(buffer.data()) + buffer.size() / sizeof(uint32_t));
return spirv;
}
std::vector<uint8_t> read_temp(const std::string &filename)
{
return vkb::filesystem::get()->read_file_binary(path::get(path::Type::Temp) + filename);
}
void write_temp(const std::vector<uint8_t> &data, const std::string &filename)
{
vkb::filesystem::get()->write_file(path::get(path::Type::Temp) + filename, data);
}
void write_image(const uint8_t *data, const std::string &filename, const uint32_t width, const uint32_t height, const uint32_t components, const uint32_t row_stride)
{
stbi_write_png((path::get(path::Type::Screenshots) + filename + ".png").c_str(), width, height, components, data, row_stride);
}
} // namespace fs
} // namespace vkb
@@ -0,0 +1,159 @@
/* Copyright (c) 2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "std_filesystem.hpp"
#include <core/util/logging.hpp>
#include <filesystem>
#include <fstream>
namespace vkb
{
namespace filesystem
{
FileStat StdFileSystem::stat_file(const Path &path)
{
std::error_code ec;
auto fs_stat = std::filesystem::status(path, ec);
if (ec)
{
return FileStat{
false,
false,
0,
};
}
auto size = std::filesystem::file_size(path, ec);
if (ec)
{
size = 0;
}
return FileStat{
fs_stat.type() == std::filesystem::file_type::regular,
fs_stat.type() == std::filesystem::file_type::directory,
size,
};
}
bool StdFileSystem::is_file(const Path &path)
{
auto stat = stat_file(path);
return stat.is_file;
}
bool StdFileSystem::is_directory(const Path &path)
{
auto stat = stat_file(path);
return stat.is_directory;
}
bool StdFileSystem::exists(const Path &path)
{
auto stat = stat_file(path);
return stat.is_file || stat.is_directory;
}
bool StdFileSystem::create_directory(const Path &path)
{
std::error_code ec;
std::filesystem::create_directories(path, ec);
if (ec)
{
throw std::runtime_error("Failed to create directory at path: " + path.string());
}
return !ec;
}
std::vector<uint8_t> StdFileSystem::read_chunk(const Path &path, size_t offset, size_t count)
{
std::ifstream file{path, std::ios::binary | std::ios::ate};
if (!file.is_open())
{
throw std::runtime_error("Failed to open file for reading at path: " + path.string());
}
auto size = stat_file(path).size;
if (offset + count > size)
{
return {};
}
// read file contents
file.seekg(offset, std::ios::beg);
std::vector<uint8_t> data(count);
file.read(reinterpret_cast<char *>(data.data()), count);
return data;
}
void StdFileSystem::write_file(const Path &path, const std::vector<uint8_t> &data)
{
// create directory if it doesn't exist
auto parent = path.parent_path();
if (!std::filesystem::exists(parent))
{
create_directory(parent);
}
std::ofstream file{path, std::ios::binary | std::ios::trunc};
if (!file.is_open())
{
throw std::runtime_error("Failed to open file for writing at path: " + path.string());
}
file.write(reinterpret_cast<const char *>(data.data()), data.size());
}
void StdFileSystem::remove(const Path &path)
{
std::error_code ec;
std::filesystem::remove_all(path, ec);
if (ec)
{
throw std::runtime_error("Failed to remove file at path: " + path.string());
}
}
void StdFileSystem::set_external_storage_directory(const std::string &dir)
{
_external_storage_directory = dir;
}
const Path &StdFileSystem::external_storage_directory() const
{
return _external_storage_directory;
}
const Path &StdFileSystem::temp_directory() const
{
return _temp_directory;
}
} // namespace filesystem
} // namespace vkb
@@ -0,0 +1,63 @@
/* Copyright (c) 2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "filesystem/filesystem.hpp"
#include <filesystem>
namespace vkb
{
namespace filesystem
{
class StdFileSystem final : public FileSystem
{
public:
StdFileSystem(Path external_storage_directory = std::filesystem::current_path(), Path temp_directory = std::filesystem::temp_directory_path()) :
_external_storage_directory(std::move(external_storage_directory)),
_temp_directory(std::move(temp_directory))
{}
virtual ~StdFileSystem() = default;
FileStat stat_file(const Path &path) override;
bool is_file(const Path &path) override;
bool is_directory(const Path &path) override;
bool exists(const Path &path) override;
bool create_directory(const Path &path) override;
std::vector<uint8_t> read_chunk(const Path &path, size_t offset, size_t count) override;
void write_file(const Path &path, const std::vector<uint8_t> &data) override;
virtual void remove(const Path &path) override;
virtual void set_external_storage_directory(const std::string &dir) override;
const Path &external_storage_directory() const override;
const Path &temp_directory() const override;
private:
Path _external_storage_directory;
Path _temp_directory;
};
} // namespace filesystem
} // namespace vkb
+31
View File
@@ -0,0 +1,31 @@
# Copyright (c) 2023-2025, Thomas Atkinson
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 the "License";
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
enable_language(OBJCXX)
vkb__register_component(
NAME ios_platform
HEADERS
include/ios/context.hpp
SRC
src/context.mm
src/entrypoint.cpp
LINK_LIBS
vkb__core
)
# attach to core
target_link_libraries(vkb__core INTERFACE vkb__ios_platform)
+39
View File
@@ -0,0 +1,39 @@
/* Copyright (c) 2023-2024, Holochip Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <core/platform/context.hpp>
namespace vkb
{
/**
* @brief IOS platform context
*
* @warning Use in extreme circumstances with code guarded by the PLATFORM__UNIX define
*/
class IosPlatformContext final : public PlatformContext
{
public:
IosPlatformContext(int argc, char **argv);
~IosPlatformContext() override = default;
void * view;
void* userPlatform;
};
} // namespace vkb
+39
View File
@@ -0,0 +1,39 @@
/* Copyright (c) 2023-2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ios/context.hpp"
#import <UIKit/UIKit.h>
namespace vkb
{
IosPlatformContext::IosPlatformContext(int argc, char **argv) :
PlatformContext{}
{
_arguments.reserve(argc);
for (int i = 1; i < argc; ++i)
{
_arguments.emplace_back(argv[i]);
}
const char *env_temp_dir = std::getenv("TMPDIR");
const char *env_get_home_dir = std::getenv("HOME");
const char *bundle_dir = [[[NSBundle mainBundle] resourcePath] UTF8String];
_temp_directory = env_temp_dir ? std::string(env_temp_dir) + "/" : "/tmp/";
_external_storage_directory = bundle_dir;
}
} // namespace vkb
+25
View File
@@ -0,0 +1,25 @@
/* Copyright (c) 2023-2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <core/platform/entrypoint.hpp>
#include "ios/context.hpp"
std::unique_ptr<vkb::PlatformContext> create_platform_context(int argc, char **argv)
{
return std::make_unique<vkb::IosPlatformContext>(argc, argv);
}
+29
View File
@@ -0,0 +1,29 @@
# Copyright (c) 2023-2025, Thomas Atkinson
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 the "License";
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
vkb__register_component(
NAME unix_platform
HEADERS
include/unix/context.hpp
SRC
src/context.cpp
src/entrypoint.cpp
LINK_LIBS
vkb__core
)
# attach to core
target_link_libraries(vkb__core INTERFACE vkb__unix_platform)
+37
View File
@@ -0,0 +1,37 @@
/* Copyright (c) 2023-2024, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <core/platform/context.hpp>
namespace vkb
{
/**
* @brief Unix platform context
*
* @warning Use in extreme circumstances with code guarded by the PLATFORM__UNIX define
*/
class UnixPlatformContext final : public PlatformContext
{
public:
UnixPlatformContext(int argc, char **argv);
~UnixPlatformContext() override = default;
};
} // namespace vkb
+36
View File
@@ -0,0 +1,36 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "unix/context.hpp"
namespace vkb
{
UnixPlatformContext::UnixPlatformContext(int argc, char **argv) :
PlatformContext{}
{
_arguments.reserve(argc);
for (int i = 1; i < argc; ++i)
{
_arguments.emplace_back(argv[i]);
}
const char *env_temp_dir = std::getenv("TMPDIR");
_temp_directory = env_temp_dir ? std::string(env_temp_dir) + "/" : "/tmp/";
_external_storage_directory = "";
}
} // namespace vkb
+25
View File
@@ -0,0 +1,25 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <core/platform/entrypoint.hpp>
#include "unix/context.hpp"
std::unique_ptr<vkb::PlatformContext> create_platform_context(int argc, char **argv)
{
return std::make_unique<vkb::UnixPlatformContext>(argc, argv);
}
+29
View File
@@ -0,0 +1,29 @@
# Copyright (c) 2023-2025, Thomas Atkinson
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 the "License";
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
vkb__register_component(
NAME windows_platform
HEADERS
include/windows/context.hpp
SRC
src/context.cpp
src/entrypoint.cpp
LINK_LIBS
vkb__core
)
# attach to core
target_link_libraries(vkb__core INTERFACE vkb__windows_platform)
@@ -0,0 +1,38 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <Windows.h>
#include <core/platform/context.hpp>
namespace vkb
{
/**
* @brief MS Windows platform context
*
* @warning Use in extreme circumstances with code guarded by the PLATFORM__WINDOWS define
*/
class WindowsPlatformContext final : public PlatformContext
{
public:
WindowsPlatformContext(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow);
~WindowsPlatformContext() override = default;
};
} // namespace vkb
+105
View File
@@ -0,0 +1,105 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "windows/context.hpp"
#include <Windows.h>
#include <cassert>
#include <stdexcept>
namespace vkb
{
inline const std::string get_temp_path_from_environment()
{
std::string temp_path = "temp/";
TCHAR temp_buffer[MAX_PATH];
DWORD temp_path_ret = GetTempPath(MAX_PATH, temp_buffer);
if (temp_path_ret > MAX_PATH || temp_path_ret == 0)
{
temp_path = "temp/";
}
else
{
temp_path = std::string(temp_buffer) + "/";
}
return temp_path;
}
/// @brief Converts wstring to string using Windows specific function
/// @param wstr Wide string to convert
/// @return A converted utf8 string
inline std::string wstr_to_str(const std::wstring &wstr)
{
if (wstr.empty())
{
return {};
}
auto wstr_len = static_cast<int>(wstr.size());
auto str_len = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr_len, NULL, 0, NULL, NULL);
std::string str(str_len, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr_len, &str[0], str_len, NULL, NULL);
return str;
}
inline std::vector<std::string> get_args()
{
LPWSTR *argv;
int argc;
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
// Ignore the first argument containing the application full path
std::vector<std::wstring> arg_strings(argv + 1, argv + argc);
std::vector<std::string> args;
for (auto &arg : arg_strings)
{
args.push_back(wstr_to_str(arg));
}
return args;
}
WindowsPlatformContext::WindowsPlatformContext(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) :
PlatformContext{}
{
_external_storage_directory = "";
_temp_directory = get_temp_path_from_environment();
_arguments = get_args();
// Attempt to attach to the parent process console if it exists
if (!AttachConsole(ATTACH_PARENT_PROCESS))
{
// No parent console, allocate a new one for this process
if (!AllocConsole())
{
throw std::runtime_error{"AllocConsole error"};
}
}
FILE *fp;
freopen_s(&fp, "conin$", "r", stdin);
freopen_s(&fp, "conout$", "w", stdout);
freopen_s(&fp, "conout$", "w", stderr);
}
} // namespace vkb
+26
View File
@@ -0,0 +1,26 @@
/* Copyright (c) 2023, Thomas Atkinson
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <core/platform/entrypoint.hpp>
#include "windows/context.hpp"
#include <Windows.h>
std::unique_ptr<vkb::PlatformContext> create_platform_context(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
return std::make_unique<vkb::WindowsPlatformContext>(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}