Separate out rendering / resource loading code logically

This commit is contained in:
William 2024-01-31 07:08:40 +00:00
parent 5a67f85bc9
commit c5e926df08
21 changed files with 1691 additions and 212 deletions

View File

@ -0,0 +1,68 @@
FetchContent_Declare(fast_io GIT_REPOSITORY https://github.com/cppfastio/fast_io.git GIT_TAG 804d943e30df0da782538d508da6ea6e427fc2cf GIT_PROGRESS ON)
FetchContent_GetProperties(fast_io)
if(NOT fast_io_POPULATED)
FetchContent_Populate(fast_io)
message(STATUS "Patching fast_io")
PatchUtil_Patch(
fast_io
"${CMAKE_SOURCE_DIR}/patches/fast_io.patch"
"${fast_io_SOURCE_DIR}"
2
_patch_result
)
if(_patch_result)
message(STATUS "Patched fast_io (or it was already patched)")
else()
message(FATAL_ERROR "Failed to patch fast_io")
endif()
add_subdirectory(${fast_io_SOURCE_DIR} ${fast_io_BINARY_DIR})
endif()
FetchContent_MakeAvailable(fast_io)
FetchContent_Declare(glm GIT_REPOSITORY https://github.com/g-truc/glm.git GIT_TAG 0.9.9.8 GIT_PROGRESS ON)
FetchContent_MakeAvailable(glm)
# FetchContent_Declare(assimp GIT_REPOSITORY https://github.com/assimp/assimp.git GIT_TAG v5.3.1 GIT_PROGRESS ON)
# FetchContent_MakeAvailable(assimp)
FetchContent_Declare(GSL
GIT_REPOSITORY https://github.com/microsoft/GSL.git
GIT_TAG v4.0.0
GIT_PROGRESS ON)
FetchContent_MakeAvailable(GSL)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) # Tells CMAKE to shut up about glad using an old CMAKE
FetchContent_Declare(glad GIT_REPOSITORY https://github.com/Dav1dde/glad.git GIT_TAG b6f6ff2c4a25cd0dfe11ea6e3dc50454677251b9 GIT_PROGRESS ON)
FetchContent_MakeAvailable(glad)
add_library(fast_io_module)
target_sources(fast_io_module PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES fast_io.cpp)
message(${fast_io_SOURCE_DIR}/include)
target_include_directories(fast_io_module PUBLIC ${fast_io_SOURCE_DIR}/include)
add_library(glm_module)
target_sources(glm_module PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES glm.cpp)
target_link_libraries(glm_module PRIVATE glm)
add_library(glm.lh_module)
target_sources(glm.lh_module PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES glm.lh.cpp)
target_link_libraries(glm.lh_module PRIVATE glm)
add_library(glfw_module)
target_sources(glfw_module PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES glfw.cpp)
target_link_libraries(glfw_module PRIVATE glfw)
# add_library(assimp_module)
# target_sources(assimp_module PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES assimp.cpp)
# target_link_libraries(assimp_module PRIVATE assimp::assimp)
add_library(GSL_module)
target_sources(GSL_module PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES gsl.cpp)
target_link_libraries(GSL_module PRIVATE Microsoft.GSL::GSL)
add_library(glad_module)
target_sources(glad_module PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES glad.cpp)
target_link_libraries(glad_module PRIVATE glad)

View File

@ -0,0 +1,37 @@
module;
#include <cmath>
#include <algorithm>
#include <string>
export module assimptest;
export
{
#include <assimp/color4.h>
#include <assimp/vector2.h>
#include <assimp/vector3.h>
#include <assimp/matrix3x3.h>
#include <assimp/matrix4x4.h>
#include <assimp/quaternion.h>
}
#include <assimp/color4.inl>
#include <assimp/vector2.inl>
#include <assimp/vector3.inl>
#include <assimp/matrix3x3.inl>
#include <assimp/matrix4x4.inl>
#include <assimp/quaternion.inl>
export
{
#include <assimp/material.h>
}
#include <assimp/material.inl>
export
{
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
}

View File

@ -0,0 +1,23 @@
module;
#include <ctime>
#include <iterator>
#include <limits>
#include <ranges>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
export module fast_io;
export
{
#include <fast_io.h>
#include <fast_io_device.h>
#include <fast_io_unit/gb18030.h>
}

View File

@ -0,0 +1,7 @@
module;
export module glad;
export
{
#include <glad/glad.h>
}

1081
3rdparty-modules/glfw.cpp Normal file

File diff suppressed because it is too large Load Diff

86
3rdparty-modules/glm.cpp Normal file
View File

@ -0,0 +1,86 @@
module;
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstddef>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iosfwd>
#include <limits>
#include <locale>
export module glm;
export
{
// include all glm headers
#include <glm/glm.hpp>
#include <glm/gtc/bitfield.hpp>
#include <glm/gtc/color_space.hpp>
#include <glm/gtc/constants.hpp>
#include <glm/gtc/epsilon.hpp>
#include <glm/gtc/integer.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/noise.hpp>
#include <glm/gtc/packing.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtc/reciprocal.hpp>
#include <glm/gtc/round.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/ulp.hpp>
#include <glm/gtc/vec1.hpp>
#include <glm/gtx/associated_min_max.hpp>
#include <glm/gtx/bit.hpp>
#include <glm/gtx/closest_point.hpp>
#include <glm/gtx/color_space.hpp>
#include <glm/gtx/color_space_YCoCg.hpp>
#include <glm/gtx/compatibility.hpp>
#include <glm/gtx/component_wise.hpp>
#include <glm/gtx/dual_quaternion.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/extend.hpp>
#include <glm/gtx/gradient_paint.hpp>
#include <glm/gtx/handed_coordinate_space.hpp>
#include <glm/gtx/hash.hpp>
#include <glm/gtx/integer.hpp>
#include <glm/gtx/intersect.hpp>
#include <glm/gtx/io.hpp>
#include <glm/gtx/log_base.hpp>
#include <glm/gtx/matrix_cross_product.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtx/matrix_interpolation.hpp>
#include <glm/gtx/matrix_major_storage.hpp>
#include <glm/gtx/matrix_operation.hpp>
#include <glm/gtx/matrix_query.hpp>
#include <glm/gtx/mixed_product.hpp>
#include <glm/gtx/norm.hpp>
#include <glm/gtx/normal.hpp>
#include <glm/gtx/normalize_dot.hpp>
#include <glm/gtx/number_precision.hpp>
#include <glm/gtx/optimum_pow.hpp>
#include <glm/gtx/orthonormalize.hpp>
#include <glm/gtx/perpendicular.hpp>
#include <glm/gtx/polar_coordinates.hpp>
#include <glm/gtx/projection.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/raw_data.hpp>
#include <glm/gtx/rotate_normalized_axis.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/scalar_multiplication.hpp>
#include <glm/gtx/scalar_relational.hpp>
#include <glm/gtx/spline.hpp>
#include <glm/gtx/std_based_type.hpp>
// Doesn't work with modules: #include <glm/gtx/string_cast.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/transform2.hpp>
#include <glm/gtx/type_trait.hpp>
#include <glm/gtx/vec_swizzle.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <glm/gtx/vector_query.hpp>
#include <glm/gtx/wrap.hpp>
}

View File

@ -0,0 +1,87 @@
module;
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstddef>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iosfwd>
#include <limits>
#include <locale>
export module glm.lh;
export
{
#define GLM_FORCE_LEFT_HANDED
// include all glm headers
#include <glm/glm.hpp>
#include <glm/gtc/bitfield.hpp>
#include <glm/gtc/color_space.hpp>
#include <glm/gtc/constants.hpp>
#include <glm/gtc/epsilon.hpp>
#include <glm/gtc/integer.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/noise.hpp>
#include <glm/gtc/packing.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtc/reciprocal.hpp>
#include <glm/gtc/round.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/ulp.hpp>
#include <glm/gtc/vec1.hpp>
#include <glm/gtx/associated_min_max.hpp>
#include <glm/gtx/bit.hpp>
#include <glm/gtx/closest_point.hpp>
#include <glm/gtx/color_space.hpp>
#include <glm/gtx/color_space_YCoCg.hpp>
#include <glm/gtx/compatibility.hpp>
#include <glm/gtx/component_wise.hpp>
#include <glm/gtx/dual_quaternion.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/extend.hpp>
#include <glm/gtx/gradient_paint.hpp>
#include <glm/gtx/handed_coordinate_space.hpp>
#include <glm/gtx/hash.hpp>
#include <glm/gtx/integer.hpp>
#include <glm/gtx/intersect.hpp>
#include <glm/gtx/io.hpp>
#include <glm/gtx/log_base.hpp>
#include <glm/gtx/matrix_cross_product.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtx/matrix_interpolation.hpp>
#include <glm/gtx/matrix_major_storage.hpp>
#include <glm/gtx/matrix_operation.hpp>
#include <glm/gtx/matrix_query.hpp>
#include <glm/gtx/mixed_product.hpp>
#include <glm/gtx/norm.hpp>
#include <glm/gtx/normal.hpp>
#include <glm/gtx/normalize_dot.hpp>
#include <glm/gtx/number_precision.hpp>
#include <glm/gtx/optimum_pow.hpp>
#include <glm/gtx/orthonormalize.hpp>
#include <glm/gtx/perpendicular.hpp>
#include <glm/gtx/polar_coordinates.hpp>
#include <glm/gtx/projection.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/raw_data.hpp>
#include <glm/gtx/rotate_normalized_axis.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/scalar_multiplication.hpp>
#include <glm/gtx/scalar_relational.hpp>
#include <glm/gtx/spline.hpp>
#include <glm/gtx/std_based_type.hpp>
// Doesn't work with modules: #include <glm/gtx/string_cast.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/transform2.hpp>
#include <glm/gtx/type_trait.hpp>
#include <glm/gtx/vec_swizzle.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <glm/gtx/vector_query.hpp>
#include <glm/gtx/wrap.hpp>
}

14
3rdparty-modules/gsl.cpp Normal file
View File

@ -0,0 +1,14 @@
module;
#include <cstdint>
#include <cstddef>
#include <algorithm>
#include <exception>
#include <memory>
#include <ranges>
export module gsl;
export
{
#include <gsl/gsl>
}

View File

@ -10,6 +10,10 @@ endif()
include(${CMAKE_SOURCE_DIR}/cmake/PatchUtil.cmake)
include(FetchContent)
include(CheckIPOSupported)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
check_ipo_supported(RESULT ipo_supported OUTPUT error)
endif()
find_package(OpenGL)
find_package(Vulkan)
@ -22,9 +26,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux)
endif()
endif()
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) # Tells CMAKE to shut up about glad using an old CMAKE
FetchContent_Declare(glad GIT_REPOSITORY https://github.com/Dav1dde/glad.git GIT_TAG b6f6ff2c4a25cd0dfe11ea6e3dc50454677251b9 GIT_PROGRESS ON)
FetchContent_MakeAvailable(glad)
add_subdirectory(3rdparty-modules)
FetchContent_Declare(Boost
GIT_REPOSITORY https://github.com/boostorg/boost.git
@ -40,12 +42,6 @@ FetchContent_Declare(Boost
FetchContent_MakeAvailable(Boost)
FetchContent_Declare(GSL
GIT_REPOSITORY https://github.com/microsoft/GSL.git
GIT_TAG v4.0.0
GIT_PROGRESS ON)
FetchContent_MakeAvailable(GSL)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
@ -75,39 +71,11 @@ if(NOT imgui_POPULATED)
target_link_libraries(imgui ${OPENGL_LIBRARIES} glfw glad Vulkan::Vulkan)
endif()
FetchContent_Declare(glm GIT_REPOSITORY https://github.com/g-truc/glm.git GIT_TAG 0.9.9.8 GIT_PROGRESS ON)
FetchContent_MakeAvailable(glm)
FetchContent_Declare(bgfx GIT_REPOSITORY https://github.com/bkaradzic/bgfx.cmake.git GIT_TAG 2f0e950b8f0b94864b5d5bedf403ee7007d1d7a3 GIT_PROGRESS ON)
FetchContent_GetProperties(bgfx)
FetchContent_Declare(assimp GIT_REPOSITORY https://github.com/assimp/assimp.git GIT_TAG v5.3.1 GIT_PROGRESS ON)
FetchContent_MakeAvailable(assimp)
FetchContent_Declare(fast_io GIT_REPOSITORY https://github.com/cppfastio/fast_io.git GIT_TAG 804d943e30df0da782538d508da6ea6e427fc2cf GIT_PROGRESS ON)
FetchContent_GetProperties(fast_io)
if(NOT fast_io_POPULATED)
FetchContent_Populate(fast_io)
message(STATUS "Patching fast_io")
PatchUtil_Patch(
fast_io
"${CMAKE_CURRENT_SOURCE_DIR}/patches/fast_io.patch"
"${fast_io_SOURCE_DIR}"
1
_patch_result
)
if(_patch_result)
message(STATUS "Patched fast_io (or it was already patched)")
else()
message(FATAL_ERROR "Failed to patch fast_io")
endif()
add_subdirectory(${fast_io_SOURCE_DIR} ${fast_io_BINARY_DIR})
endif()
FetchContent_MakeAvailable(fast_io)
if(NOT bgfx_POPULATED)
FetchContent_Populate(bgfx)
set(BGFX_BUILD_EXAMPLES OFF CACHE BOOL "Build BGFX examples")
@ -129,8 +97,15 @@ set(IRIDIUM_SOURCES
add_library(iridium)
target_sources(iridium PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES ${IRIDIUM_SOURCES})
target_link_libraries(iridium PUBLIC imgui glfw glad Vulkan::Vulkan glm bgfx bx Boost::predef Boost::endian Microsoft.GSL::GSL assimp::assimp)
target_include_directories(iridium PUBLIC ${fast_io_SOURCE_DIR}/include)
target_link_libraries(iridium PUBLIC imgui glfw_module glad_module Vulkan::Vulkan glm_module bgfx bx Boost::predef Boost::endian GSL_module assimp::assimp fast_io_module)
target_compile_options(iridium PUBLIC -Wall -Wextra)
if( ipo_supported )
message(STATUS "IPO / LTO enabled")
# set_property(TARGET iridium PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(STATUS "IPO / LTO not supported: <${error}>")
endif()
add_subdirectory(example)

View File

@ -10,6 +10,13 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_options(iridium-example PUBLIC -g)
endif()
if( ipo_supported )
message(STATUS "IPO / LTO enabled")
# set_property(TARGET iridium-example PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(STATUS "IPO / LTO not supported: <${error}>")
endif()
add_custom_target(copy-assets ALL)
# Collect all asset files into a variable

View File

@ -1,25 +1,26 @@
#include <cstdint>
#include <ranges>
#include <map>
#include <memory>
#include <queue>
#include <ranges>
#include <set>
#include <span>
#include <tuple>
#include <vector>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <fast_io.h>
#include <fast_io_device.h>
#include <assimp/Importer.hpp>
#include <assimp/mesh.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <gsl/span>
#include <bgfx/bgfx.h>
#include <bx/bx.h>
#include <bx/math.h>
#include <bx/timer.h>
import iridium;
import fast_io;
import glm;
import glfw;
import gsl;
using namespace iridium;
@ -33,7 +34,6 @@ int windowPosX, windowPosY, windowWidth, windowHeight;
*
* @param window
*/
template <typename T>
requires std::derived_from<T, IRenderer>
std::unique_ptr<T> spawn_renderer(IWindow* window)
@ -44,8 +44,21 @@ std::unique_ptr<T> spawn_renderer(IWindow* window)
return renderer;
}
auto load_models(IRenderer* renderer, std::string scene_filename = "assets/models/suzanne.fbx")
template <typename T, typename ValueType>
concept RangeOf = std::ranges::range<T> && std::same_as<std::ranges::range_value_t<T>, ValueType>;
auto reload_meshes(IRenderer &renderer, RangeOf<std::shared_ptr<MeshResource>> auto const &meshes)
{
for(auto &mesh : meshes)
{
mesh->gpu_mesh = renderer.load_mesh(mesh->cpu_mesh);
}
}
auto load_models(IRenderer &renderer, std::string scene_filename = "assets/models/suzanne.fbx")
{
using MeshRes = std::shared_ptr<MeshResource>;
using Model = std::vector<MeshRes>;
io::native_file_loader model_file;
try
{
@ -60,28 +73,29 @@ auto load_models(IRenderer* renderer, std::string scene_filename = "assets/model
Assimp::Importer imp;
const aiScene* scene = imp.ReadFileFromMemory(model_file.data(), model_file.size(), aiProcess_ValidateDataStructure | aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_FlipWindingOrder);
using GpuModel = std::vector<std::shared_ptr<IGpuMesh>>;
std::queue<aiNode*> nodes_to_visit;
std::vector<GpuModel> models;
std::map<unsigned int, std::shared_ptr<IGpuMesh>> gpuMeshes;
std::vector<Model> models;
std::map<unsigned int, MeshRes> meshes;
auto allMeshes = gsl::span{scene->mMeshes, scene->mNumMeshes};
auto visitNode = [&renderer, &nodes_to_visit, &allMeshes, &gpuMeshes, &models](aiNode* node) {
auto visitNode = [&renderer, &nodes_to_visit, &meshes, &allMeshes, &models](aiNode* node) {
if(node->mNumMeshes > 0)
{
std::vector<std::shared_ptr<IGpuMesh>> model;
Model model;
for(auto const mesh_idx : std::span{node->mMeshes, node->mNumMeshes})
{
auto existing_mesh = gpuMeshes.find(mesh_idx);
if(existing_mesh != gpuMeshes.end())
auto existing_mesh = meshes.find(mesh_idx);
if(existing_mesh != meshes.end())
{
model.push_back(existing_mesh->second);
}
else
{
auto mesh = renderer->load_mesh(*allMeshes[mesh_idx]);
gpuMeshes[mesh_idx] = mesh;
auto mesh = std::make_shared<MeshResource>();
mesh->cpu_mesh = Mesh::from_assimp(*allMeshes[mesh_idx]);
mesh->gpu_mesh = renderer.load_mesh(mesh->cpu_mesh);
meshes[mesh_idx] = mesh;
model.push_back(mesh);
}
}
@ -101,9 +115,10 @@ auto load_models(IRenderer* renderer, std::string scene_filename = "assets/model
visitNode(nodes_to_visit.front());
nodes_to_visit.pop();
}
return std::tuple{std::move(meshes), std::move(models)};
}
void key_callback(GLFWWindow* window, std::unique_ptr<IRenderer> &renderer, Key key, int scancode, int action, int mods)
void key_callback(GLFWWindow* window, std::unique_ptr<IRenderer> &renderer, RangeOf<std::shared_ptr<MeshResource>> auto const &meshes, IRenderer::handle_t &shader, Key key, int /*scancode*/, int action, int /*mods*/)
{
if(key == GLFW_KEY_F11 && action == GLFW_PRESS)
{
@ -120,8 +135,11 @@ void key_callback(GLFWWindow* window, std::unique_ptr<IRenderer> &renderer, Key
}
if(key == Key::R && action == GLFW_PRESS)
{
// Ensure renderer is destroyed before creating a new one.
renderer.reset();
renderer = spawn_renderer<BGFXRenderer>(window);
reload_meshes(*renderer, meshes);
shader = renderer->load_shader("vs_cubes.bin", "fs_cubes.bin");
}
}
@ -133,10 +151,26 @@ static void resize_callback(std::unique_ptr<IRenderer> &renderer, glm::vec2 size
}
}
void render_shit(IRenderer &renderer, int64_t timeOffset, MeshResource const &theModelInQuestion, IRenderer::handle_t shader_handle)
{
float time = (float)((bx::getHPCounter() - timeOffset) / double(bx::getHPFrequency()));
constexpr float distance = 3.0f;
constexpr int amount = 10;
constexpr float offset = -distance * (amount / 2) + ((amount % 2 == 0) ? distance * 0.5f : 0);
for(int i = 0; i < amount; ++i)
{
glm::mat4 mtx{1.0f};
mtx = glm::translate(mtx, glm::vec3{offset + i * distance, 0.0f, 0.0f});
mtx = glm::rotate(mtx, time * (i + 1) * 2.0f, glm::vec3{0.0f, -1.0f, 0.0f});
mtx = glm::rotate(mtx, time * (2 - i) * 2.0f, glm::vec3{-1.0f, 0.0f, 0.0f});
renderer.render_mesh(theModelInQuestion.gpu_mesh, shader_handle, mtx);
}
}
int main()
{
int width = 1280;
int height = 720;
int64_t timeOffset{};
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
@ -147,12 +181,6 @@ int main()
auto window = std::make_unique<GLFWWindow>(IWindow::WindowConfig{.geometry = {{0, 0}, {800, 600}},
.monitor = -1,
.title = "Iridium Example"});
window->set_key_callback([&window, &renderer](auto &&... args) {
key_callback(window.get(), renderer, std::forward<decltype(args)>(args)...);
});
window->set_resize_callback([&renderer](auto &&... args) {
resize_callback(renderer, std::forward<decltype(args)>(args)...);
});
if(!window)
{
@ -163,19 +191,38 @@ int main()
// Initialize renderer
// TODO: Currently just BGFX
renderer = spawn_renderer<BGFXRenderer>(window.get());
auto [meshes, models] = load_models(*renderer, "assets/models/suzanne.fbx");
auto shader = renderer->load_shader("vs_cubes.bin", "fs_cubes.bin");
renderer.reset();
renderer = spawn_renderer<BGFXRenderer>(window.get());
reload_meshes(*renderer, std::views::values(meshes));
shader = renderer->load_shader("vs_cubes.bin", "fs_cubes.bin");
window->set_key_callback([&window, &renderer, &meshes, &shader](auto &&... args) {
key_callback(window.get(), renderer, std::views::values(meshes), shader, std::forward<decltype(args)>(args)...);
});
window->set_resize_callback([&renderer](auto &&... args) {
resize_callback(renderer, std::forward<decltype(args)>(args)...);
});
timeOffset = bx::getHPCounter();
while(!window->should_close())
{
if(renderer)
{
render_shit(*renderer, timeOffset, *meshes.at(0), shader);
renderer->update();
}
window->update();
}
// TODO: maybe refactor to remove explicit reset... renderer must be shut down before window is closed.
renderer.reset();
}
glfwTerminate();
println("Exiting");
return 0;
}

View File

@ -1,3 +1,17 @@
diff --git a/include/fast_io_core_impl/integers/sto/sto_contiguous.h b/include/fast_io_core_impl/integers/sto/sto_contiguous.h
index 5dc69c1..2abe897 100644
--- a/include/fast_io_core_impl/integers/sto/sto_contiguous.h
+++ b/include/fast_io_core_impl/integers/sto/sto_contiguous.h
@@ -567,9 +567,6 @@ inline constexpr parse_result<char_type const*> scan_shbase_impl(char_type const
return {first,ongoing_parse_code};
}
-template<std::integral char_type>
-inline constexpr char_type const* skip_hexdigits(char_type const* first,char_type const* last) noexcept;
-
template<char8_t base,bool shbase=false,bool skipzero=false,::std::integral char_type,my_integral T>
inline constexpr parse_result<char_type const*> scan_int_contiguous_none_space_part_define_impl(char_type const* first,char_type const* last,T& t) noexcept
{
diff --git a/include/fast_io_core_impl/literals/literal.h b/include/fast_io_core_impl/literals/literal.h
index d04aa23..f5b4283 100644
--- a/include/fast_io_core_impl/literals/literal.h

28
patches/glm.patch Normal file
View File

@ -0,0 +1,28 @@
diff --git a/glm/gtc/random.inl b/glm/gtc/random.inl
index 70485098..964a342d 100644
--- a/glm/gtc/random.inl
+++ b/glm/gtc/random.inl
@@ -11,10 +11,7 @@ namespace glm{
namespace detail
{
template <length_t L, typename T, qualifier Q>
- struct compute_rand
- {
- GLM_FUNC_QUALIFIER static vec<L, T, Q> call();
- };
+ struct compute_rand;
template <qualifier P>
struct compute_rand<1, uint8, P>
@@ -96,10 +93,7 @@ namespace detail
};
template <length_t L, typename T, qualifier Q>
- struct compute_linearRand
- {
- GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& Min, vec<L, T, Q> const& Max);
- };
+ struct compute_linearRand;
template<length_t L, qualifier Q>
struct compute_linearRand<L, int8, Q>

View File

@ -4,7 +4,6 @@ export module iridium;
// Renderer
export import :i_renderer;
export import :r_bgfx;
export import :models;
// Windowing
export import :i_window;

View File

@ -9,9 +9,11 @@ module;
export module iridium:i_renderer;
import :i_window;
import glm;
namespace
{
using handle_t = std::uint64_t;
using handle_t = std::uint32_t;
};
export namespace iridium
@ -59,57 +61,78 @@ struct Mesh
return mesh;
}
};
struct IGpuMesh
struct GpuMesh
{
handle_t vertices{};
handle_t indices{};
IGpuMesh() = default;
IGpuMesh(IGpuMesh const &) = delete;
IGpuMesh(IGpuMesh &&) = default;
IGpuMesh &operator=(IGpuMesh &) = delete;
IGpuMesh &operator=(IGpuMesh &&) = default;
virtual ~IGpuMesh() = 0;
handle_t vertices_handle{};
handle_t indices_handle{};
GpuMesh(handle_t vertices_handle, handle_t indices_handle)
: vertices_handle(vertices_handle), indices_handle(indices_handle)
{
}
GpuMesh(GpuMesh const &) = delete;
GpuMesh(GpuMesh &&) = default;
GpuMesh &operator=(GpuMesh const &) = delete;
GpuMesh &operator=(GpuMesh &&) = default;
};
struct MeshResource
{
Mesh cpu_mesh;
GpuMesh gpu_mesh = {0, 0};
};
struct GpuShader
{
handle_t vertex_shader_handle;
handle_t fragment_shader_handle;
handle_t program_handle;
};
struct shaderResource
{
std::string vertex_shader;
std::string fragment_shader;
GpuShader gpu_shader;
};
class IRenderer
{
public:
using handle_t = ::uint64_t;
using handle_t = ::handle_t;
virtual bool init_renderer(IWindow* window) = 0;
virtual std::shared_ptr<IGpuMesh> load_mesh(Mesh const &mesh) = 0;
// Shortcut for loading from assimp, calls load_mesh(Mesh const &mesh)
std::shared_ptr<IGpuMesh> load_mesh(aiMesh const &mesh);
GpuMesh load_mesh(Mesh const &mesh);
// Shortcut for loading from assimp, calls load_mesh(Mesh const &)
GpuMesh load_mesh(aiMesh const &mesh);
void unload_mesh(GpuMesh const &mesh)
{
unload_vertex_buffer(mesh.vertices_handle);
unload_index_buffer(mesh.indices_handle);
}
void unload_mesh(MeshResource const &mesh)
{
unload_mesh(mesh.gpu_mesh);
}
virtual handle_t load_vertex_buffer(const void* vertices, uint32_t size) = 0;
virtual void unload_vertex_buffer(handle_t handle) = 0;
virtual handle_t load_index_buffer(const void* indices, uint32_t size) = 0;
virtual void unload_index_buffer(handle_t handle) = 0;
virtual handle_t load_shader(const char* vsh, const char* fsh) = 0;
virtual void unload_shader(handle_t handle) = 0;
virtual void resize_frame_buffer(int width, int height) = 0;
virtual void render_mesh(GpuMesh const &mesh, handle_t ShaderProgram, glm::mat4 const &transform) = 0;
virtual void update() = 0;
virtual ~IRenderer() = default;
};
template <typename T>
class RendererImplementation : public IRenderer
{
public:
using IRenderer::load_mesh;
virtual std::shared_ptr<IGpuMesh> load_mesh(Mesh const &mesh) override
{
auto ptr = std::make_shared<typename T::GpuMeshType>();
ptr->vertices = load_vertex_buffer(mesh.vertices.data(), mesh.vertices.size() * sizeof(PosColorVertex));
ptr->indices = load_index_buffer(mesh.indices.data(), mesh.indices.size() * sizeof(std::uint16_t));
return ptr;
}
};
} // namespace iridium
// FIXME: module :private
namespace iridium
{
IGpuMesh::~IGpuMesh() = default;
std::shared_ptr<IGpuMesh> IRenderer::load_mesh(aiMesh const &mesh)
GpuMesh IRenderer::load_mesh(aiMesh const &mesh)
{
return load_mesh(Mesh::from_assimp(mesh));
}
GpuMesh IRenderer::load_mesh(Mesh const &mesh)
{
return GpuMesh{
load_vertex_buffer(mesh.vertices.data(), mesh.vertices.size() * sizeof(PosColorVertex)),
load_index_buffer(mesh.indices.data(), mesh.indices.size() * sizeof(std::uint16_t))};
}
} // namespace iridium

View File

@ -1,3 +1,2 @@
module;
export module iridium:models;
import :i_renderer;

View File

@ -1,36 +1,33 @@
module;
#include "../window/native_windowing.h"
#include <ranges>
#include "bgfx/bgfx.h"
#include "bx/math.h"
#include "bx/timer.h"
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#include <bgfx/bgfx.h>
#include <bx/math.h>
#include <bx/timer.h>
#include <bit>
#include <cstdint>
#include <cstdio>
#include <exception>
#include <format>
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <assimp/mesh.h>
#include <unordered_set>
#include <boost/predef.h>
#define GLM_FORCE_LEFT_HANDED
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
export module iridium:r_bgfx;
import :i_renderer;
import :i_window;
import :w_glfw;
import fast_io;
import glm;
import glfw;
export namespace iridium
{
/**
@ -43,18 +40,11 @@ export namespace iridium
* When a new renderer is created, all meshes must be reloaded. Don't know how this will be handled yet.
* For now, we're just hard coding the reloading of the meshes in the example. It will probably be the responsibility of the user to destroy the meshes before the renderer is destroyed unless we redesign this.
*/
struct BgfxGpuMesh : public IGpuMesh
{
~BgfxGpuMesh()
{
bgfx::destroy(static_cast<bgfx::VertexBufferHandle>(vertices));
bgfx::destroy(static_cast<bgfx::IndexBufferHandle>(indices));
}
};
class BGFXRenderer : public RendererImplementation<BGFXRenderer>
// Bgfx Renderer
class BGFXRenderer : public IRenderer
{
public:
using GpuMeshType = BgfxGpuMesh;
bool init_renderer(IWindow* iwin) override
{
@ -94,8 +84,6 @@ public:
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0);
bgfx::setViewRect(0, 0, 0, width, height);
m_timeOffset = bx::getHPCounter();
return true;
}
catch(const std::exception &e)
@ -119,74 +107,93 @@ public:
// Static data can be passed with bgfx::makeRef, but this is not static.
bgfx::copy(vertices, size),
layout);
m_vertex_buffers.insert(vbh.idx);
return vbh.idx;
}
void unload_vertex_buffer(handle_t handle) override
{
bgfx::destroy(static_cast<bgfx::VertexBufferHandle>(handle));
m_vertex_buffers.erase(handle);
}
handle_t load_index_buffer(const void* indices, uint32_t size) override
{
auto ibh = bgfx::createIndexBuffer(
// Static data can be passed with bgfx::makeRef
bgfx::copy(indices, size));
m_index_buffers.insert(ibh.idx);
return ibh.idx;
}
void unload_index_buffer(handle_t handle) override
{
bgfx::destroy(static_cast<bgfx::IndexBufferHandle>(handle));
m_index_buffers.erase(handle);
}
handle_t load_shader(const char* vsh_name, const char* fsh_name) override
{
vsh = get_shader(vsh_name);
fsh = get_shader(fsh_name);
auto vsh = get_shader(vsh_name);
auto fsh = get_shader(fsh_name);
auto program = bgfx::createProgram(vsh, fsh, true);
m_shader_programs[program.idx] = {vsh.idx, fsh.idx, program.idx};
return program.idx;
}
void unload_shader(handle_t handle) override
{
auto [vsh, fsh, program] = m_shader_programs[handle];
bgfx::destroy(static_cast<bgfx::ShaderHandle>(vsh));
bgfx::destroy(static_cast<bgfx::ShaderHandle>(fsh));
bgfx::destroy(static_cast<bgfx::ProgramHandle>(program));
m_shader_programs.erase(handle);
}
void render_mesh(GpuMesh const &mesh, handle_t shader_program, glm::mat4 const &transform) override
{
bgfx::setTransform(value_ptr(transform));
bgfx::setVertexBuffer(0, static_cast<bgfx::VertexBufferHandle>(mesh.vertices_handle));
bgfx::setIndexBuffer(static_cast<bgfx::IndexBufferHandle>(mesh.indices_handle));
bgfx::submit(0, static_cast<bgfx::ProgramHandle>(shader_program));
}
void update() override
{
float time = (float)((bx::getHPCounter() - m_timeOffset) / double(bx::getHPFrequency()));
const bx::Vec3 at = {0.0f, 0.0f, 0.0f};
const bx::Vec3 eye = {0.0f, 0.0f, -10.0f};
constexpr glm::vec3 at = {0.0f, 0.0f, 0.0f};
constexpr glm::vec3 eye = {0.0f, 0.0f, -10.0f};
glm::mat4 view = glm::lookAt(glm::vec3{eye.x, eye.y, eye.z}, glm::vec3{at.x, at.y, at.z}, glm::vec3{0.0f, 1.0f, 0.0f});
glm::mat4 proj = glm::perspective(glm::radians(90.0f), float(width) / float(height), 0.01f, 200.0f);
glm::mat4 view = glm::lookAtLH(eye, at, glm::vec3{0.0f, 1.0f, 0.0f});
glm::mat4 proj = glm::perspectiveLH(glm::radians(90.0f), float(width) / float(height), 0.01f, 200.0f);
bgfx::setViewTransform(0, value_ptr(view), value_ptr(proj));
constexpr float distance = 3.0f;
constexpr int amount = 10;
constexpr float offset = -distance * (amount / 2) + ((amount % 2 == 0) ? distance * 0.5f : 0);
for(int i = 0; i < amount; ++i)
{
glm::mat4 mtx{1.0f};
mtx = glm::translate(mtx, glm::vec3{offset + i * distance, 0.0f, 0.0f});
mtx = glm::rotate(mtx, time * (i + 1) * 2.0f, glm::vec3{0.0f, -1.0f, 0.0f});
mtx = glm::rotate(mtx, time * (2 - i) * 2.0f, glm::vec3{-1.0f, 0.0f, 0.0f});
bgfx::setTransform(value_ptr(mtx));
bgfx::setVertexBuffer(0, vbh);
bgfx::setIndexBuffer(ibh);
bgfx::submit(0, program);
}
bgfx::frame();
}
~BGFXRenderer()
{
bgfx::destroy(vbh);
bgfx::destroy(ibh);
bgfx::destroy(program);
bgfx::destroy(vsh);
bgfx::destroy(fsh);
for(auto &vbh : m_vertex_buffers)
{
bgfx::destroy(static_cast<bgfx::VertexBufferHandle>(vbh));
}
for(auto &ibh : m_index_buffers)
{
bgfx::destroy(static_cast<bgfx::IndexBufferHandle>(ibh));
}
for(auto &[vsh, fsh, program] : std::views::values(m_shader_programs))
{
bgfx::destroy(static_cast<bgfx::ShaderHandle>(vsh));
bgfx::destroy(static_cast<bgfx::ShaderHandle>(fsh));
bgfx::destroy(static_cast<bgfx::ProgramHandle>(program));
}
bgfx::shutdown();
}
private:
GLFWwindow* window;
int width, height;
int64_t m_timeOffset;
bgfx::VertexBufferHandle vbh;
bgfx::IndexBufferHandle ibh;
bgfx::ShaderHandle vsh;
bgfx::ShaderHandle fsh;
bgfx::ProgramHandle program;
std::unordered_set<handle_t> m_vertex_buffers;
std::unordered_set<handle_t> m_index_buffers;
std::map<handle_t, std::array<handle_t, 3>> m_shader_programs;
void resize_frame_buffer(int width, int height) override
{
@ -200,6 +207,7 @@ private:
bgfx::ShaderHandle get_shader(std::string_view fileName)
{
using namespace fast_io::io;
std::string_view shaderTypeName = "???";
switch(bgfx::getRendererType())
@ -230,32 +238,24 @@ private:
std::string filePath = std::format("assets/shaders/{}/{}", shaderTypeName, fileName);
printf("File path: %s\n", filePath.c_str());
FILE* file = fopen(filePath.c_str(), "rb");
if(!file)
println("File path: ", filePath);
try
{
printf("Failed to open file: %s\n", filePath.c_str());
fast_io::native_file_loader file{filePath};
const bgfx::Memory* mem = bgfx::alloc(file.size() + 1);
// fread(mem->data, 1, fileSize, file);
std::ranges::copy(file, mem->data);
mem->data[mem->size - 1] = '\0';
return bgfx::createShader(mem);
}
catch(const fast_io::error &e)
{
println("Failed to open file: ", filePath);
println("Error: ", e);
return BGFX_INVALID_HANDLE;
}
if(fseek(file, 0, SEEK_END) != 0)
{
printf("Failed to seek to end of file: %s\n", filePath.c_str());
return BGFX_INVALID_HANDLE;
}
long fileSize = ftell(file);
if(fseek(file, 0, SEEK_SET) != 0)
{
printf("Failed to seek to beginning of file: %s\n", filePath.c_str());
return BGFX_INVALID_HANDLE;
}
const bgfx::Memory* mem = bgfx::alloc(fileSize + 1);
fread(mem->data, 1, fileSize, file);
mem->data[mem->size - 1] = '\0';
fclose(file);
return bgfx::createShader(mem);
}
};
} // namespace iridium

View File

@ -1,8 +1,5 @@
module;
#include <glm/glm.hpp>
export module iridium:u_math;
import glm;
export namespace iridium::math
{

View File

@ -1,18 +1,16 @@
module;
#include "native_windowing.h"
#include <functional>
#include <string>
#include <boost/predef.h>
#include <glm/glm.hpp>
export module iridium:i_window;
import :u_math;
import :key;
import glm;
export namespace iridium
{
using namespace math;

View File

@ -1,13 +1,11 @@
#include <boost/predef.h>
#if BOOST_OS_WINDOWS
#include <windows.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#elif BOOST_OS_LINUX
#ifdef IRIDIUM_ENABLE_WAYLAND
#include <wayland-client.h>
#define GLFW_EXPOSE_NATIVE_WAYLAND
#endif
#include <X11/X.h>
#include <X11/Xlib.h>
#define GLFW_EXPOSE_NATIVE_X11
#endif

View File

@ -1,19 +1,15 @@
module;
#include <stdexcept>
#include "native_windowing.h"
#include "GLFW/glfw3.h"
#include "GLFW/glfw3native.h"
#include <glm/glm.hpp>
#include <stdexcept>
export module iridium:w_glfw;
import :i_window;
import :u_math;
import :key;
import glm;
import glfw;
export namespace iridium
{
class GLFWWindow : public IWindow
@ -43,11 +39,6 @@ public:
win->m_key_callback(static_cast<Key>(key), scancode, action, mods);
});
auto theLambda = [](GLFWwindow* window, int key, int scancode, int action, int mods) {
auto win = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
win->m_key_callback(static_cast<Key>(key), scancode, action, mods);
};
glfwMakeContextCurrent(m_window);
}