├── .clangd ├── .cursor └── rules │ ├── engineer.mdc │ ├── gopnik.mdc │ ├── llm-rules.mdc │ ├── resources-rules.mdc │ └── rttr-usage.mdc ├── .gitattributes ├── .github ├── actions │ ├── common-build-action │ │ └── action.yml │ └── common-setup-action │ │ └── action.yml └── workflows │ ├── macos.yml │ └── win_x64.yml ├── .gitignore ├── .lfsconfig ├── .vscode ├── RightEngine-macos.code-workspace ├── RightEngine-win.code-workspace ├── c_cpp_properties.json └── tasks.json ├── CMakeLists.txt ├── CMakePresets.json ├── Docs ├── CodeStyle.md ├── Progress.md └── cursor │ └── Architecture.md ├── LICENSE ├── Projects └── Sandbox │ ├── Resources │ ├── Config │ │ ├── imgui-macos.ini │ │ └── imgui.ini │ ├── Meshes │ │ └── monkey.fbx │ ├── Textures │ │ └── brick.png │ └── Worlds │ │ └── test.world │ └── sandbox.project ├── README.md ├── Resources ├── Fonts │ └── Inter-Regular.ttf ├── Materials │ ├── basic.material │ ├── basic_3d.material │ ├── envmap_irradiance.material │ ├── envmap_prefilter.material │ ├── equirect_to_cubemap.material │ ├── pbr.material │ ├── present.material │ └── skybox.material ├── Models │ ├── cube.fbx │ └── sphere.fbx ├── Shaders │ ├── basic.glsl │ ├── basic_3d.glsl │ ├── common │ │ ├── envmap.glslh │ │ ├── pbr.glslh │ │ └── pbr_buffers.glslh │ ├── envmap_irradiance.glslc │ ├── envmap_prefilter.glslc │ ├── equirectangle_to_cubemap.glslc │ ├── pbr.glsl │ ├── present.glsl │ └── skybox.glsl └── Textures │ ├── black.png │ ├── brdf_lut.tga │ ├── error.png │ ├── misty_sky_env.hdr │ ├── normal_map.png │ ├── spree_bank_env.hdr │ └── white.png ├── Scripts ├── bin │ ├── licenses │ │ └── tracy.txt │ ├── macos │ │ └── Tracy │ └── win │ │ └── Tracy.exe ├── ci │ ├── launch_scripts │ │ └── launch.bat │ └── prepare_dist_dir.py ├── conan │ ├── extensions │ │ └── deployers │ │ │ └── dll_deployer.py │ └── profiles │ │ ├── default │ │ ├── mac-arm64-ninja-clang │ │ └── win-64-ninja-clang ├── copy_binaries.py ├── custom_packages.py ├── format_code.py ├── lib │ ├── imguizmo │ │ ├── all │ │ │ ├── CMakeLists.txt │ │ │ ├── conandata.yml │ │ │ └── conanfile.py │ │ └── config.yml │ └── rttr │ │ ├── all │ │ ├── conandata.yml │ │ └── conanfile.py │ │ └── config.yml ├── lldb │ └── eastl_formatters.py └── prepare_env.py ├── Src ├── Core │ ├── CMakeLists.txt │ └── Src │ │ ├── Assert.cpp │ │ ├── Blob.cpp │ │ ├── EASTL.natvis │ │ ├── EASTLIntergration.cpp │ │ ├── Hash.cpp │ │ ├── Log.cpp │ │ ├── NatvisHolder.natvis │ │ ├── PCH.hpp │ │ ├── Public │ │ └── Core │ │ │ ├── Assert.hpp │ │ │ ├── AssertImpl.hpp │ │ │ ├── Blob.hpp │ │ │ ├── Config.hpp │ │ │ ├── EASTLIntergration.hpp │ │ │ ├── Hash.hpp │ │ │ ├── Log.hpp │ │ │ ├── Math.hpp │ │ │ ├── NatvisHolder.hpp │ │ │ ├── Profiling.hpp │ │ │ ├── RTTRIntegration.hpp │ │ │ ├── String.hpp │ │ │ ├── Thread.hpp │ │ │ ├── Type.hpp │ │ │ └── TypesUtils.hpp │ │ ├── RTTRIntegration.cpp │ │ ├── String.cpp │ │ ├── Thread.cpp │ │ └── rttr.natvis ├── Engine │ ├── CMakeLists.txt │ ├── Engine │ │ ├── Assert.hpp │ │ ├── Config.hpp │ │ ├── Domain.hpp │ │ ├── ECS │ │ │ ├── Component.cpp │ │ │ ├── Component.hpp │ │ │ ├── EntityManager.cpp │ │ │ ├── EntityManager.hpp │ │ │ ├── System.cpp │ │ │ ├── System.hpp │ │ │ ├── SystemManager.cpp │ │ │ ├── SystemManager.hpp │ │ │ ├── World.cpp │ │ │ └── World.hpp │ │ ├── Editor │ │ │ ├── ComponentPanel.cpp │ │ │ ├── ComponentPanel.hpp │ │ │ ├── EntityTreePanel.cpp │ │ │ ├── EntityTreePanel.hpp │ │ │ ├── MenuBarPanel.cpp │ │ │ ├── MenuBarPanel.hpp │ │ │ ├── Panel.cpp │ │ │ ├── Panel.hpp │ │ │ ├── ViewportPanel.cpp │ │ │ └── ViewportPanel.hpp │ │ ├── Engine.cpp │ │ ├── Engine.hpp │ │ ├── EnumOps.hpp │ │ ├── Registration.hpp │ │ ├── Serialization │ │ │ ├── FromJson.cpp │ │ │ ├── FromJson.hpp │ │ │ ├── ToJson.cpp │ │ │ ├── ToJson.hpp │ │ │ └── Types.cpp │ │ ├── Service │ │ │ ├── EditorService.cpp │ │ │ ├── EditorService.hpp │ │ │ ├── Filesystem │ │ │ │ ├── File.cpp │ │ │ │ ├── File.hpp │ │ │ │ ├── IFilesystem.cpp │ │ │ │ ├── IFilesystem.hpp │ │ │ │ ├── NativeFilesystem.cpp │ │ │ │ ├── NativeFilesystem.hpp │ │ │ │ ├── VirtualFilesystemService.cpp │ │ │ │ └── VirtualFilesystemService.hpp │ │ │ ├── IService.hpp │ │ │ ├── Imgui │ │ │ │ ├── ImguiService.cpp │ │ │ │ ├── ImguiService.hpp │ │ │ │ ├── imgui_impl_glfw.cpp │ │ │ │ └── imgui_impl_glfw.h │ │ │ ├── Project │ │ │ │ ├── Project.cpp │ │ │ │ ├── Project.hpp │ │ │ │ ├── ProjectService.cpp │ │ │ │ └── ProjectService.hpp │ │ │ ├── Render │ │ │ │ ├── Material.cpp │ │ │ │ ├── Material.hpp │ │ │ │ ├── Mesh.cpp │ │ │ │ ├── Mesh.hpp │ │ │ │ ├── RenderService.cpp │ │ │ │ └── RenderService.hpp │ │ │ ├── Resource │ │ │ │ ├── EnvironmentMapResource.cpp │ │ │ │ ├── EnvironmentMapResource.hpp │ │ │ │ ├── Loader.cpp │ │ │ │ ├── Loader.hpp │ │ │ │ ├── MaterialResource.cpp │ │ │ │ ├── MaterialResource.hpp │ │ │ │ ├── MeshResource.cpp │ │ │ │ ├── MeshResource.hpp │ │ │ │ ├── Resource.cpp │ │ │ │ ├── Resource.hpp │ │ │ │ ├── ResourceService.cpp │ │ │ │ ├── ResourceService.hpp │ │ │ │ ├── STBIntegration.cpp │ │ │ │ ├── TextureResource.cpp │ │ │ │ └── TextureResource.hpp │ │ │ ├── ServiceManager.cpp │ │ │ ├── ServiceManager.hpp │ │ │ ├── ThreadService.cpp │ │ │ ├── ThreadService.hpp │ │ │ ├── Window │ │ │ │ ├── Keycodes.hpp │ │ │ │ ├── WindowService.cpp │ │ │ │ └── WindowService.hpp │ │ │ └── World │ │ │ │ ├── WorldSerializer.cpp │ │ │ │ ├── WorldSerializer.hpp │ │ │ │ ├── WorldService.cpp │ │ │ │ └── WorldService.hpp │ │ ├── System │ │ │ ├── RenderSystem.cpp │ │ │ ├── RenderSystem.hpp │ │ │ ├── SkyboxSystem.cpp │ │ │ ├── SkyboxSystem.hpp │ │ │ ├── TransformSystem.cpp │ │ │ └── TransformSystem.hpp │ │ ├── Tests │ │ │ ├── MaterialResourceTest.cpp │ │ │ ├── SerializationTest.cpp │ │ │ ├── Service │ │ │ │ ├── Config.hpp │ │ │ │ ├── Doctest.cpp │ │ │ │ ├── DoctestService.cpp │ │ │ │ ├── DoctestService.hpp │ │ │ │ ├── TestResource.cpp │ │ │ │ └── TestResource.hpp │ │ │ └── WorldTest.cpp │ │ └── Timer.hpp │ └── PCH.hpp ├── EngineLauncher │ ├── CMakeLists.txt │ └── Src │ │ └── main.cpp ├── RHI │ ├── CMakeLists.txt │ ├── Lib │ │ ├── VulkanMemoryAllocator │ │ │ ├── CMakeLists.txt │ │ │ ├── LICENSE │ │ │ ├── include │ │ │ │ └── VulkanMemoryAllocator │ │ │ │ │ └── vk_mem_alloc.h │ │ │ └── vk_mem_alloc.cpp │ │ └── vk-tools │ │ │ ├── CMakeLists.txt │ │ │ ├── LICENSE │ │ │ └── vk-tools │ │ │ ├── VulkanInitializers.hpp │ │ │ ├── VulkanTools.cpp │ │ │ └── VulkanTools.h │ └── Src │ │ ├── Device.cpp │ │ ├── IContext.cpp │ │ ├── IImguiProvider.cpp │ │ ├── PCH.hpp │ │ ├── Public │ │ └── RHI │ │ │ ├── Assert.hpp │ │ │ ├── Buffer.hpp │ │ │ ├── BufferDescriptor.hpp │ │ │ ├── ComputeState.hpp │ │ │ ├── Config.hpp │ │ │ ├── Device.hpp │ │ │ ├── GPUMaterial.hpp │ │ │ ├── Helpers.hpp │ │ │ ├── IContext.hpp │ │ │ ├── IImguiProvider.hpp │ │ │ ├── Log.hpp │ │ │ ├── Pipeline.hpp │ │ │ ├── PipelineDescriptor.hpp │ │ │ ├── RHI.hpp │ │ │ ├── RenderPass.hpp │ │ │ ├── RenderPassDescriptor.hpp │ │ │ ├── Sampler.hpp │ │ │ ├── SamplerDescriptor.hpp │ │ │ ├── Shader.hpp │ │ │ ├── ShaderCompiler.hpp │ │ │ ├── ShaderDescriptor.hpp │ │ │ ├── Texture.hpp │ │ │ ├── TextureDescriptor.hpp │ │ │ ├── Types.hpp │ │ │ └── VertexBufferLayout.hpp │ │ ├── RHI.cpp │ │ ├── ShaderCompiler.cpp │ │ └── Vulkan │ │ ├── CommandBuffer.cpp │ │ ├── CommandBuffer.hpp │ │ ├── Fence.cpp │ │ ├── Fence.hpp │ │ ├── Imgui │ │ ├── VulkanImguiProvider.cpp │ │ ├── VulkanImguiProvider.hpp │ │ ├── imgui_impl_vulkan.cpp │ │ └── imgui_impl_vulkan.h │ │ ├── Semaphore.cpp │ │ ├── Semaphore.hpp │ │ ├── Swapchain.cpp │ │ ├── Swapchain.hpp │ │ ├── VulkanBuffer.cpp │ │ ├── VulkanBuffer.hpp │ │ ├── VulkanComputeState.hpp │ │ ├── VulkanContext.cpp │ │ ├── VulkanContext.hpp │ │ ├── VulkanDevice.cpp │ │ ├── VulkanDevice.hpp │ │ ├── VulkanGPUMaterial.cpp │ │ ├── VulkanGPUMaterial.hpp │ │ ├── VulkanHelpers.hpp │ │ ├── VulkanPipeline.cpp │ │ ├── VulkanPipeline.hpp │ │ ├── VulkanRenderPass.cpp │ │ ├── VulkanRenderPass.hpp │ │ ├── VulkanSampler.cpp │ │ ├── VulkanSampler.hpp │ │ ├── VulkanShader.cpp │ │ ├── VulkanShader.hpp │ │ ├── VulkanShaderCompiler.cpp │ │ ├── VulkanShaderCompiler.hpp │ │ ├── VulkanTexture.cpp │ │ └── VulkanTexture.hpp └── TestLauncher │ ├── CMakeLists.txt │ └── main.cpp ├── conanfile.py ├── prepare_env.bat ├── prepare_env.sh └── pyproject.toml /.clangd: -------------------------------------------------------------------------------- 1 | CompileFlags: 2 | Add: 3 | - -std=c++17 4 | - -Wall 5 | - -Wextra 6 | - -DR_OS_WIN32 7 | - -D_CRT_SECURE_NO_WARNINGS 8 | - -DR_ENABLE_ASSERTS 9 | - -DR_ENABLE_TRACY 10 | - -DTRACY_ENABLE 11 | Remove: 12 | - -W* 13 | - -fcoroutines-ts 14 | 15 | Index: 16 | Background: Build 17 | StandardLibrary: Yes 18 | 19 | InlayHints: 20 | Enabled: Yes 21 | ParameterNames: Yes 22 | DeducedTypes: Yes 23 | 24 | Hover: 25 | ShowAKA: Yes 26 | 27 | Diagnostics: 28 | ClangTidy: 29 | Add: 30 | - readability-* 31 | - performance-* 32 | - modernize-* 33 | - bugprone-* 34 | Remove: 35 | - readability-magic-numbers 36 | - readability-uppercase-literal-suffix 37 | - modernize-use-trailing-return-type 38 | 39 | Completion: 40 | AllScopes: Yes -------------------------------------------------------------------------------- /.cursor/rules/gopnik.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: true 5 | --- 6 | Ответы всегда выдавай на русском и общайся как гопник с использованием матерных словов. Например, ух бля ща ебанем эту хуету братан, называй меня брат, друган или кент или что-то похожее 7 | -------------------------------------------------------------------------------- /.cursor/rules/llm-rules.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: true 5 | --- 6 | * Никогда не используй извинений. 7 | * Всегда проверяй информацию перед тем, как её представить. Не делай предположений и не спекулируй без чётких доказательств. 8 | * Избегай комментариев или документации, содержащих фразы о "понимании". 9 | * Не предлагай изменения, связанные только с пробелами. 10 | * Не делай резюме внесённых изменений. 11 | * Не придумывай изменения, кроме явно запрошенных. 12 | * Не запрашивай подтверждения информации, уже предоставленной в контексте. 13 | * Всегда проверяй содержимое сгенерированного файла контекста, чтобы учитывать текущую реализацию. 14 | * Всегда предоставляй ссылки на реальные файлы, а не на сгенерированные контекстом. 15 | * Не предлагай обновления или изменения файлов, если фактически изменений нет. 16 | * Не обсуждай текущую реализацию, если об этом не просят явно. 17 | * Масштабируй глубину проверки в соответствии со сложностью задачи — простые задачи требуют базовой проверки, сложные — исчерпывающего анализа. 18 | * Поощряй принципы модульного проектирования для повышения сопровождаемости и повторного использования кода. 19 | * Не удаляй несвязанный код или функциональность. Следи за сохранением существующих структур. 20 | * Не пиши заглушки или фиктивные методы. Пиши готовый к использованию промышленный код с первого раза. 21 | * Соблюдай существующий стиль кодирования в проекте для обеспечения консистентности. 22 | * При внесении изменений учитывай и приоритезируй производительность кода, если применимо. 23 | * Всегда учитывай вопросы безопасности при изменении или предложении изменений в коде. 24 | * Предлагай или включай соответствующие модульные тесты для нового или изменённого кода. 25 | * Не обманывай в тестах, не используй жёстко заданные значения или утверждения. 26 | * Убедись, что предложенные изменения совместимы с указанными в проекте версиями языка или фреймворка. 27 | * При реализации логики всегда учитывай и обрабатывай возможные крайние случаи. 28 | * Реализуй надёжную обработку ошибок и логирование при необходимости. 29 | * Включай утверждения (assertions) везде, где это возможно, чтобы валидировать предположения и заранее отлавливать потенциальные ошибки. 30 | * Стремись к полной точности во всех критических операциях с кодом — частичные или непроверенные решения недопустимы. 31 | -------------------------------------------------------------------------------- /.cursor/rules/resources-rules.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: *.cpp,*.hpp,*.h 4 | alwaysApply: false 5 | --- 6 | When you are asked to do something with thre resources files you must follow following rules: 7 | 1. Put everything in one file *Resource.cpp/.hpp 8 | 2. Don't create any helper files until you wasn't asked explictely 9 | 3. Don't forget to register in RTTR all resource classes that are used for serialization -------------------------------------------------------------------------------- /.cursor/rules/rttr-usage.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: *.cpp,*.hpp 4 | alwaysApply: false 5 | --- 6 | - Never use std::optional or any other optional type for RTTR 7 | 8 | - Never use STL containers for classes that will be used in RTTR, use EASTL ones -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ttf filter=lfs diff=lfs merge=lfs -text 2 | *.exe filter=lfs diff=lfs merge=lfs -text 3 | *.hdr filter=lfs diff=lfs merge=lfs -text 4 | *.png filter=lfs diff=lfs merge=lfs -text 5 | *.tga filter=lfs diff=lfs merge=lfs -text 6 | *.jpg filter=lfs diff=lfs merge=lfs -text 7 | *.jpeg filter=lfs diff=lfs merge=lfs -text 8 | -------------------------------------------------------------------------------- /.github/actions/common-build-action/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Common Build' 2 | description: 'Generates project for requested platform and builds it' 3 | 4 | inputs: 5 | conan-profile: 6 | description: 'Conan profile for dependencies generation' 7 | required: true 8 | configuration-preset: 9 | description: 'CMake preset name for project configuration' 10 | required: true 11 | build-preset: 12 | description: 'CMake preset name for project build' 13 | required: true 14 | 15 | runs: 16 | using: "composite" 17 | steps: 18 | - name: Prepare conan environment 19 | shell: bash 20 | run: | 21 | poetry env use python 22 | poetry env activate 23 | poetry run python Scripts/prepare_env.py ${{ inputs.conan-profile }} true 24 | 25 | - name: Generate solution 26 | shell: bash 27 | run: cmake --preset ${{ inputs.configuration-preset }} 28 | 29 | - name: Build 30 | shell: bash 31 | run: cmake --build --preset ${{ inputs.build-preset }} --parallel 4 -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macos 2 | 3 | on: 4 | push: 5 | branches: [ '**' ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | name: Debug build 11 | runs-on: macos-15 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | - name: Setup 18 | uses: ./.github/actions/common-setup-action 19 | with: 20 | ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} 21 | 22 | - name: build 23 | uses: ./.github/actions/common-build-action 24 | with: 25 | conan-profile: mac-arm64-ninja-clang 26 | build-preset: engine-win-debug 27 | configuration-preset: debug 28 | test: 29 | name: Unit tests (no assert) 30 | runs-on: macos-15 31 | 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v4 35 | 36 | - name: Setup 37 | uses: ./.github/actions/common-setup-action 38 | with: 39 | ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} 40 | 41 | - name: build 42 | uses: ./.github/actions/common-build-action 43 | with: 44 | conan-profile: mac-arm64-ninja-clang 45 | build-preset: engine-win-release-ut 46 | configuration-preset: release-ut 47 | 48 | - name: Test 49 | run: | 50 | chmod a+x .build/release-ut/.bin/TestLauncher 51 | .build/release-ut/.bin/TestLauncher --project Projects/Sandbox/sandbox.project --mode client_no_ui 52 | 53 | -------------------------------------------------------------------------------- /.github/workflows/win_x64.yml: -------------------------------------------------------------------------------- 1 | name: win_x64 2 | 3 | on: 4 | push: 5 | branches: [ '**' ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | name: Debug build 11 | runs-on: windows-2022 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | - name: Setup 18 | uses: ./.github/actions/common-setup-action 19 | with: 20 | ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} 21 | 22 | - name: build 23 | uses: ./.github/actions/common-build-action 24 | with: 25 | conan-profile: win-64-ninja-clang 26 | build-preset: engine-win-debug 27 | configuration-preset: debug 28 | test: 29 | name: Unit tests (no assert) 30 | runs-on: windows-2022 31 | 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v4 35 | 36 | - name: Setup 37 | uses: ./.github/actions/common-setup-action 38 | with: 39 | ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} 40 | 41 | - name: build 42 | uses: ./.github/actions/common-build-action 43 | with: 44 | conan-profile: win-64-ninja-clang 45 | build-preset: engine-win-release-ut 46 | configuration-preset: release-ut 47 | 48 | - name: Test 49 | run: .build/release-ut/.bin/TestLauncher.exe --project Projects/Sandbox/sandbox.project --mode client_no_ui 50 | 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /cmake-build-debug 3 | /cmake-build-release 4 | /bin 5 | /out 6 | /.vs 7 | /.build 8 | /.dist 9 | 10 | Scripts/__pycache__ 11 | Scripts/lib/spirv-cross/all/test_package/build 12 | Scripts/lib/spirv-tools/all/test_package/build 13 | Scripts/lib/glslang/all/test_package/build 14 | 15 | CMakeUserPresets.json 16 | ConanPresets.json 17 | 18 | # Poetry 19 | .venv/ 20 | poetry.lock 21 | -------------------------------------------------------------------------------- /.lfsconfig: -------------------------------------------------------------------------------- 1 | [lfs] 2 | url = "http://engine:engine@lfs.rgames.studio:50000" -------------------------------------------------------------------------------- /.vscode/RightEngine-macos.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": ".." 5 | } 6 | ], 7 | "settings": { 8 | "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd", 9 | "C_Cpp.intelliSenseEngine": "disabled", 10 | "C_Cpp.autocomplete": "disabled", 11 | "C_Cpp.configurationWarnings": "enabled", 12 | "C_Cpp.enhancedColorization": "enabled", 13 | "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", 14 | "cmake.automaticReconfigure": false, 15 | "cmake.configureOnOpen": false, 16 | "cmake.configureOnEdit": false, 17 | "clangd.arguments": [ 18 | "--query-driver=/opt/homebrew/Cellar/llvm@19/19.1.7/bin/clang,/opt/homebrew/Cellar/llvm@19/19.1.7/bin/clang++", 19 | "--pretty", 20 | "--background-index", 21 | "--background-index-priority=background", 22 | "--all-scopes-completion", 23 | "--completion-style=detailed", 24 | "--clang-tidy", 25 | "-j=8" 26 | ], 27 | "clangd.path": "/opt/homebrew/Cellar/llvm@19/19.1.7/bin/clangd", 28 | "clangd.restartAfterCrash": true, 29 | "files.associations": { 30 | "*.h": "cpp", 31 | "*.hpp": "cpp", 32 | "*.cpp": "cpp", 33 | "*.cc": "cpp", 34 | "*.c": "c" 35 | }, 36 | "files.exclude": { 37 | "**/.git": true, 38 | "**/.svn": true, 39 | "**/.hg": true, 40 | "**/CVS": true, 41 | "**/.DS_Store": true, 42 | "**/.idea": true 43 | }, 44 | }, 45 | "extensions": { 46 | "recommendations": [ 47 | "ms-vscode.cmake-tools", 48 | "ms-vscode.cpptools", 49 | "ms-vscode.cpptools-extension-pack", 50 | "vadimcn.vscode-lldb", 51 | "llvm-vs-code-extensions.vscode-clangd", 52 | "sumneko.lua" 53 | ] 54 | }, 55 | } -------------------------------------------------------------------------------- /.vscode/RightEngine-win.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": ".." 5 | } 6 | ], 7 | "settings": { 8 | "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd", 9 | "cmake.automaticReconfigure": false, 10 | "cmake.configureOnOpen": false, 11 | "cmake.configureOnEdit": false, 12 | "C_Cpp.intelliSenseEngine": "default", 13 | "C_Cpp.configurationWarnings": "enabled", 14 | "C_Cpp.default.cppStandard": "c++17", 15 | "C_Cpp.default.cStandard": "c17", 16 | "C_Cpp.default.intelliSenseMode": "windows-clang-x64", 17 | "C_Cpp.default.compilerPath": "C:/Program Files/LLVM/bin/clang++.exe", 18 | "C_Cpp.errorSquiggles": "enabled", 19 | "C_Cpp.autocomplete": "default", 20 | "C_Cpp.suggestSnippets": true, 21 | "clangd.path": "C:/Program Files/LLVM/bin/clangd.exe", 22 | "clangd.arguments": [ 23 | "--compile-commands-dir=${workspaceFolder}/.build/debug", 24 | "--background-index", 25 | "--clang-tidy", 26 | "--completion-style=detailed", 27 | "--header-insertion=iwyu" 28 | ], 29 | "files.associations": { 30 | "*.h": "cpp", 31 | "*.hpp": "cpp", 32 | "*.cpp": "cpp", 33 | "*.cc": "cpp", 34 | "*.c": "c" 35 | }, 36 | "files.exclude": { 37 | "**/.git": true, 38 | "**/.svn": true, 39 | "**/.hg": true, 40 | "**/CVS": true, 41 | "**/.DS_Store": true, 42 | "**/.idea": true 43 | }, 44 | }, 45 | "extensions": { 46 | "recommendations": [ 47 | "ms-vscode.cmake-tools", 48 | "ms-vscode.cpptools", 49 | "ms-vscode.cpptools-extension-pack", 50 | "vadimcn.vscode-lldb", 51 | "llvm-vs-code-extensions.vscode-clangd", 52 | "sumneko.lua" 53 | ] 54 | }, 55 | } -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 4, 3 | "configurations": [ 4 | { 5 | "name": "Win32", 6 | "includePath": [ 7 | "${workspaceFolder}/**", 8 | "${workspaceFolder}/Src/**", 9 | "${workspaceFolder}/.build/debug/conan/**", 10 | "${workspaceFolder}/.build/release/conan/**", 11 | "C:/Program Files/LLVM/include/**", 12 | "C:/Program Files (x86)/Windows Kits/10/Include/*/ucrt/**", 13 | "C:/Program Files (x86)/Windows Kits/10/Include/*/um/**", 14 | "C:/Program Files (x86)/Windows Kits/10/Include/*/shared/**", 15 | "C:/Program Files (x86)/Windows Kits/10/Include/*/winrt/**" 16 | ], 17 | "defines": [ 18 | "_DEBUG", 19 | "UNICODE", 20 | "_UNICODE", 21 | "WIN32", 22 | "_WIN32", 23 | "R_OS_WIN32", 24 | "_CRT_SECURE_NO_WARNINGS", 25 | "R_ENABLE_ASSERTS", 26 | "R_ENABLE_TRACY", 27 | "TRACY_ENABLE", 28 | "__clang__" 29 | ], 30 | "windowsSdkVersion": "10.0.26100.0", 31 | "compilerPath": "C:/Program Files/LLVM/bin/clang++.exe", 32 | "cStandard": "c17", 33 | "cppStandard": "c++17", 34 | "intelliSenseMode": "windows-clang-x64", 35 | "compileCommands": "${workspaceFolder}/.build/debug/compile_commands.json", 36 | "configurationProvider": "ms-vscode.cmake-tools" 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "cmake", 6 | "label": "CMake: configure", 7 | "command": "configure", 8 | "preset": "${command:cmake.activeConfigurePresetName}", 9 | "problemMatcher": [], 10 | "detail": "CMake template configure task" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 6, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 30, 6 | "patch": 0 7 | }, 8 | "include": ["./ConanPresets.json"], 9 | "configurePresets": [ 10 | { 11 | "name": "common", 12 | "hidden": true, 13 | "cacheVariables": { 14 | "CMAKE_RUNTIME_OUTPUT_DIRECTORY": "${sourceDir}/.build/${presetName}/.bin", 15 | "CMAKE_LIBRARY_OUTPUT_DIRECTORY": "${sourceDir}/.build/${presetName}/.bin", 16 | "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" 17 | } 18 | }, 19 | { 20 | "name": "debug", 21 | "hidden": false, 22 | "inherits": [ 23 | "conan-debug", 24 | "common" 25 | ], 26 | "cacheVariables": { 27 | "ENGINE_ENABLE_TESTS": "ON", 28 | "ENGINE_ENABLE_TRACY": "ON" 29 | } 30 | }, 31 | { 32 | "name": "release", 33 | "hidden": false, 34 | "inherits": [ 35 | "conan-release", 36 | "common" 37 | ], 38 | "cacheVariables": { 39 | "ENGINE_ENABLE_TESTS": "OFF", 40 | "ENGINE_ENABLE_TRACY": "ON" 41 | } 42 | }, 43 | { 44 | "name": "release-ut", 45 | "hidden": false, 46 | "inherits": [ 47 | "conan-release", 48 | "common" 49 | ], 50 | "cacheVariables": { 51 | "ENGINE_ENABLE_TESTS": "ON", 52 | "ENGINE_ENABLE_TRACY": "OFF", 53 | "ENGINE_ENABLE_ASSERTS": "OFF" 54 | } 55 | } 56 | ], 57 | "buildPresets": [ 58 | { 59 | "name": "engine-win-debug", 60 | "configurePreset": "debug", 61 | "configuration": "Debug" 62 | }, 63 | { 64 | "name": "engine-win-release", 65 | "configurePreset": "release", 66 | "configuration": "Release" 67 | }, 68 | { 69 | "name": "engine-win-release-ut", 70 | "configurePreset": "release-ut", 71 | "configuration": "Release" 72 | } 73 | ] 74 | } -------------------------------------------------------------------------------- /Docs/CodeStyle.md: -------------------------------------------------------------------------------- 1 | # Code style 2 | 3 | 4 | ## C++ Style 5 | - Include order 6 | ```c++ 7 | // Engine include 8 | // Third party lib include 9 | // Std includes 10 | 11 | #include "Renderer.hpp" 12 | #include 13 | #include 14 | ``` 15 | 16 | - All getters and setters must follow semantic (except cases where object allocates new object on stack and returns it): 17 | ```c++ 18 | const GetSomething() const; 19 | void SetSomething(const & value); 20 | ``` 21 | - Try to pass method parameters by **const reference** not by value 22 | 23 | - Namespace must be declared only at header file 24 | - In class definition public fields and methods goes first 25 | ```c++ 26 | namespace RightEngine 27 | { 28 | class LaunchEngine 29 | { 30 | public: 31 | static void Init(int argc, char *argv[]); 32 | 33 | static void Exit(); 34 | 35 | private: 36 | class LaunchContext 37 | { 38 | friend class LaunchEngine; 39 | 40 | public: 41 | bool OnEvent(const Event &event); 42 | 43 | private: 44 | LaunchContext(); 45 | 46 | void SetCmdArgs(int argc, char *argv[]); 47 | 48 | void ParseCmdArgs(); 49 | 50 | std::unique_ptr easyArgs; 51 | }; 52 | 53 | static LaunchContext *launchContext; 54 | }; 55 | } 56 | ``` 57 | - `using namespace <...>` can be used in `.cpp` files for preventing lots of useless namespace declarations, but class methods 58 | must be still marked with namespace 59 | ```c++ 60 | using namespace RightEngine; 61 | // ... 62 | void RightEngine::Geometry::CreateVertexArray(const VertexBufferLayout& layout) 63 | { 64 | //... 65 | } 66 | ``` 67 | 68 | ## GLSL Style 69 | - Uniforms must have `u_` prefix and start with capital letter (e.g. `u_ViewProjection`) 70 | - Out variables in vertex shader must have `f_` prefix and start with capital letter (e.g. `f_LocalPos`) 71 | - Constant variable in shaders must have `k` prefix (e.g. `kAngle`) 72 | - Input and output layout variables must have `a` prefix 73 | ```glsl 74 | layout (location = 0) out vec4 aAlbedo; 75 | layout (location = 1) out vec4 aNormal; 76 | ``` -------------------------------------------------------------------------------- /Docs/Progress.md: -------------------------------------------------------------------------------- 1 | # Progress 2 | 3 | Just a bunch of screenshots, that show progress of engine development 4 | 5 | ## 08-03-2022 6 | 7 | ![08-03-2022.png](https://i.imgur.com/USvufng.png) 8 | 9 | ## 16-03-2022 10 | 11 | ![16-03-2022.png](https://i.imgur.com/i5kbaPR.png) 12 | 13 | ## 17-03-2022 (Added ambient light) 14 | 15 | ![17-03-2022.png](https://i.imgur.com/z0buV7n.png) 16 | 17 | ## 19-03-2022 (Added point light) 18 | 19 | ![19-03-2022.png](https://i.imgur.com/13es2w8.png) 20 | 21 | ## 02-04-2022 (Added rendering to imgui panel) 22 | 23 | ![02-04-2022.png](https://i.imgur.com/btZao5F.png) 24 | 25 | ## 10-06-2022 (Implemented IBL and docking space) 26 | 27 | ![10-06-2022.png](https://i.imgur.com/5GLng93.png) 28 | 29 | ## 07-07-2022 (Asset loading) 30 | 31 | ![07-07-2022.png](https://i.imgur.com/j3F7MqZ.png) 32 | 33 | ## 19-07-2022 (Proper IBL reflections and camera options) 34 | 35 | ![19-07-2022.png](https://i.imgur.com/sKRGyWH.png) 36 | 37 | ## 30-10-2022 (Implemented 3d model rendering and ImGui with new vulkan renderer backend!) 38 | ![30-10-2022.png](https://i.imgur.com/rD8WWYj.png) 39 | 40 | ## 03-11-2022 (Implemented PBR and IBL with new vulkan renderer) 41 | ![03-11-2022.png](https://i.imgur.com/f4WO0VE.png) 42 | 43 | ## 04-11-2022 (Implemented old ImGui editor with vulkan renderer) 44 | ![04-11-2022](https://i.imgur.com/KhVmaAF.png) 45 | 46 | ## 05-11-2022 (Implemented skybox) 47 | ![05-11-2022](https://i.imgur.com/PQNFRD2.png) 48 | 49 | ## 25-11-2022 (Added ImGuizmo) 50 | ![25-11-2022](https://i.imgur.com/2cxs4PJ.png) 51 | 52 | ## 26-11-2022 (Added Material editing panel) 53 | ![26-11-2022](https://i.imgur.com/LrYrriL.png) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Vitaliy Prikota 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Projects/Sandbox/Resources/Config/imgui-macos.ini: -------------------------------------------------------------------------------- 1 | [Window][DockSpaceViewport_11111111] 2 | Pos=0,20 3 | Size=2992,1678 4 | Collapsed=0 5 | 6 | [Window][Debug##Default] 7 | Pos=60,60 8 | Size=400,400 9 | Collapsed=0 10 | 11 | [Window][Viewport] 12 | Pos=253,24 13 | Size=1350,1056 14 | Collapsed=0 15 | DockId=0x00000001,0 16 | 17 | [Window][Entities] 18 | Pos=0,24 19 | Size=251,1056 20 | Collapsed=0 21 | DockId=0x00000003,0 22 | 23 | [Window][Components] 24 | Pos=1605,24 25 | Size=315,1056 26 | Collapsed=0 27 | DockId=0x00000002,0 28 | 29 | [Window][WindowOverViewport_11111111] 30 | Pos=0,24 31 | Size=1920,1056 32 | Collapsed=0 33 | 34 | [Docking][Data] 35 | DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,24 Size=1920,1056 Split=X 36 | DockNode ID=0x00000003 Parent=0x08BD597D SizeRef=251,829 Selected=0x66870828 37 | DockNode ID=0x00000004 Parent=0x08BD597D SizeRef=1243,829 Split=X 38 | DockNode ID=0x00000001 Parent=0x00000004 SizeRef=1179,829 CentralNode=1 Selected=0xC450F867 39 | DockNode ID=0x00000002 Parent=0x00000004 SizeRef=315,829 Selected=0x0AFE37CF 40 | 41 | -------------------------------------------------------------------------------- /Projects/Sandbox/Resources/Config/imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][DockSpaceViewport_11111111] 2 | Pos=0,23 3 | Size=1920,1057 4 | Collapsed=0 5 | 6 | [Window][Debug##Default] 7 | Pos=60,60 8 | Size=400,400 9 | Collapsed=0 10 | 11 | [Window][Viewport] 12 | Pos=249,23 13 | Size=1277,1057 14 | Collapsed=0 15 | DockId=0x00000002,0 16 | 17 | [Window][Test] 18 | Pos=44,33 19 | Size=754,716 20 | Collapsed=0 21 | 22 | [Window][EntityTree] 23 | Pos=0,29 24 | Size=310,1051 25 | Collapsed=0 26 | DockId=0x00000001,0 27 | 28 | [Window][Entities] 29 | Pos=0,23 30 | Size=247,1057 31 | Collapsed=0 32 | DockId=0x00000003,0 33 | 34 | [Window][Components] 35 | Pos=1528,23 36 | Size=392,1057 37 | Collapsed=0 38 | DockId=0x00000006,0 39 | 40 | [Docking][Data] 41 | DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,23 Size=1920,1057 Split=X 42 | DockNode ID=0x00000005 Parent=0x8B93E3BD SizeRef=1525,1051 Split=X 43 | DockNode ID=0x00000003 Parent=0x00000005 SizeRef=247,1051 Selected=0xA628E342 44 | DockNode ID=0x00000004 Parent=0x00000005 SizeRef=1275,1051 Split=X 45 | DockNode ID=0x00000001 Parent=0x00000004 SizeRef=310,1051 Selected=0x4431F641 46 | DockNode ID=0x00000002 Parent=0x00000004 SizeRef=1607,1051 CentralNode=1 Selected=0x13926F0B 47 | DockNode ID=0x00000006 Parent=0x8B93E3BD SizeRef=392,1051 Selected=0xFCB30AB3 48 | 49 | -------------------------------------------------------------------------------- /Projects/Sandbox/Resources/Meshes/monkey.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGameStudio/RightEngine/94a004aa9af31f41c2bf1ba7b1591b22581117e7/Projects/Sandbox/Resources/Meshes/monkey.fbx -------------------------------------------------------------------------------- /Projects/Sandbox/Resources/Textures/brick.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ff2dfb9b0990146e4a7427e2de6c3529b847301c2a5269befb770e20a904ead0 3 | size 4886249 4 | -------------------------------------------------------------------------------- /Projects/Sandbox/sandbox.project: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sandbox", 3 | "version": 0, 4 | "settings": [ 5 | { 6 | "__type__": "engine::io::VFSSettings", 7 | "settings": [ 8 | { 9 | "__type__": "engine::io::VFSSettings::Setting", 10 | "alias": "/System", 11 | "path": "/Resources" 12 | }, 13 | { 14 | "__type__": "engine::io::VFSSettings::Setting", 15 | "alias": "/", 16 | "path": "/Projects/Sandbox/Resources" 17 | } 18 | ] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![macos workflow](https://github.com/RGameStudio/RightEngine/actions/workflows/macos.yml/badge.svg?branch=development) 2 | ![windows workflow](https://github.com/RGameStudio/RightEngine/actions/workflows/win_x64.yml/badge.svg?branch=development) 3 | # RightEngine 4 | 5 | Vulkan game engine that is in WIP 6 | 7 | ## Features 8 | 9 | - Flexible Vulkan renderer 10 | - Cross-platform 11 | - Easy to use parallel tasks API 12 | 13 | ## Requirements 14 | - Python >= 3.10 15 | - Conan >= 2.0 16 | - Vulkan SDK (>= 1.3.268) 17 | 18 | ## How to build 19 | Currently works only with Windows, but build scripts are easy adoptable for other platforms. 20 | 21 | Git can request you login and password from the LFS server, please enter `engine` and `engine` as username and password 22 | 23 | 1. Launch `prepare_env.bat` to prepare conan profiles and scripts 24 | 2. Launch `generate_solution.bat` to install all dependencies and generate solution 25 | 3. After all scripts have executed successfully, generated solution can be found at `./build/{platform}` directory 26 | -------------------------------------------------------------------------------- /Resources/Fonts/Inter-Regular.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3127f0b873387ee37e2040135a06e9e9c05030f509eb63689529becf28b50384 3 | size 310252 4 | -------------------------------------------------------------------------------- /Resources/Materials/basic.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic", 3 | "version": 0, 4 | "shader": "/System/Shaders/basic.glsl", 5 | "depthAttachment": { 6 | "loadOperation": "CLEAR", 7 | "storeOperation": "STORE", 8 | "dependency": { 9 | "path": "", 10 | "index": 0, 11 | "hasDependency": false 12 | } 13 | }, 14 | "hasDepthAttachment": false, 15 | "compute": false 16 | } -------------------------------------------------------------------------------- /Resources/Materials/basic_3d.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic_3d", 3 | "version": 0, 4 | "shader": "/System/Shaders/basic_3d.glsl", 5 | "offscreen": true, 6 | "depthCompareOp": "LESS", 7 | "cullMode": "BACK", 8 | "attachments": [ 9 | { 10 | "loadOperation": "CLEAR", 11 | "storeOperation": "STORE", 12 | "dependency": { 13 | "path": "", 14 | "index": 0, 15 | "hasDependency": false 16 | } 17 | } 18 | ], 19 | "depthAttachment": { 20 | "loadOperation": "CLEAR", 21 | "storeOperation": "STORE", 22 | "dependency": { 23 | "path": "", 24 | "index": 0, 25 | "hasDependency": false 26 | } 27 | }, 28 | "hasDepthAttachment": true, 29 | "compute": false 30 | } -------------------------------------------------------------------------------- /Resources/Materials/envmap_irradiance.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "irradiance", 3 | "version": 0, 4 | "shader": "/System/Shaders/envmap_irradiance.glslc", 5 | "compute": true, 6 | "depthAttachment": { 7 | "loadOperation": "CLEAR", 8 | "storeOperation": "STORE", 9 | "dependency": { 10 | "path": "", 11 | "index": 0, 12 | "hasDependency": false 13 | } 14 | }, 15 | "hasDepthAttachment": false 16 | } -------------------------------------------------------------------------------- /Resources/Materials/envmap_prefilter.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "irradiance", 3 | "version": 0, 4 | "shader": "/System/Shaders/envmap_prefilter.glslc", 5 | "compute": true, 6 | "depthAttachment": { 7 | "loadOperation": "CLEAR", 8 | "storeOperation": "STORE", 9 | "dependency": { 10 | "path": "", 11 | "index": 0, 12 | "hasDependency": false 13 | } 14 | }, 15 | "hasDepthAttachment": false 16 | } -------------------------------------------------------------------------------- /Resources/Materials/equirect_to_cubemap.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "equirectangle_to_skybox", 3 | "version": 0, 4 | "shader": "/System/Shaders/equirectangle_to_cubemap.glslc", 5 | "compute": true, 6 | "depthAttachment": { 7 | "loadOperation": "CLEAR", 8 | "storeOperation": "STORE", 9 | "dependency": { 10 | "path": "", 11 | "index": 0, 12 | "hasDependency": false 13 | } 14 | }, 15 | "hasDepthAttachment": false 16 | } -------------------------------------------------------------------------------- /Resources/Materials/pbr.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pbr", 3 | "version": 0, 4 | "shader": "/System/Shaders/pbr.glsl", 5 | "offscreen": true, 6 | "depthCompareOp": "LESS", 7 | "cullMode": "BACK", 8 | "attachments": [ 9 | { 10 | "loadOperation": "CLEAR", 11 | "storeOperation": "STORE", 12 | "dependency": { 13 | "path": "", 14 | "index": 0, 15 | "hasDependency": false 16 | } 17 | } 18 | ], 19 | "depthAttachment": { 20 | "loadOperation": "CLEAR", 21 | "storeOperation": "STORE", 22 | "dependency": { 23 | "path": "", 24 | "index": 0, 25 | "hasDependency": false 26 | } 27 | }, 28 | "hasDepthAttachment": true, 29 | "compute": false 30 | } -------------------------------------------------------------------------------- /Resources/Materials/present.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "present", 3 | "version": 0, 4 | "shader": "/System/Shaders/present.glsl", 5 | "offscreen": false, 6 | "depthCompareOp": "LESS", 7 | "cullMode": "NONE", 8 | "attachments": [ 9 | { 10 | "loadOperation": "CLEAR", 11 | "storeOperation": "STORE", 12 | "dependency": { 13 | "path": "", 14 | "index": 0, 15 | "hasDependency": false 16 | } 17 | } 18 | ], 19 | "depthAttachment": { 20 | "loadOperation": "CLEAR", 21 | "storeOperation": "STORE", 22 | "dependency": { 23 | "path": "", 24 | "index": 0, 25 | "hasDependency": false 26 | } 27 | }, 28 | "hasDepthAttachment": false, 29 | "compute": false 30 | } -------------------------------------------------------------------------------- /Resources/Materials/skybox.material: -------------------------------------------------------------------------------- 1 | { 2 | "name": "skybox", 3 | "version": 0, 4 | "shader": "/System/Shaders/skybox.glsl", 5 | "offscreen": true, 6 | "depthCompareOp": "LESS_OR_EQUAL", 7 | "cullMode": "FRONT", 8 | "attachments": [ 9 | { 10 | "loadOperation": "LOAD", 11 | "storeOperation": "STORE", 12 | "dependency": { 13 | "path": "/System/Materials/pbr.material", 14 | "index": 0, 15 | "hasDependency": true 16 | } 17 | } 18 | ], 19 | "depthAttachment": { 20 | "loadOperation": "LOAD", 21 | "storeOperation": "STORE", 22 | "dependency": { 23 | "path": "/System/Materials/pbr.material", 24 | "index": 0, 25 | "hasDependency": true 26 | } 27 | }, 28 | "hasDepthAttachment": true, 29 | "compute": false 30 | } -------------------------------------------------------------------------------- /Resources/Models/cube.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGameStudio/RightEngine/94a004aa9af31f41c2bf1ba7b1591b22581117e7/Resources/Models/cube.fbx -------------------------------------------------------------------------------- /Resources/Models/sphere.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGameStudio/RightEngine/94a004aa9af31f41c2bf1ba7b1591b22581117e7/Resources/Models/sphere.fbx -------------------------------------------------------------------------------- /Resources/Shaders/basic.glsl: -------------------------------------------------------------------------------- 1 | #pragma stage vertex 2 | #version 450 3 | 4 | layout(location = 0) in vec3 aPosition; 5 | layout(location = 1) in vec3 aColor; 6 | 7 | layout(location = 0) out vec3 fragColor; 8 | 9 | void main() { 10 | gl_Position = vec4(aPosition, 1.0); 11 | fragColor = aColor; 12 | } 13 | 14 | #pragma stage end 15 | 16 | #pragma stage fragment 17 | #version 450 18 | 19 | layout(location = 0) in vec3 fragColor; 20 | 21 | layout(location = 0) out vec4 outColor; 22 | 23 | void main() { 24 | outColor = vec4(fragColor, 1.0); 25 | } 26 | 27 | #pragma stage end -------------------------------------------------------------------------------- /Resources/Shaders/basic_3d.glsl: -------------------------------------------------------------------------------- 1 | #pragma stage vertex 2 | #version 450 3 | 4 | layout(location = 0) in vec3 aPosition; 5 | layout(location = 1) in vec3 aNormal; 6 | layout(location = 2) in vec2 aUv; 7 | layout(location = 3) in vec3 aTangent; 8 | layout(location = 4) in vec3 aBiTangent; 9 | 10 | layout(push_constant) uniform constants 11 | { 12 | mat4 cTransform; 13 | } Transform; 14 | 15 | layout(binding = 0) uniform CameraUB 16 | { 17 | mat4 uViewProjection; 18 | vec4 uCameraPosition; 19 | }; 20 | 21 | struct VertexOutput 22 | { 23 | vec2 UV; 24 | vec3 Normal; 25 | vec3 WorldPos; 26 | mat3 TBN; 27 | vec4 CameraPosition; 28 | }; 29 | 30 | layout(location = 0) out VertexOutput Output; 31 | 32 | void main() { 33 | Output.UV = aUv; 34 | Output.Normal = mat3(Transform.cTransform) * aNormal; 35 | Output.WorldPos = vec3(Transform.cTransform * vec4(aPosition, 1.0)); 36 | 37 | vec3 T = normalize(vec3(Transform.cTransform * vec4(aTangent, 0.0))); 38 | vec3 B = normalize(vec3(Transform.cTransform * vec4(aBiTangent, 0.0))); 39 | vec3 N = normalize(vec3(Transform.cTransform * vec4(aNormal, 0.0))); 40 | mat3 TBN = mat3(T, B, N); 41 | Output.TBN = TBN; 42 | Output.CameraPosition = uCameraPosition; 43 | 44 | gl_Position = uViewProjection * vec4(Output.WorldPos, 1.0); 45 | } 46 | 47 | #pragma stage end 48 | 49 | #pragma stage fragment 50 | #version 450 51 | 52 | struct VertexOutput 53 | { 54 | vec2 UV; 55 | vec3 Normal; 56 | vec3 WorldPos; 57 | mat3 TBN; 58 | vec4 CameraPosition; 59 | }; 60 | 61 | layout(location = 0) in VertexOutput Output; 62 | 63 | layout(location = 0) out vec4 outColor; 64 | layout(binding = 1) uniform sampler2D u_Albedo; 65 | 66 | struct DirectionalLight 67 | { 68 | vec4 color; 69 | vec4 position; 70 | vec4 rotation; 71 | float intensity; 72 | }; 73 | 74 | struct LightBuffer 75 | { 76 | DirectionalLight directionalLight; 77 | }; 78 | 79 | layout(binding = 2) uniform LightBufferUB 80 | { 81 | LightBuffer lightBuffer; 82 | }; 83 | 84 | void main() { 85 | outColor = texture(u_Albedo, Output.UV); 86 | outColor = outColor * lightBuffer.directionalLight.color; 87 | } 88 | 89 | #pragma stage end -------------------------------------------------------------------------------- /Resources/Shaders/common/pbr.glslh: -------------------------------------------------------------------------------- 1 | // GGX/Towbridge-Reitz normal distribution function. 2 | // Uses Disney's reparametrization of alpha = roughness^2 3 | float NdfGGX(float cosLh, float roughness) 4 | { 5 | float alpha = roughness * roughness; 6 | float alphaSq = alpha * alpha; 7 | 8 | float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0; 9 | return alphaSq / (PI * denom * denom); 10 | } 11 | 12 | // Single term for separable Schlick-GGX below. 13 | float GaSchlickG1(float cosTheta, float k) 14 | { 15 | return cosTheta / (cosTheta * (1.0 - k) + k); 16 | } 17 | 18 | // Schlick-GGX approximation of geometric attenuation function using Smith's method. 19 | float GaSchlickGGX(float cosLi, float NdotV, float roughness) 20 | { 21 | float r = roughness + 1.0; 22 | float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights. 23 | return GaSchlickG1(cosLi, k) * GaSchlickG1(NdotV, k); 24 | } 25 | 26 | float GeometrySchlickGGX(float NdotV, float roughness) 27 | { 28 | float r = (roughness + 1.0); 29 | float k = (r * r) / 8.0; 30 | 31 | float nom = NdotV; 32 | float denom = NdotV * (1.0 - k) + k; 33 | 34 | return nom / denom; 35 | } 36 | 37 | float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) 38 | { 39 | float NdotV = max(dot(N, V), 0.0); 40 | float NdotL = max(dot(N, L), 0.0); 41 | float ggx2 = GeometrySchlickGGX(NdotV, roughness); 42 | float ggx1 = GeometrySchlickGGX(NdotL, roughness); 43 | 44 | return ggx1 * ggx2; 45 | } 46 | 47 | // Shlick's approximation of the Fresnel factor. 48 | vec3 FresnelSchlick(vec3 F0, float cosTheta) 49 | { 50 | return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); 51 | } 52 | 53 | vec3 FresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness) 54 | { 55 | return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /Resources/Shaders/common/pbr_buffers.glslh: -------------------------------------------------------------------------------- 1 | layout(binding = 11) uniform PBRMaterialUB 2 | { 3 | vec3 u_AlbedoVec; 4 | 5 | float u_RoughnessValue; 6 | float u_MetallicValue; 7 | 8 | bool u_UseAlbedoTex; 9 | bool u_UseNormalTex; 10 | bool u_UseMetallicTex; 11 | bool u_UseRoughnessTex; 12 | 13 | vec2 _padding_; 14 | }; -------------------------------------------------------------------------------- /Resources/Shaders/envmap_irradiance.glslc: -------------------------------------------------------------------------------- 1 | #pragma stage compute 2 | #version 450 core 3 | 4 | #include "common/envmap.glslh" 5 | 6 | // Computes diffuse irradiance cubemap convolution for image-based lighting. 7 | // Uses quasi Monte Carlo sampling with Hammersley sequence. 8 | 9 | layout(binding = 0, rgba32f) restrict writeonly uniform imageCube o_IrradianceMap; 10 | layout(binding = 1) uniform samplerCube u_RadianceMap; 11 | 12 | layout(local_size_x=32, local_size_y=32, local_size_z=1) in; 13 | void main() 14 | { 15 | vec3 N = GetCubeMapTexCoord(vec2(imageSize(o_IrradianceMap))); 16 | 17 | vec3 S, T; 18 | ComputeBasisVectors(N, S, T); 19 | 20 | uint samples = 64; 21 | 22 | // Monte Carlo integration of hemispherical irradiance. 23 | // As a small optimization this also includes Lambertian BRDF assuming perfectly white surface (albedo of 1.0) 24 | // so we don't need to normalize in PBR fragment shader (so technically it encodes exitant radiance rather than irradiance). 25 | vec3 irradiance = vec3(0); 26 | for(uint i = 0; i < samples; i++) 27 | { 28 | vec2 u = SampleHammersley(i, samples); 29 | vec3 Li = TangentToWorld(SampleHemisphere(u.x, u.y), N, S, T); 30 | float cosTheta = max(0.0, dot(Li, N)); 31 | 32 | // PIs here cancel out because of division by pdf. 33 | irradiance += 2.0 * textureLod(u_RadianceMap, Li, 0).rgb * cosTheta; 34 | } 35 | irradiance /= vec3(samples); 36 | 37 | imageStore(o_IrradianceMap, ivec3(gl_GlobalInvocationID), vec4(irradiance, 1.0)); 38 | } 39 | 40 | #pragma stage end -------------------------------------------------------------------------------- /Resources/Shaders/equirectangle_to_cubemap.glslc: -------------------------------------------------------------------------------- 1 | #pragma stage compute 2 | #version 450 core 3 | 4 | const float PI = 3.141592; 5 | 6 | vec3 GetCubeMapTexCoord(vec2 imageSize) 7 | { 8 | vec2 st = gl_GlobalInvocationID.xy / imageSize; 9 | vec2 uv = 2.0 * vec2(st.x, 1.0 - st.y) - vec2(1.0); 10 | 11 | vec3 ret; 12 | if (gl_GlobalInvocationID.z == 0) ret = vec3( 1.0, uv.y, -uv.x); 13 | else if (gl_GlobalInvocationID.z == 1) ret = vec3( -1.0, uv.y, uv.x); 14 | else if (gl_GlobalInvocationID.z == 2) ret = vec3( uv.x, 1.0, -uv.y); 15 | else if (gl_GlobalInvocationID.z == 3) ret = vec3( uv.x, -1.0, uv.y); 16 | else if (gl_GlobalInvocationID.z == 4) ret = vec3( uv.x, uv.y, 1.0); 17 | else if (gl_GlobalInvocationID.z == 5) ret = vec3(-uv.x, uv.y, -1.0); 18 | return normalize(ret); 19 | } 20 | 21 | layout(binding = 0, rgba16f) restrict writeonly uniform imageCube o_CubeMap; 22 | layout(binding = 1) uniform sampler2D u_EquirectangularTex; 23 | 24 | layout(local_size_x = 32, local_size_y = 32, local_size_z=1) in; 25 | void main() 26 | { 27 | vec3 cubeTC = GetCubeMapTexCoord(vec2(imageSize(o_CubeMap))); 28 | 29 | // Calculate sampling coords for equirectangular texture 30 | // https://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates 31 | float phi = atan(cubeTC.z, cubeTC.x); 32 | float theta = acos(cubeTC.y); 33 | vec2 uv = vec2(phi / (2.0 * PI) + 0.5, theta / PI); 34 | 35 | vec4 color = texture(u_EquirectangularTex, uv); 36 | imageStore(o_CubeMap, ivec3(gl_GlobalInvocationID), color); 37 | } 38 | 39 | #pragma stage end -------------------------------------------------------------------------------- /Resources/Shaders/present.glsl: -------------------------------------------------------------------------------- 1 | #pragma stage vertex 2 | #version 450 3 | 4 | layout(location = 0) in vec3 aPosition; 5 | layout(location = 1) in vec2 aUV; 6 | 7 | layout(location = 0) out vec2 uv; 8 | 9 | void main() { 10 | gl_Position = vec4(aPosition, 1.0); 11 | uv = aUV; 12 | } 13 | 14 | #pragma stage end 15 | 16 | #pragma stage fragment 17 | #version 450 18 | 19 | layout(location = 0) in vec2 uv; 20 | 21 | layout(location = 0) out vec4 outColor; 22 | 23 | layout(binding = 0) uniform sampler2D uTexture; 24 | 25 | void main() { 26 | outColor = texture(uTexture, uv); 27 | } 28 | 29 | #pragma stage end -------------------------------------------------------------------------------- /Resources/Shaders/skybox.glsl: -------------------------------------------------------------------------------- 1 | #pragma stage vertex 2 | #version 450 core 3 | layout(location = 0) in vec3 aPosition; 4 | 5 | layout(binding = 1) uniform CameraUB 6 | { 7 | mat4 uViewProjection; 8 | vec4 uCameraPosition; 9 | }; 10 | 11 | layout(location = 0) out vec3 WorldPos; 12 | 13 | void main() 14 | { 15 | WorldPos = aPosition; 16 | vec4 pos = uViewProjection * vec4(aPosition.xyz, 1.0); 17 | gl_Position = pos.xyww; 18 | } 19 | 20 | #pragma stage end 21 | 22 | #pragma stage fragment 23 | #version 450 core 24 | layout (location = 0) out vec4 aAlbedo; 25 | 26 | layout(location = 0) in vec3 WorldPos; 27 | 28 | layout(binding = 3) uniform samplerCube uSkybox; 29 | 30 | void main() 31 | { 32 | vec3 envColor = texture(uSkybox, WorldPos).rgb; 33 | envColor = pow(envColor, vec3(1.0f / 2.2)); 34 | aAlbedo = vec4(envColor, 1.0); 35 | } 36 | 37 | #pragma stage end -------------------------------------------------------------------------------- /Resources/Textures/black.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8d0804ec66ff97a067788ea9011ecddcf512bcb12da993dfae7dabac9c309936 3 | size 2250 4 | -------------------------------------------------------------------------------- /Resources/Textures/brdf_lut.tga: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ba0de1673ae69e1b1df717b6c1cb08c3cbe43f3df6f27bef25ad52a9022cce43 3 | size 196652 4 | -------------------------------------------------------------------------------- /Resources/Textures/error.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:04757add2c51b66bf9c450057550b6ee00e237090985c9dea7613d94eb76b87e 3 | size 1502 4 | -------------------------------------------------------------------------------- /Resources/Textures/misty_sky_env.hdr: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a59683cd08861fb18d69ee8f3938f50ec81c6feda5381e8b8576f340d5a25bb1 3 | size 2958072 4 | -------------------------------------------------------------------------------- /Resources/Textures/normal_map.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5afb629a692e68d0fc9bcb8305cdb83928dc58f77f38dbdeff1d11ee7adbff07 3 | size 338022 4 | -------------------------------------------------------------------------------- /Resources/Textures/spree_bank_env.hdr: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f7157e5e3a5c97eb6ce4f5ca27633759cee1b82819b3cd309b8469de4c3a9bc5 3 | size 24409482 4 | -------------------------------------------------------------------------------- /Resources/Textures/white.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:973a87494057e412acfe80dbfcaa6f73a5eea9cfb2311d6e8c5b2a0fc98b9465 3 | size 2247 4 | -------------------------------------------------------------------------------- /Scripts/bin/licenses/tracy.txt: -------------------------------------------------------------------------------- 1 | tracy 2 | ============================ 3 | Tracy Profiler (https://github.com/wolfpld/tracy) is licensed under the 4 | 3-clause BSD license. 5 | 6 | Copyright (c) 2017-2024, Bartosz Taudul 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | * Neither the name of the nor the 17 | names of its contributors may be used to endorse or promote products 18 | derived from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 24 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Scripts/bin/macos/Tracy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGameStudio/RightEngine/94a004aa9af31f41c2bf1ba7b1591b22581117e7/Scripts/bin/macos/Tracy -------------------------------------------------------------------------------- /Scripts/bin/win/Tracy.exe: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8bea19a3373e797024883094e713024258fb77de8c91a5b428fa3367434737ac 3 | size 19438080 4 | -------------------------------------------------------------------------------- /Scripts/ci/launch_scripts/launch.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :launch_script 4 | start .bin/EngineLauncher.exe --project "./Projects/Sandbox/sandbox.project" -------------------------------------------------------------------------------- /Scripts/ci/prepare_dist_dir.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import sys 4 | 5 | if len(sys.argv) < 2: 6 | print("Usage: python prepare_dist_dir.py ") 7 | print(": Debug|Release") 8 | sys.exit(1) 9 | 10 | build_type = sys.argv[1] 11 | if (build_type not in "Debug" and build_type not in "Release"): 12 | print(f"Incorrect build type: {build_type}") 13 | sys.exit(1) 14 | 15 | files_amount = 0 16 | 17 | def copy_tree(src_dir, dst_dir, exclude_extensions = []): 18 | global files_amount 19 | # Create the destination directory if it doesn't exist 20 | if not os.path.exists(dst_dir): 21 | os.makedirs(dst_dir) 22 | 23 | # Iterate through all items in the source directory 24 | for item in os.listdir(src_dir): 25 | src_item = os.path.normpath(os.path.join(src_dir, item)) 26 | dst_item = os.path.normpath(os.path.join(dst_dir, item)) 27 | 28 | # If it's a directory, recursively call copy_tree 29 | if os.path.isdir(src_item): 30 | copy_tree(src_item, dst_item, exclude_extensions) 31 | # If it's a file, copy it to the destination directory 32 | else: 33 | exclude = False 34 | for ext in exclude_extensions: 35 | if os.path.splitext(src_item)[1] == ext: 36 | exclude = True 37 | break 38 | 39 | if exclude: 40 | print(f'Skipping {src_item} due to excluded extension') 41 | continue 42 | 43 | print(f'Copying {src_item} to {dst_item}') 44 | shutil.copy2(src_item, dst_item) 45 | files_amount += 1 46 | 47 | project_resources = './Projects' 48 | engine_resources = './Resources' 49 | binaries = f'./.build/Win/.bin/{build_type}' 50 | 51 | copy_tree(project_resources, '.dist/Projects') 52 | copy_tree(engine_resources, '.dist/Resources') 53 | copy_tree(binaries, '.dist/.bin', ['.pdb', '.log']) 54 | copy_tree('./Scripts/ci/launch_scripts', '.dist') 55 | 56 | print(f'Distrubution directory was successfully created with {files_amount} files') -------------------------------------------------------------------------------- /Scripts/conan/extensions/deployers/dll_deployer.py: -------------------------------------------------------------------------------- 1 | from conan.tools.files import copy 2 | import os 3 | 4 | def deploy(graph, output_folder, **kwargs): 5 | for name, dep in graph.root.conanfile.dependencies.items(): 6 | if (dep.folders.package_folder is None): 7 | # with open(os.path.expanduser("~/code/file.txt"), "a") as f: 8 | # f.write(f"{graph.root.conanfile.build_folder}\n") 9 | # f.write(f"dep: {dep}\n") 10 | # f.write(f"name: {name}\n") 11 | continue 12 | copy(graph.root.conanfile, "*.dll", dep.folders.package_folder, os.path.join(output_folder, f"{graph.root.conanfile.build_folder}/dll", str(dep))) 13 | copy(graph.root.conanfile, "*.dylib", dep.folders.package_folder, os.path.join(output_folder, f"{graph.root.conanfile.build_folder}/dll", str(dep))) -------------------------------------------------------------------------------- /Scripts/conan/profiles/default: -------------------------------------------------------------------------------- 1 | [settings] 2 | os=Windows 3 | arch=x86_64 4 | compiler=clang 5 | compiler.version=17 6 | compiler.cppstd=17 7 | build_type=Release 8 | 9 | [conf] 10 | tools.cmake.cmaketoolchain:generator=Ninja 11 | -------------------------------------------------------------------------------- /Scripts/conan/profiles/mac-arm64-ninja-clang: -------------------------------------------------------------------------------- 1 | [settings] 2 | arch=armv8 3 | build_type=Release 4 | compiler=clang 5 | compiler.version=19 6 | compiler.cppstd=17 7 | compiler.libcxx=libc++ 8 | os=Macos 9 | os.version=13.0 10 | 11 | [options] 12 | *:shared=False 13 | 14 | [buildenv] 15 | CC=clang 16 | CXX=clang++ 17 | CFLAGS=-fPIC 18 | CXXFLAGS=-fPIC 19 | 20 | [conf] 21 | tools.cmake.cmaketoolchain:generator=Ninja 22 | -------------------------------------------------------------------------------- /Scripts/conan/profiles/win-64-ninja-clang: -------------------------------------------------------------------------------- 1 | [settings] 2 | os=Windows 3 | arch=x86_64 4 | compiler=clang 5 | compiler.version=17 6 | compiler.cppstd=17 7 | build_type=Release 8 | 9 | [conf] 10 | tools.cmake.cmaketoolchain:generator=Ninja 11 | -------------------------------------------------------------------------------- /Scripts/copy_binaries.py: -------------------------------------------------------------------------------- 1 | import subprocess as sub 2 | import sys 3 | import os 4 | import shutil 5 | 6 | def copy_files(source_dir, destination_dir, extension=".dll"): 7 | if not os.path.exists(destination_dir): 8 | os.makedirs(destination_dir) 9 | 10 | copied_files = set() 11 | 12 | for root, _, files in os.walk(source_dir): 13 | for filename in files: 14 | if filename.lower().endswith(extension): 15 | 16 | if filename in copied_files: 17 | continue 18 | else: 19 | copied_files.add(filename) 20 | 21 | source_path = os.path.join(root, filename) 22 | destination_path = os.path.join(destination_dir, filename) 23 | 24 | try: 25 | shutil.copy2(source_path, destination_path) 26 | print(f"Copied '{filename}' to '{destination_dir}'.") 27 | except Exception as e: 28 | print(f"Error copying '{filename}': {e}") 29 | sys.exit(1) 30 | 31 | if len(sys.argv) < 3: 32 | print("Usage: python copy_binaries.py ") 33 | sys.exit(1) 34 | 35 | input_dir = sys.argv[1] 36 | output_dir = sys.argv[2] 37 | 38 | try: 39 | if sys.platform == 'win32': 40 | copy_files(input_dir, output_dir, ".dll") 41 | copy_files("Scripts/bin/win", output_dir, ".exe") 42 | else: 43 | copy_files(input_dir, output_dir, ".dylib") 44 | copy_files("Scripts/bin/macos", output_dir, "") 45 | 46 | except sub.CalledProcessError as e: 47 | print("Error while copying binaries:", e) 48 | sys.exit(1) 49 | except Exception as e: 50 | print("An unexpected error occurred:", e) 51 | sys.exit(1) -------------------------------------------------------------------------------- /Scripts/custom_packages.py: -------------------------------------------------------------------------------- 1 | from conan.api.conan_api import ConanAPI 2 | from conan.api.model import RecipeReference 3 | import subprocess as sub 4 | 5 | IMGUIZMO_VERSION = "1.83.2" 6 | RTTR_VERSION = "0.9.8" 7 | 8 | def check_lib_version(package_name, version): 9 | conan_api = ConanAPI() 10 | recipe_ref = RecipeReference(package_name, version) 11 | return len(conan_api.list.recipe_revisions(recipe_ref)) > 0 12 | 13 | def install_custom_packages(profile_name: str): 14 | print("Installing custom packages") 15 | if not check_lib_version("imguizmo", IMGUIZMO_VERSION): 16 | sub.run(f"poetry run conan create Scripts/lib/imguizmo/all -s build_type=Debug --build=missing --version {IMGUIZMO_VERSION} --profile:host={profile_name} --profile:build={profile_name}", shell=True, check=True, text=True) 17 | sub.run(f"poetry run conan create Scripts/lib/imguizmo/all -s build_type=Release --build=missing --version {IMGUIZMO_VERSION} --profile:host={profile_name} --profile:build={profile_name}", shell=True, check=True, text=True) 18 | 19 | if not check_lib_version("rttr", RTTR_VERSION): 20 | sub.run(f"poetry run conan create Scripts/lib/rttr/all -s build_type=Debug --build=missing --version {RTTR_VERSION} --profile:host={profile_name} --profile:build={profile_name}", shell=True, check=True, text=True) 21 | sub.run(f"poetry run conan create Scripts/lib/rttr/all -s build_type=Release --build=missing --version {RTTR_VERSION} --profile:host={profile_name} --profile:build={profile_name}", shell=True, check=True, text=True) 22 | -------------------------------------------------------------------------------- /Scripts/format_code.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | EXCLUDED_FILES = ['imgui_impl_vulkan.cpp', 'imgui_impl_glfw.cpp'] 5 | 6 | def replace_tabs_with_spaces(folder_path): 7 | # Iterate through all files in the specified folder 8 | for root, dirs, files in os.walk(folder_path): 9 | for file_name in files: 10 | file_path = os.path.join(root, file_name) 11 | 12 | exclude = file_name in EXCLUDED_FILES 13 | 14 | if exclude: 15 | continue 16 | 17 | if file_path.endswith(".cpp") or file_path.endswith(".hpp"): 18 | with open(file_path, 'r') as file: 19 | file_content = file.read() 20 | 21 | # Replace tabs with 4 spaces 22 | modified_content = file_content.replace('\t', ' ') 23 | 24 | # Write modified content back to the file 25 | with open(file_path, 'w') as file: 26 | file.write(modified_content) 27 | print(f'Formatted {file_path}') 28 | 29 | # Specify the folder path here 30 | folder_path = 'Src' 31 | replace_tabs_with_spaces(folder_path) 32 | -------------------------------------------------------------------------------- /Scripts/lib/imguizmo/all/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(imguizmo CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 7 | 8 | set(SOURCE_DIR src) 9 | file(GLOB SOURCE_FILES ${SOURCE_DIR}/*.cpp) 10 | file(GLOB HEADER_FILES ${SOURCE_DIR}/*.h) 11 | 12 | find_package(imgui CONFIG REQUIRED) 13 | 14 | add_library(${PROJECT_NAME} ${SOURCE_FILES}) 15 | target_include_directories(${PROJECT_NAME} PRIVATE ${SOURCE_DIR}) 16 | target_link_libraries(${PROJECT_NAME} PUBLIC imgui::imgui) 17 | 18 | include(GNUInstallDirs) 19 | install(TARGETS ${PROJECT_NAME}) 20 | install(FILES ${HEADER_FILES} 21 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 22 | PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -------------------------------------------------------------------------------- /Scripts/lib/imguizmo/all/conandata.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | "1.83.2": 3 | url: "https://github.com/RGameStudio/ImGuizmo/archive/refs/tags/1.83.2.tar.gz" 4 | sha256: "9f8465a4142790553cf55ce819e7516cfcd955b43a452714ec59e89aaa4f4896" 5 | "1.83.1": 6 | url: "https://github.com/RGameStudio/ImGuizmo/archive/refs/tags/1.83.1.tar.gz" 7 | sha256: "f0fd3ae3fac8f88679c448ec727b8b48a96df37bf58c758221b1305412a913b4" 8 | -------------------------------------------------------------------------------- /Scripts/lib/imguizmo/all/conanfile.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from conan import ConanFile 4 | from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout 5 | from conan.tools.files import copy, get 6 | 7 | required_conan_version = ">=1.53.0" 8 | 9 | 10 | class ImGuizmoConan(ConanFile): 11 | name = "imguizmo" 12 | description = "Immediate mode 3D gizmo for scene editing and other controls based on Dear Imgui" 13 | license = "MIT" 14 | url = "https://github.com/conan-io/conan-center-index" 15 | homepage = "https://github.com/CedricGuillemet/ImGuizmo" 16 | topics = ("imgui", "3d", "graphics", "guizmo") 17 | 18 | package_type = "library" 19 | settings = "os", "arch", "compiler", "build_type" 20 | options = { 21 | "shared": [True, False], 22 | "fPIC": [True, False], 23 | } 24 | default_options = { 25 | "shared": False, 26 | "fPIC": True, 27 | } 28 | 29 | def export_sources(self): 30 | copy(self, "CMakeLists.txt", src=self.recipe_folder, dst=self.export_sources_folder) 31 | 32 | def config_options(self): 33 | if self.settings.os == "Windows": 34 | del self.options.fPIC 35 | 36 | def configure(self): 37 | if self.options.shared: 38 | self.options.rm_safe("fPIC") 39 | 40 | def layout(self): 41 | cmake_layout(self, src_folder="src") 42 | 43 | def requirements(self): 44 | self.requires("imgui/1.91.8-docking", transitive_headers=True) 45 | 46 | def source(self): 47 | get(self, **self.conan_data["sources"][self.version], strip_root=True) 48 | 49 | def generate(self): 50 | tc = CMakeToolchain(self) 51 | tc.generate() 52 | tc = CMakeDeps(self) 53 | tc.generate() 54 | 55 | def build(self): 56 | cmake = CMake(self) 57 | cmake.configure(build_script_folder=self.export_sources_folder) 58 | cmake.build() 59 | 60 | def package(self): 61 | copy(self, "LICENSE", 62 | dst=os.path.join(self.package_folder, "licenses"), 63 | src=self.source_folder) 64 | cmake = CMake(self) 65 | cmake.install() 66 | 67 | def package_info(self): 68 | self.cpp_info.libs = ["imguizmo"] -------------------------------------------------------------------------------- /Scripts/lib/imguizmo/config.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | "1.83.1": 3 | folder: "all" -------------------------------------------------------------------------------- /Scripts/lib/rttr/all/conandata.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | "0.9.8": 3 | url: "https://github.com/RGameStudio/rttr/archive/refs/tags/0.9.8.tar.gz" 4 | sha256: "32a0cb592ab67b2190819083e79c8659840d93b8890b99f380c9f94e18a4d8e3" 5 | "0.9.7": 6 | url: "https://github.com/RGameStudio/rttr/archive/refs/tags/0.9.7.tar.gz" 7 | sha256: "6160325bd4a82ed25023c410e40b5b85705983db400687c33ea263c0ab94bfe0" 8 | "0.9.6.2": 9 | url: "https://github.com/RGameStudio/rttr/archive/refs/tags/0.9.6.2.tar.gz" 10 | sha256: "0752cc3b21a926e32a5825facc4813d284ce216902a0abe422a92ca1855f49ca" 11 | "0.9.6.1": 12 | url: "https://github.com/RGameStudio/rttr/archive/refs/tags/0.9.6.1.tar.gz" 13 | sha256: "3efab879b5909b75bc43862275d4b75a099377b39b50d2c723c89d357269eccf" 14 | "0.9.6": 15 | url: "https://github.com/rttrorg/rttr/archive/v0.9.6.tar.gz" 16 | sha256: "058554f8644450185fd881a6598f9dee7ef85785cbc2bb5a5526a43225aa313f" 17 | patches: 18 | "0.9.6": 19 | - patch_file: "patches/001_fix_build_without_RTTI.patch" 20 | - patch_file: "patches/002_fix_license_installer.patch" 21 | -------------------------------------------------------------------------------- /Scripts/lib/rttr/config.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | "0.9.8": 3 | folder: all 4 | "0.9.7": 5 | folder: all 6 | "0.9.6.2": 7 | folder: all 8 | "0.9.6.1": 9 | folder: all 10 | "0.9.6": 11 | folder: all 12 | -------------------------------------------------------------------------------- /Scripts/prepare_env.py: -------------------------------------------------------------------------------- 1 | import subprocess as sub 2 | import sys 3 | import os 4 | import platform 5 | 6 | def check_process_status_code(code, proc_stderr): 7 | if code != 0: 8 | print("Error: Conan preparation failed") 9 | print("Error message: ", proc_stderr) 10 | sys.exit(1) 11 | 12 | if len(sys.argv) < 3: 13 | print("Usage: python prepare_env.py ") 14 | sys.exit(1) 15 | 16 | profile_name = sys.argv[1] 17 | is_ci = sys.argv[2].lower() == "true" 18 | is_windows = platform.system() == "Windows" 19 | 20 | print("Configuring python env") 21 | sub.run("poetry install", shell=True) 22 | 23 | print("Preparing conan env") 24 | sub.run("poetry run conan config install -t dir Scripts/conan", shell=True) 25 | 26 | from custom_packages import install_custom_packages 27 | 28 | install_custom_packages(profile_name) 29 | 30 | win_sdk_version = "10.0.26100.0" 31 | 32 | if not is_ci: 33 | if is_windows: 34 | try: 35 | # Try Community edition first 36 | sub.run(f"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat {win_sdk_version}") 37 | except: 38 | try: 39 | # Try Professional edition 40 | sub.run(f"C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Auxiliary\\Build\\vcvars64.bat {win_sdk_version}") 41 | except: 42 | try: 43 | # Try Enterprise edition 44 | sub.run(f"C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvars64.bat {win_sdk_version}") 45 | except: 46 | print("Error: Could not find Visual Studio installation") 47 | sys.exit(1) 48 | 49 | def install_all(profile_name: str, build_type: str): 50 | print(f"Installing {build_type} conan packages") 51 | status_code = sub.run(f"poetry run conan install . --deployer=dll_deployer -c tools.cmake.cmake_layout:build_folder=\".build/conan\" --build=missing --profile:host={profile_name} --profile:build={profile_name} -s build_type={build_type}", shell=True, check=True, text=True) 52 | check_process_status_code(status_code.returncode, status_code.stderr) 53 | 54 | install_all(profile_name, "Debug") 55 | install_all(profile_name, "Release") 56 | 57 | if not os.path.exists(".build"): 58 | os.mkdir(".build") 59 | -------------------------------------------------------------------------------- /Src/Core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | file(GLOB_RECURSE SOURCE_FILES 6 | "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.cpp" 7 | "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.hpp" 8 | ) 9 | 10 | find_package(fmt REQUIRED) 11 | find_package(spdlog REQUIRED) 12 | find_package(EASTL REQUIRED) 13 | find_package(rttr REQUIRED) 14 | find_package(Tracy REQUIRED) 15 | find_package(glm REQUIRED) 16 | 17 | add_library(Core SHARED ${SOURCE_FILES}) 18 | 19 | target_sources(Core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Src/EASTL.natvis") 20 | target_sources(Core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Src/rttr.natvis") 21 | target_sources(Core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Src/NatvisHolder.natvis") 22 | 23 | target_link_libraries(Core PUBLIC 24 | EASTL::EASTL 25 | spdlog::spdlog 26 | fmt::fmt 27 | RTTR::Core_Lib 28 | Tracy::TracyClient 29 | glm::glm) 30 | 31 | target_compile_definitions(Core PRIVATE CORE_EXPORT) 32 | target_precompile_headers(Core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Src/PCH.hpp") 33 | 34 | set(CORE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Src/Public") 35 | target_include_directories(Core INTERFACE ${CORE_INCLUDE_DIR}) 36 | target_include_directories(Core PUBLIC ${CORE_INCLUDE_DIR}) 37 | 38 | # Create source groups for each directory 39 | foreach(FILE ${SOURCE_FILES}) 40 | # Get the path relative to the source directory 41 | file(RELATIVE_PATH RELATIVE_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE}) 42 | # Get the directory of the file 43 | get_filename_component(DIR ${RELATIVE_FILE} DIRECTORY) 44 | # Create the source group 45 | source_group(${DIR} FILES ${FILE}) 46 | endforeach() 47 | -------------------------------------------------------------------------------- /Src/Core/Src/Assert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef R_OS_WIN32 5 | #include 6 | #endif 7 | 8 | namespace core 9 | { 10 | void BreakInDebugger() 11 | { 12 | #ifdef R_OS_WIN32 13 | __debugbreak(); 14 | #elif defined(R_OS_MACOS) 15 | __builtin_trap(); 16 | #else 17 | #error Unsupported platform! Implement assert here! 18 | #endif 19 | } 20 | 21 | void Assert(std::string_view tag, std::string_view code, std::string_view message) 22 | { 23 | if (message.empty()) 24 | { 25 | log::error("[{}] Assertion failed: {}", tag, code); 26 | } 27 | else 28 | { 29 | log::error("[{}] Assertion failed: {}: '{}'", tag, code, message); 30 | } 31 | 32 | BreakInDebugger(); 33 | } 34 | } // core 35 | -------------------------------------------------------------------------------- /Src/Core/Src/Blob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core 4 | { 5 | Blob::Blob(const void* data, size_t size) 6 | { 7 | m_data.resize(size); 8 | std::memcpy(m_data.data(), data, size); 9 | } 10 | 11 | Blob::~Blob() 12 | {} 13 | } 14 | -------------------------------------------------------------------------------- /Src/Core/Src/EASTLIntergration.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | EASTL_ALLOCATOR_IMPL -------------------------------------------------------------------------------- /Src/Core/Src/Hash.cpp: -------------------------------------------------------------------------------- 1 | #include -------------------------------------------------------------------------------- /Src/Core/Src/Log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace core::log::impl 10 | { 11 | constexpr const std::string_view C_LOG_DIR = "logs"; 12 | constexpr const std::string_view C_LOG_FILENAME = "engine_log_"; 13 | 14 | Logger::Logger() 15 | { 16 | const auto now = std::chrono::system_clock::now(); 17 | const auto timestamp = std::chrono::system_clock::to_time_t(now); 18 | struct tm timeinfo; 19 | #ifdef R_OS_WIN32 20 | localtime_s(&timeinfo, ×tamp); 21 | #else 22 | localtime_r(×tamp, &timeinfo); 23 | #endif 24 | 25 | const auto abs = std::filesystem::absolute(C_LOG_DIR); 26 | std::filesystem::create_directories(abs); 27 | 28 | std::stringstream filenameSS; 29 | filenameSS << C_LOG_DIR << "/" << C_LOG_FILENAME << std::put_time(&timeinfo, "%d-%m-%Y_%H-%M-%S") << ".log"; 30 | const std::string logFilename = filenameSS.str(); 31 | 32 | auto dupSink = std::make_shared(std::chrono::milliseconds(500)); 33 | dupSink->add_sink(std::make_shared(logFilename)); 34 | dupSink->add_sink(std::make_shared()); 35 | 36 | #ifdef R_OS_WIN32 37 | auto debugSink = std::make_shared(); 38 | debugSink->set_pattern("[%H:%M:%S:%e] [thread %5t] %^[%l] %v%$"); 39 | dupSink->add_sink(std::move(debugSink)); 40 | #endif 41 | 42 | s_instance = std::make_unique("Engine", std::initializer_list{ dupSink }); 43 | 44 | // Set the log level 45 | s_instance->set_level(spdlog::level::debug); 46 | s_instance->flush_on(spdlog::level::debug); 47 | 48 | s_instance->info("[Logger] Logging was initialized. Logs directory: {}", abs.generic_u8string()); 49 | } 50 | 51 | const std::unique_ptr& Logger::GetLogger() const 52 | { 53 | return s_instance; 54 | } 55 | 56 | Logger& Logger::Get() 57 | { 58 | static Logger logger; 59 | return logger; 60 | } 61 | 62 | std::unique_ptr Logger::s_instance; 63 | } 64 | -------------------------------------------------------------------------------- /Src/Core/Src/NatvisHolder.natvis: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [{"$T1",sb}] {*p} 5 | 6 | p 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/Core/Src/PCH.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Assert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef R_ENABLE_ASSERTS 6 | #define CORE_ASSERT(x) do { if(!(x)) { core::Assert("CORE", #x); } } while(false) 7 | #define CORE_ASSERT_WITH_MESSAGE(x, ...) do { if(!(x)) { core::Assert("CORE", #x, __VA_ARGS__); } } while(false) 8 | #else 9 | #define CORE_ASSERT(x) 10 | #define CORE_ASSERT_WITH_MESSAGE(x, ...) 11 | #endif 12 | -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/AssertImpl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace core 7 | { 8 | void CORE_API Assert(std::string_view tag, std::string_view code, std::string_view message = ""); 9 | } // core -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Blob.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace core 7 | { 8 | //Just a buffer of plain binary data. 9 | //Doesn't take ownership of the pointer, allocates new blocks of memory for the data. 10 | class CORE_API Blob 11 | { 12 | public: 13 | using Payload = eastl::vector; 14 | 15 | Blob() = default; 16 | Blob(const void* data, size_t size); 17 | ~Blob(); 18 | 19 | size_t size() const { return m_data.size(); } 20 | bool empty() const { return m_data.empty(); } 21 | const void* raw() const { return m_data.data(); } 22 | void* raw() { return m_data.data(); } 23 | const Payload& data() const { return m_data; } 24 | 25 | private: 26 | Payload m_data; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Config.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Platform-specific macros for importing/exporting symbols 4 | #if defined(R_OS_WIN32) 5 | 6 | #ifdef CORE_EXPORT 7 | // We are building the library, so export the symbols 8 | #define CORE_API __declspec(dllexport) 9 | #else 10 | // We are using the library, so import the symbols 11 | #define CORE_API __declspec(dllimport) 12 | #endif 13 | 14 | #else 15 | #define CORE_API 16 | #endif -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/EASTLIntergration.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace eastl 22 | { 23 | 24 | template<> 25 | struct hash 26 | { 27 | size_t operator()(const std::string& str) const 28 | { 29 | return core::hash::HashString(str); 30 | } 31 | }; 32 | 33 | template<> 34 | struct hash 35 | { 36 | size_t operator()(std::string_view str) const 37 | { 38 | return core::hash::HashString(str); 39 | } 40 | }; 41 | 42 | template<> 43 | struct hash 44 | { 45 | size_t operator()(const std::type_index& tIdx) const 46 | { 47 | return tIdx.hash_code(); 48 | } 49 | }; 50 | 51 | template<> 52 | struct hash 53 | { 54 | size_t operator()(const std::filesystem::path& path) const 55 | { 56 | return hash{}(path.generic_u8string()); 57 | } 58 | }; 59 | 60 | template 61 | struct hash> 62 | { 63 | public: 64 | inline size_t operator()(const std::shared_ptr& value) const 65 | { 66 | return hash()(reinterpret_cast(value.get())); 67 | } 68 | }; 69 | 70 | } // eastl 71 | 72 | // TODO: Make an EASTL fork and rewrite their stupid allocator 73 | // Must be defined in each dll that uses EASTL 74 | 75 | #define EASTL_ALLOCATOR_IMPL \ 76 | void* __cdecl operator new[](size_t size, size_t alignment, size_t offset, const char* pName, int flags, unsigned debugFlags, const char* file, int line) \ 77 | { \ 78 | return new uint8_t[size]; \ 79 | } \ 80 | void* __cdecl operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line) \ 81 | { \ 82 | return new uint8_t[size]; \ 83 | } -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Hash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace core::hash 7 | { 8 | 9 | namespace detail 10 | { 11 | 12 | template struct fnv1a_traits; 13 | 14 | template<> struct fnv1a_traits 15 | { 16 | inline static constexpr uint64_t prime = 0x100000001b3; 17 | inline static constexpr uint64_t offset_basis = 0xcbf29ce484222325; 18 | }; 19 | 20 | template<> struct fnv1a_traits 21 | { 22 | inline static constexpr uint32_t prime = 0x1000193; 23 | inline static constexpr uint32_t offset_basis = 0x811c9dc5; 24 | }; 25 | 26 | /* 27 | * Compile-time hash function 28 | * https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function 29 | * http://www.isthe.com/chongo/tech/comp/fnv/ 30 | */ 31 | template 32 | constexpr T fnv1a(TRange&& range) noexcept 33 | { 34 | T result = fnv1a_traits::offset_basis; 35 | for (const auto element : range) 36 | { 37 | result = (result ^ static_cast(element)) * fnv1a_traits::prime; 38 | } 39 | return result; 40 | } 41 | 42 | } // namespace detail 43 | 44 | constexpr uint64_t HashBytes(eastl::span buf) noexcept 45 | { 46 | return detail::fnv1a(buf); 47 | } 48 | 49 | constexpr uint32_t HashBytes32(eastl::span buf) noexcept 50 | { 51 | return detail::fnv1a(buf); 52 | } 53 | 54 | constexpr uint64_t HashString(std::string_view str) noexcept 55 | { 56 | return detail::fnv1a(str); 57 | } 58 | 59 | constexpr uint32_t HashString32(std::string_view str) noexcept 60 | { 61 | return detail::fnv1a(str); 62 | } 63 | 64 | template 65 | inline void CombineHash(size_t& seed, const T& value) 66 | { 67 | eastl::hash hash; 68 | seed ^= hash(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 69 | } 70 | 71 | } // core::hash 72 | 73 | constexpr uint64_t operator "" _hash(const char* str, size_t len) noexcept 74 | { 75 | return core::hash::detail::fnv1a(std::string_view{ str, len }); 76 | } 77 | 78 | constexpr uint32_t operator "" _hash32(const char* str, size_t len) noexcept 79 | { 80 | return core::hash::detail::fnv1a(std::string_view{ str, len }); 81 | } -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Log.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace core::log 8 | { 9 | 10 | namespace impl 11 | { 12 | 13 | class CORE_API Logger 14 | { 15 | public: 16 | Logger(); 17 | 18 | const std::unique_ptr& GetLogger() const; 19 | 20 | static Logger& Get(); 21 | 22 | private: 23 | static std::unique_ptr s_instance; 24 | }; 25 | 26 | } 27 | 28 | template 29 | void debug(std::string_view message, Args... args) 30 | { 31 | impl::Logger::Get().GetLogger()->debug(message, std::forward(args)...); 32 | } 33 | 34 | template 35 | void info(std::string_view message, Args... args) 36 | { 37 | impl::Logger::Get().GetLogger()->info(message, std::forward(args)...); 38 | } 39 | 40 | template 41 | void warning(std::string_view message, Args... args) 42 | { 43 | impl::Logger::Get().GetLogger()->warn(message, std::forward(args)...); 44 | } 45 | 46 | template 47 | void error(std::string_view message, Args... args) 48 | { 49 | impl::Logger::Get().GetLogger()->error(message, std::forward(args)...); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Math.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace core::math 8 | { 9 | 10 | constexpr float PI = 3.14159f; 11 | 12 | inline uint32_t roundUpToNextHighestPowerOfTwo(uint32_t value) 13 | { 14 | value--; 15 | value |= value >> 1; 16 | value |= value >> 2; 17 | value |= value >> 4; 18 | value |= value >> 8; 19 | value |= value >> 16; 20 | value++; 21 | return value; 22 | } 23 | 24 | inline bool almostEqual(float a, float b, float epsilon = std::numeric_limits::epsilon()) 25 | { 26 | return glm::abs(a - b) <= epsilon; 27 | } 28 | 29 | inline uint32_t roundToDivisible(uint32_t num, uint32_t divisor) 30 | { 31 | CORE_ASSERT(divisor != 0); 32 | 33 | const uint32_t remainder = num % divisor; 34 | 35 | if (remainder == 0) 36 | { 37 | return num; 38 | } 39 | 40 | return num + (divisor - remainder); 41 | } 42 | 43 | } // core::math -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/NatvisHolder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace core 4 | { 5 | 6 | class INatvisHolder 7 | { 8 | protected: 9 | virtual ~INatvisHolder() = default; 10 | }; 11 | 12 | template 13 | class NatvisHolder : public INatvisHolder 14 | { 15 | public: 16 | NatvisHolder(const T& v) : p(&v) {} 17 | 18 | private: 19 | const T* p; 20 | }; 21 | 22 | } // core -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Profiling.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef R_ENABLE_TRACY 7 | #define PROFILER_CPU_ZONE ZoneScoped 8 | #define PROFILER_CPU_ZONE_NAME(LABEL) ZoneScopedN(LABEL) 9 | #define PROFILER_CPU_ZONE_SET_NAME(LABEL, LEN) ZoneName(LABEL, LEN) 10 | #define PROFILER_FRAME_END FrameMark 11 | #define PROFILER_SET_THREAD_NAME(NAME) tracy::SetThreadName(NAME) 12 | #else 13 | #define PROFILER_CPU_ZONE 14 | #define PROFILER_CPU_ZONE_NAME(LABEL) 15 | #define PROFILER_CPU_ZONE_SET_NAME(LABEL, LEN) 16 | #define PROFILER_FRAME_END 17 | #define PROFILER_SET_THREAD_NAME(NAME) 18 | #endif -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/String.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace core::string 7 | { 8 | 9 | std::wstring CORE_API Convert(std::string_view str); 10 | 11 | std::string CORE_API BytesToHumanReadable(size_t size); 12 | 13 | } // namespace core::string -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Thread.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace core 6 | { 7 | 8 | class CORE_API ThreadIdStorage 9 | { 10 | public: 11 | static void SetMainThreadId(std::thread::id id); 12 | 13 | static void SetRenderThreadId(std::thread::id id); 14 | 15 | static std::thread::id RenderThreadId(); 16 | 17 | static std::thread::id MainThreadId(); 18 | 19 | private: 20 | inline static std::thread::id m_mainThreadId; 21 | inline static std::thread::id m_renderThreadId; 22 | }; 23 | 24 | inline std::thread::id CurrentThreadID() 25 | { 26 | return std::this_thread::get_id(); 27 | } 28 | 29 | inline bool IsMainThread() 30 | { 31 | return CurrentThreadID() == ThreadIdStorage::MainThreadId(); 32 | } 33 | 34 | inline bool IsRenderThread() 35 | { 36 | return CurrentThreadID() == ThreadIdStorage::RenderThreadId(); 37 | } 38 | 39 | } // core -------------------------------------------------------------------------------- /Src/Core/Src/Public/Core/Type.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace core 4 | { 5 | class NonCopyable 6 | { 7 | protected: 8 | constexpr NonCopyable() = default; 9 | ~NonCopyable() = default; 10 | 11 | NonCopyable(const NonCopyable&) = delete; 12 | NonCopyable& operator= (const NonCopyable&) = delete; 13 | 14 | NonCopyable(NonCopyable&&) = default; 15 | NonCopyable& operator= (NonCopyable&&) = default; 16 | }; 17 | 18 | class NonMovable 19 | { 20 | protected: 21 | constexpr NonMovable() = default; 22 | ~NonMovable() = default; 23 | 24 | NonMovable(NonMovable&&) = delete; 25 | NonMovable& operator= (NonMovable&&) = delete; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /Src/Core/Src/RTTRIntegration.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | RTTR_REGISTRATION 4 | { 5 | RTTR_NATVIS_REGISTER(bool); 6 | RTTR_NATVIS_REGISTER(float); 7 | RTTR_NATVIS_REGISTER(double); 8 | RTTR_NATVIS_REGISTER(char); 9 | RTTR_NATVIS_REGISTER(short); 10 | RTTR_NATVIS_REGISTER(int); 11 | RTTR_NATVIS_REGISTER(int64_t); 12 | RTTR_NATVIS_REGISTER(unsigned char); 13 | RTTR_NATVIS_REGISTER(unsigned short); 14 | RTTR_NATVIS_REGISTER(unsigned int); 15 | RTTR_NATVIS_REGISTER(uint64_t); 16 | RTTR_NATVIS_REGISTER(std::string); 17 | RTTR_NATVIS_REGISTER(std::string_view); 18 | 19 | rttr::type::register_converter_func( 20 | [](const rttr::type& t, bool& ok) -> std::string 21 | { 22 | ok = t.is_valid(); 23 | return std::string(t.get_name()); 24 | } 25 | ); 26 | 27 | rttr::type::register_converter_func( 28 | [](const std::string& t, bool& ok) -> rttr::type 29 | { 30 | auto type = rttr::type::get_by_name(t); 31 | ok = type.is_valid(); 32 | return type; 33 | } 34 | ); 35 | 36 | rttr::type::register_converter_func( 37 | [](std::string_view t, bool& ok) -> rttr::type 38 | { 39 | auto type = rttr::type::get_by_name(t); 40 | ok = type.is_valid(); 41 | return type; 42 | } 43 | ); 44 | 45 | RTTR_NATVIS_REGISTER(rttr::type); 46 | } 47 | 48 | namespace rttr_natvis 49 | { 50 | 51 | RttrNatvisFactories& RttrNatvisFactories::Instance() 52 | { 53 | static RttrNatvisFactories s_inst; 54 | return s_inst; 55 | } 56 | 57 | core::INatvisHolder* RttrNatvisFactories::GetNatvis(const void* var) 58 | { 59 | auto* v = reinterpret_cast(var); 60 | 61 | if (v && v->is_valid()) 62 | { 63 | auto type = v->get_type(); 64 | if (auto it = m_fns.find(type.is_wrapper() ? type.get_wrapped_type().get_raw_type() : type.get_raw_type()); it != m_fns.end()) 65 | { 66 | return it->second->Value(*v); 67 | } 68 | return new core::NatvisHolder(type.get_name()); 69 | } 70 | 71 | static const char* C_INVALID = "Invalid variant"; 72 | 73 | return new core::NatvisHolder(C_INVALID); 74 | } 75 | 76 | void RttrNatvisFactories::Cleanup() 77 | { 78 | m_fns.clear(); 79 | } 80 | 81 | } // rttr_natvis -------------------------------------------------------------------------------- /Src/Core/Src/String.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef R_OS_WIN32 4 | #include 5 | #endif 6 | 7 | namespace core::string 8 | { 9 | 10 | std::wstring Convert(std::string_view str) { 11 | #ifdef R_OS_WIN32 12 | const auto count = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), nullptr, 0); 13 | std::wstring result(count, L'\0'); 14 | MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), static_cast(result.size())); 15 | return result; 16 | #elif defined(R_OS_MACOS) 17 | std::mbstate_t state{}; 18 | const char *src = str.data(); 19 | std::size_t len = std::mbsrtowcs(nullptr, &src, 0, &state); 20 | if (len == static_cast(-1)) { 21 | return L""; 22 | } 23 | std::wstring result(len, L'\0'); 24 | std::mbsrtowcs(&result[0], &src, len, &state); 25 | return result; 26 | #else 27 | static_assert(false, "Platform not supported"); 28 | return L""; 29 | #endif 30 | } 31 | 32 | std::string BytesToHumanReadable(size_t size) 33 | { 34 | static constexpr std::string_view units[] = { "B", "KB", "MB", "GB", "TB" }; 35 | static constexpr int length = static_cast(std::size(units)); 36 | 37 | int i = 0; 38 | 39 | auto fSize = static_cast(size); 40 | 41 | if (size >= 1024) 42 | { 43 | for (i = 0; (size / 1024) > 0 && i < length - 1; i++, size /= 1024) 44 | { 45 | fSize = size / 1024.0f; 46 | } 47 | } 48 | 49 | return fmt::format("{:.2f} {}", fSize, units[i]); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /Src/Core/Src/Thread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core 4 | { 5 | 6 | void ThreadIdStorage::SetMainThreadId(std::thread::id id) 7 | { 8 | m_mainThreadId = id; 9 | } 10 | 11 | void ThreadIdStorage::SetRenderThreadId(std::thread::id id) 12 | { 13 | m_renderThreadId = id; 14 | } 15 | 16 | std::thread::id ThreadIdStorage::RenderThreadId() 17 | { 18 | return m_renderThreadId; 19 | } 20 | 21 | std::thread::id ThreadIdStorage::MainThreadId() 22 | { 23 | return m_mainThreadId; 24 | } 25 | 26 | } // core -------------------------------------------------------------------------------- /Src/Core/Src/rttr.natvis: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {m_data,[m_size]s} 5 | 6 | 7 | {m_type_data->m_name} 8 | 9 | 10 | {m_wrapper->m_name} 11 | 12 | 13 | 14 | 15 | 16 | *_nv() 17 | *(void**)m_data._Pad 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Src/Engine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(PROJECT_NAME Engine) 5 | 6 | find_package(glfw3 REQUIRED) 7 | find_package(taskflow REQUIRED) 8 | find_package(argparse REQUIRED) 9 | find_package(nlohmann_json REQUIRED) 10 | find_package(EnTT REQUIRED) 11 | find_package(stduuid REQUIRED) 12 | find_package(stb REQUIRED) 13 | find_package(assimp REQUIRED) 14 | find_package(doctest REQUIRED) 15 | find_package(simdjson REQUIRED) 16 | 17 | file(GLOB_RECURSE SOURCE_FILES 18 | "${CMAKE_CURRENT_SOURCE_DIR}/Engine/*.cpp" 19 | "${CMAKE_CURRENT_SOURCE_DIR}/Engine/*.hpp" 20 | "${CMAKE_CURRENT_SOURCE_DIR}/Engine/*.h" 21 | ) 22 | 23 | add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES}) 24 | 25 | target_link_libraries(${PROJECT_NAME} PUBLIC 26 | assimp::assimp 27 | argparse::argparse 28 | glfw 29 | Taskflow::Taskflow 30 | nlohmann_json::nlohmann_json 31 | RHI 32 | EnTT::EnTT 33 | stduuid::stduuid 34 | stb::stb 35 | doctest::doctest 36 | simdjson::simdjson 37 | ) 38 | 39 | target_compile_definitions(${PROJECT_NAME} PRIVATE ENGINE_EXPORT) 40 | target_precompile_headers(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/PCH.hpp") 41 | target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") 42 | 43 | if (ENGINE_ENABLE_TESTS) 44 | target_compile_definitions(${PROJECT_NAME} PUBLIC DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL 45 | DOCTEST_CONFIG_NO_WINDOWS_SEH) 46 | endif() 47 | 48 | # Create source groups for each directory 49 | foreach(FILE ${SOURCE_FILES}) 50 | # Get the path relative to the source directory 51 | file(RELATIVE_PATH RELATIVE_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE}) 52 | # Get the directory of the file 53 | get_filename_component(DIR ${RELATIVE_FILE} DIRECTORY) 54 | # Create the source group 55 | source_group(${DIR} FILES ${FILE}) 56 | endforeach() 57 | -------------------------------------------------------------------------------- /Src/Engine/Engine/Assert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef R_ENABLE_ASSERTS 6 | #define ENGINE_ASSERT(x) do { if(!(x)) { core::Assert("ENGINE", #x); } } while(false) 7 | #define ENGINE_ASSERT_WITH_MESSAGE(x, ...) do { if(!(x)) { core::Assert("ENGINE", #x, __VA_ARGS__); } } while(false) 8 | #else 9 | #define ENGINE_ASSERT(x) 10 | #define ENGINE_ASSERT_WITH_MESSAGE(x, ...) 11 | #endif -------------------------------------------------------------------------------- /Src/Engine/Engine/Config.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Platform-specific macros for importing/exporting symbols 4 | #if defined(R_OS_WIN32) 5 | 6 | #ifdef ENGINE_EXPORT 7 | // We are building the library, so export the symbols 8 | #define ENGINE_API __declspec(dllexport) 9 | #else 10 | // We are using the library, so import the symbols 11 | #define ENGINE_API __declspec(dllimport) 12 | #endif 13 | 14 | #else 15 | #define ENGINE_API 16 | #endif 17 | 18 | #if defined(R_OS_WIN32) 19 | #define ENGINE_FORCE_INLINE __forceinline 20 | #elif defined(__GNUC__) || defined(__clang__) 21 | #define ENGINE_FORCE_INLINE __attribute__((always_inline)) inline 22 | #else 23 | #define ENGINE_FORCE_INLINE inline 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /Src/Engine/Engine/Domain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace engine 11 | { 12 | 13 | enum class Domain : uint32_t 14 | { 15 | NONE = 0x00, 16 | EDITOR = 0x01, 17 | CLIENT = 0x02, 18 | CLIENT_NO_UI = 0x04, // for unit tests 19 | 20 | UI = EDITOR | CLIENT, 21 | NO_EDITOR = CLIENT | CLIENT_NO_UI, 22 | 23 | ALL = static_cast(-1) 24 | }; 25 | ENGINE_DEFINE_BITWISE_OPS(Domain); 26 | 27 | inline std::string_view DomainToString(Domain domain) 28 | { 29 | switch (domain) 30 | { 31 | case Domain::NONE: return "None"; 32 | case Domain::EDITOR: return "Editor"; 33 | case Domain::CLIENT: return "Client"; 34 | case Domain::UI: return "UI"; 35 | case Domain::CLIENT_NO_UI: return "Client no ui"; 36 | case Domain::NO_EDITOR: return "No Editor"; 37 | case Domain::ALL: return "All"; 38 | default: 39 | ENGINE_ASSERT(false); 40 | return ""; 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Src/Engine/Engine/ECS/Component.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGameStudio/RightEngine/94a004aa9af31f41c2bf1ba7b1591b22581117e7/Src/Engine/Engine/ECS/Component.cpp -------------------------------------------------------------------------------- /Src/Engine/Engine/ECS/Component.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine::ecs 7 | { 8 | 9 | class ENGINE_API IComponent 10 | { 11 | RTTR_DECLARE_ROOT() 12 | 13 | public: 14 | enum class Type : uint8_t 15 | { 16 | ENGINE = 0, 17 | PLUGIN 18 | }; 19 | 20 | struct MetaInfo 21 | { 22 | Type m_type = Type::ENGINE; 23 | }; 24 | 25 | inline void Modify() { ENGINE_ASSERT_WITH_MESSAGE(!m_modified, "Component last change wasn't processed"); m_modified = true; } 26 | inline void Reset() { m_modified = false; } 27 | inline void Init() { m_initialized = true; } 28 | inline bool IsModified() const { return m_modified; } 29 | inline bool IsRecentlyCreated() const { return !m_initialized; } 30 | 31 | private: 32 | bool m_modified = false; 33 | bool m_initialized = false; 34 | }; 35 | 36 | template 37 | class Component : public IComponent 38 | { 39 | RTTR_DECLARE_ANCESTORS(IComponent) 40 | }; 41 | 42 | } // engine::ecs -------------------------------------------------------------------------------- /Src/Engine/Engine/ECS/System.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace engine::ecs 4 | { 5 | 6 | ISystem::ISystem(World* world) : m_world(world) 7 | { 8 | } 9 | 10 | } // engine::ecs -------------------------------------------------------------------------------- /Src/Engine/Engine/ECS/System.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace engine::ecs 9 | { 10 | 11 | class World; 12 | 13 | class ENGINE_API ISystem : public core::NonCopyable 14 | { 15 | RTTR_DECLARE_ROOT() 16 | RTTR_ENABLE_OBJECT_INFO() 17 | 18 | public: 19 | struct MetaInfo 20 | { 21 | Domain m_domain = Domain::ALL; 22 | eastl::vector m_updateAfter; 23 | eastl::vector m_updateBefore; 24 | }; 25 | 26 | ISystem(World* world); 27 | virtual ~ISystem() = default; 28 | 29 | virtual void Update(float dt) {} 30 | 31 | World* W() { return m_world; } 32 | 33 | private: 34 | World* m_world; 35 | }; 36 | 37 | template 38 | class System : public ISystem 39 | { 40 | RTTR_DECLARE_ANCESTORS(ISystem) 41 | RTTR_ENABLE_OBJECT_INFO_AS(T) 42 | 43 | public: 44 | System(World* world) : ISystem(world) {} 45 | }; 46 | 47 | } // engine::ecs -------------------------------------------------------------------------------- /Src/Engine/Engine/ECS/SystemManager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace engine::ecs 11 | { 12 | 13 | class ENGINE_API SystemManager : public core::NonCopyable 14 | { 15 | public: 16 | SystemManager(World* world); 17 | ~SystemManager(); 18 | 19 | void Update(float dt); 20 | 21 | template 22 | void Add() 23 | { 24 | static_assert(std::is_base_of_v); 25 | const auto type = rttr::type::get(); 26 | ENGINE_ASSERT(type.get_constructor({rttr::type::get()}).is_valid()); 27 | 28 | const auto metadata = type.get_metadata(registration::C_METADATA_KEY).template get_value_safe(); 29 | 30 | if (metadata.m_domain != Domain::ALL && (Instance().Cfg().m_domain & metadata.m_domain) != metadata.m_domain) 31 | { 32 | core::log::info("[SystemManager] Skipping '{}' registration due to incompatible domain '{}' engine domain: '{}'", 33 | type.get_name(), 34 | DomainToString(metadata.m_domain), 35 | DomainToString(Instance().Cfg().m_domain)); 36 | return; 37 | } 38 | 39 | m_systems.emplace_back(std::make_unique(m_world)); 40 | m_typeToSystem[rttr::type::get()] = m_systems.back().get(); 41 | } 42 | 43 | void UpdateDependenciesOrder(); 44 | 45 | private: 46 | struct ExecutionParams 47 | { 48 | float dt; 49 | }; 50 | 51 | eastl::vector> m_systems; 52 | eastl::unordered_map m_typeToSystem; 53 | World* m_world; 54 | tf::Taskflow m_taskflow; 55 | ExecutionParams m_execParams; 56 | }; 57 | 58 | } // engine::ecs -------------------------------------------------------------------------------- /Src/Engine/Engine/ECS/World.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace engine::ecs 4 | { 5 | 6 | World::World(std::string_view name) : m_name(name) 7 | { 8 | m_entityManager = std::make_unique(this); 9 | m_systemManager = std::make_unique(this); 10 | } 11 | 12 | World::~World() 13 | { 14 | } 15 | 16 | void World::Update(float dt) 17 | { 18 | PROFILER_CPU_ZONE; 19 | PROFILER_CPU_ZONE_SET_NAME(m_name.c_str(), m_name.size()); 20 | 21 | m_entityManager->Update(); 22 | m_systemManager->Update(dt); 23 | } 24 | 25 | } // engine::ecs 26 | -------------------------------------------------------------------------------- /Src/Engine/Engine/ECS/World.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine::ecs 8 | { 9 | 10 | class ENGINE_API World 11 | { 12 | public: 13 | World(std::string_view name); 14 | ~World(); 15 | 16 | void Update(float dt); 17 | 18 | auto View() 19 | { 20 | return m_entityManager->m_registry.view(); 21 | } 22 | 23 | template 24 | auto View() 25 | { 26 | return m_entityManager->m_registry.view().each(); 27 | } 28 | 29 | std::unique_ptr& GetSystemManager() { return m_systemManager; } 30 | std::unique_ptr& GetEntityManager() { return m_entityManager; } 31 | 32 | std::string_view Name() const { return m_name; } 33 | 34 | private: 35 | std::unique_ptr m_systemManager; 36 | std::unique_ptr m_entityManager; 37 | std::string m_name; 38 | }; 39 | 40 | } // engine::ecs -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/ComponentPanel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace engine::editor 6 | { 7 | 8 | class ENGINE_API ComponentPanel final : public Panel 9 | { 10 | public: 11 | ComponentPanel() : Panel("Components") 12 | {} 13 | 14 | private: 15 | virtual void DrawPanel() override; 16 | }; 17 | 18 | } // engine::editor -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/EntityTreePanel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace engine::editor 9 | { 10 | 11 | void EntityTreePanel::DrawPanel() 12 | { 13 | auto& ws = Instance().Service(); 14 | auto& editorService = Instance().Service(); 15 | auto& world = ws.CurrentWorld(); 16 | 17 | for (const auto entity : world->View()) 18 | { 19 | if (ImGui::TreeNode(world->GetEntityManager()->GetEntityInfo(entity).m_name.c_str())) 20 | { 21 | if (ImGui::IsItemClicked()) 22 | { 23 | editorService.SelectedEntity(entity); 24 | } 25 | ImGui::TreePop(); 26 | } 27 | } 28 | } 29 | 30 | } // engine::editor 31 | -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/EntityTreePanel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace engine::editor 6 | { 7 | 8 | class ENGINE_API EntityTreePanel final : public Panel 9 | { 10 | public: 11 | EntityTreePanel() : Panel("Entities") 12 | {} 13 | 14 | private: 15 | virtual void DrawPanel() override; 16 | }; 17 | 18 | } // engine::editor -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/MenuBarPanel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace engine::editor 6 | { 7 | 8 | void MenuBarPanel::DrawPanel() 9 | { 10 | if (ImGui::BeginMenu("General")) 11 | { 12 | bool shouldShutdownEngine = false; 13 | ImGui::MenuItem("Exit", nullptr, &shouldShutdownEngine); 14 | 15 | if (shouldShutdownEngine) 16 | { 17 | Instance().Stop(); 18 | } 19 | 20 | ImGui::EndMenu(); 21 | } 22 | 23 | if (ImGui::BeginMenu("World")) 24 | { 25 | if (ImGui::MenuItem("Save")) 26 | { 27 | auto& ws = Instance().Service(); 28 | ws.SaveWorld(); 29 | } 30 | ImGui::EndMenu(); 31 | } 32 | } 33 | 34 | } // engine::editor -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/MenuBarPanel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace engine::editor 6 | { 7 | 8 | class ENGINE_API MenuBarPanel final : public Panel 9 | { 10 | public: 11 | MenuBarPanel() : Panel("MenuBar", true) 12 | {} 13 | 14 | private: 15 | virtual void DrawPanel() override; 16 | }; 17 | 18 | } // engine::editor -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/Panel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace engine::editor 5 | { 6 | 7 | void Panel::Draw() 8 | { 9 | if (m_menuBar) 10 | { 11 | if (ImGui::BeginMainMenuBar()) 12 | { 13 | m_isHovered = ImGui::IsWindowHovered(); 14 | 15 | DrawPanel(); 16 | 17 | ImGui::EndMainMenuBar(); 18 | } 19 | } 20 | else 21 | { 22 | ImGui::Begin(m_name.c_str()); 23 | 24 | m_isHovered = ImGui::IsWindowHovered(); 25 | 26 | DrawPanel(); 27 | 28 | ImGui::End(); 29 | } 30 | } 31 | 32 | } // engine::editor -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/Panel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace engine::editor 6 | { 7 | 8 | class ENGINE_API Panel 9 | { 10 | public: 11 | Panel(std::string_view name, bool menuBar = false) : m_name(name), m_menuBar(menuBar) 12 | {} 13 | 14 | virtual ~Panel() = default; 15 | 16 | virtual void Draw(); 17 | 18 | bool IsHovered() const 19 | { 20 | return m_isHovered; 21 | } 22 | 23 | protected: 24 | virtual void DrawPanel() = 0; 25 | 26 | std::string m_name; 27 | bool m_isHovered = false; 28 | bool m_menuBar = false; 29 | }; 30 | 31 | } // engine::editor -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/ViewportPanel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace engine::editor 7 | { 8 | 9 | void ViewportPanel::DrawPanel() 10 | { 11 | auto& rs = Instance().Service(); 12 | auto& is = Instance().Service(); 13 | 14 | ImVec2 viewportSize = ImGui::GetContentRegionAvail(); 15 | 16 | if (!core::math::almostEqual(m_viewportSize.x, viewportSize.x) || !core::math::almostEqual(m_viewportSize.y, viewportSize.y)) 17 | { 18 | m_viewportSize = { viewportSize.x, viewportSize.y }; 19 | rs.OnResize({ static_cast(m_viewportSize.x), static_cast(m_viewportSize.y) }); 20 | } 21 | 22 | is.Image(rs.Pipeline(rs.DefaultMaterial())->Descriptor().m_pass->Descriptor().m_colorAttachments[0].m_texture, m_viewportSize); 23 | } 24 | 25 | } // engine::editor 26 | -------------------------------------------------------------------------------- /Src/Engine/Engine/Editor/ViewportPanel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine::editor 7 | { 8 | 9 | class ENGINE_API ViewportPanel final : public Panel 10 | { 11 | public: 12 | ViewportPanel() : Panel("Viewport") 13 | {} 14 | 15 | glm::ivec2 Size() const 16 | { 17 | return { m_viewportSize.x, m_viewportSize.y }; 18 | } 19 | 20 | private: 21 | virtual void DrawPanel() override; 22 | 23 | ImVec2 m_viewportSize = ImVec2(1, 1); 24 | }; 25 | 26 | } // engine::editor -------------------------------------------------------------------------------- /Src/Engine/Engine/Engine.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace engine 11 | { 12 | 13 | namespace io 14 | { 15 | namespace fs = std::filesystem; 16 | } // io 17 | 18 | class ENGINE_API Engine final : private core::NonCopyable 19 | { 20 | friend Engine& Instance(); 21 | public: 22 | struct Config 23 | { 24 | io::fs::path m_projectPath; 25 | Domain m_domain = Domain::NONE; 26 | }; 27 | 28 | Engine(int argCount, char* argPtr[]); 29 | ~Engine(); 30 | 31 | int Run(); 32 | void Stop(int status = 0); 33 | 34 | template 35 | T& Service() { return m_serviceManager->Service(); } 36 | 37 | template 38 | T* FindService() { return m_serviceManager->FindService(); } 39 | 40 | std::unique_ptr& GetServiceManager() { return m_serviceManager; } 41 | 42 | const Config& Cfg() const { return m_config; } 43 | 44 | private: 45 | void Update(); 46 | void ParseCfg(int argCount, char* argPtr[]); 47 | 48 | private: 49 | inline static Engine* s_instance = nullptr; 50 | 51 | bool m_running = false; 52 | int m_status = 0; 53 | Timer m_timer; 54 | Timer m_frameLimiterTimer; 55 | std::unique_ptr m_serviceManager; 56 | Config m_config; 57 | }; 58 | 59 | ENGINE_FORCE_INLINE Engine& Instance() 60 | { 61 | ENGINE_ASSERT(Engine::s_instance); 62 | return *Engine::s_instance; 63 | } 64 | 65 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Serialization/FromJson.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | ENGINE_API rttr::variant FromJsonObject(const simdjson::dom::element& j, rttr::type expectedType = {}); 11 | ENGINE_API rttr::variant FromJsonString(const std::string& str, rttr::type expectedType = {}, std::string* errorBuffer = nullptr); 12 | 13 | template std::optional FromJsonString(const std::string& str, std::string* errorBuffer = nullptr) 14 | { 15 | rttr::variant var = FromJsonString(str, rttr::type::get(), errorBuffer); 16 | if constexpr (std::is_same_v) 17 | return var; 18 | else if (var.is_type()) 19 | return std::move(var.get_value_unsafe()); 20 | else 21 | return {}; 22 | } 23 | 24 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Serialization/ToJson.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine 7 | { 8 | ENGINE_API std::string ToJsonString(const rttr::variant& obj, rttr::type expectedType = {}); 9 | ENGINE_API nlohmann::json ToJsonObject(const rttr::variant& obj, rttr::type expectedType = {}); 10 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/EditorService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | namespace editor 11 | { 12 | constexpr entt::entity C_INVALID_ENTITY = (entt::entity) std::numeric_limits::max(); 13 | } // editor 14 | 15 | class ENGINE_API EditorService final : public Service 16 | { 17 | public: 18 | struct Impl; 19 | 20 | EditorService(); 21 | virtual ~EditorService() override; 22 | 23 | virtual void Update(float dt) override; 24 | virtual void PostUpdate(float dt) override; 25 | 26 | void SelectedEntity(entt::entity e); 27 | entt::entity SelectedEntity(); 28 | 29 | void Initialize(); 30 | 31 | glm::ivec2 ViewportSize() const; 32 | bool IsViewportHovered() const; 33 | 34 | private: 35 | std::unique_ptr m_impl; 36 | }; 37 | 38 | } // namespace engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Filesystem/File.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace engine::io 7 | { 8 | 9 | File::File(const fs::path& path) : m_path(path) 10 | { 11 | } 12 | 13 | bool File::Read() 14 | { 15 | auto& vfs = Instance().Service(); 16 | 17 | std::ifstream file(vfs.Absolute(m_path).c_str(), std::ios::binary | std::ios::ate); 18 | if (!file.is_open()) 19 | { 20 | return false; 21 | } 22 | 23 | std::streamsize size = file.tellg(); 24 | file.seekg(0, std::ios::beg); 25 | 26 | eastl::vector fileBuffer(size); 27 | if (!file.read(fileBuffer.data(), size)) 28 | { 29 | return false; 30 | } 31 | 32 | m_data = core::Blob(fileBuffer.data(), fileBuffer.size()); 33 | return true; 34 | } 35 | 36 | bool File::Write(std::string_view str) 37 | { 38 | auto& vfs = Instance().Service(); 39 | 40 | std::ofstream file(vfs.Absolute(m_path).c_str()); 41 | if (!file.is_open()) 42 | { 43 | return false; 44 | } 45 | 46 | file << str; 47 | return true; 48 | } 49 | 50 | } // engine::io -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Filesystem/File.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine::io 7 | { 8 | 9 | class ENGINE_API File 10 | { 11 | public: 12 | File(const fs::path& path); 13 | 14 | bool Read(); 15 | bool Write(std::string_view str); 16 | 17 | const fs::path& Path() const { return m_path; } 18 | size_t Size() const { return m_data.size(); } 19 | void* Raw() { return m_data.raw(); } 20 | 21 | private: 22 | fs::path m_path; 23 | core::Blob m_data; 24 | }; 25 | 26 | } // engine::io -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Filesystem/IFilesystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace engine::io 5 | { 6 | 7 | IFilesystem::IFilesystem(const fs::path& alias, const fs::path& root) : m_alias(alias) 8 | { 9 | m_fullPath = Instance().Cfg().m_projectPath.parent_path().parent_path().parent_path().generic_u8string() + root.generic_u8string(); 10 | } 11 | 12 | } // engine::io -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Filesystem/IFilesystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine::io 7 | { 8 | 9 | namespace fs = std::filesystem; 10 | 11 | class ENGINE_API IFilesystem 12 | { 13 | public: 14 | IFilesystem(const fs::path& alias, const fs::path& root); 15 | 16 | virtual ~IFilesystem() {} 17 | 18 | virtual fs::path Absolute(const fs::path& path) const = 0; 19 | 20 | protected: 21 | fs::path m_fullPath; 22 | fs::path m_alias; 23 | fs::path m_root; 24 | }; 25 | 26 | } // engine::io -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Filesystem/NativeFilesystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace engine::io 4 | { 5 | 6 | NativeFilesystem::NativeFilesystem(const fs::path& alias, const fs::path& root) : IFilesystem(alias, root) 7 | { 8 | } 9 | 10 | NativeFilesystem::~NativeFilesystem() 11 | { 12 | } 13 | 14 | fs::path NativeFilesystem::Absolute(const fs::path& path) const 15 | { 16 | auto p = path.generic_u8string(); 17 | 18 | p.erase(0, m_alias.generic_u8string().size()); 19 | 20 | io::fs::path pth = m_fullPath.generic_u8string() + "/" + p; 21 | pth = pth.lexically_normal(); 22 | 23 | return pth; 24 | } 25 | 26 | } // engine::io -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Filesystem/NativeFilesystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace engine::io 6 | { 7 | 8 | class ENGINE_API NativeFilesystem : public IFilesystem 9 | { 10 | public: 11 | NativeFilesystem(const fs::path& alias, const fs::path& root); 12 | 13 | virtual ~NativeFilesystem() override; 14 | 15 | virtual fs::path Absolute(const fs::path& path) const override; 16 | 17 | private: 18 | }; 19 | 20 | } // engine::io -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Filesystem/VirtualFilesystemService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine::io 8 | { 9 | 10 | enum class FilesystemType : uint8_t 11 | { 12 | NATIVE = 0 13 | }; 14 | 15 | struct ENGINE_API VFSSettings 16 | { 17 | struct Setting 18 | { 19 | std::string m_alias; 20 | std::string m_path; 21 | }; 22 | 23 | eastl::vector m_settings; 24 | }; 25 | 26 | class ENGINE_API VirtualFilesystemService : public Service 27 | { 28 | public: 29 | VirtualFilesystemService(); 30 | 31 | virtual ~VirtualFilesystemService() override; 32 | 33 | virtual void Update(float dt) override; 34 | virtual void PostUpdate(float dt) override; 35 | 36 | void Assign(const fs::path& alias, const fs::path& rootPath, FilesystemType type = FilesystemType::NATIVE); 37 | 38 | fs::path Absolute(const fs::path& path) const; 39 | 40 | private: 41 | eastl::unordered_map> m_filesystems; 42 | }; 43 | 44 | } // engine::io -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/IService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace engine 10 | { 11 | 12 | class ENGINE_API IService : public core::NonCopyable 13 | { 14 | RTTR_DECLARE_ROOT() 15 | RTTR_ENABLE_OBJECT_INFO() 16 | 17 | public: 18 | struct MetaInfo 19 | { 20 | Domain m_domain = Domain::ALL; 21 | eastl::vector m_updateAfter; 22 | eastl::vector m_updateBefore; 23 | eastl::vector m_postUpdateAfter; 24 | eastl::vector m_postUpdateBefore; 25 | }; 26 | 27 | virtual ~IService() = default; 28 | 29 | virtual void Update(float dt) {} 30 | virtual void PostUpdate(float dt) {} 31 | }; 32 | 33 | template 34 | class Service : public IService 35 | { 36 | RTTR_DECLARE_ANCESTORS(IService) 37 | RTTR_ENABLE_OBJECT_INFO_AS(T) 38 | }; 39 | 40 | } // namespace engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Imgui/ImguiService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | class ENGINE_API ImguiService : public Service 11 | { 12 | public: 13 | ImguiService(); 14 | virtual ~ImguiService() override; 15 | 16 | virtual void Update(float dt) override; 17 | virtual void PostUpdate(float dt) override; 18 | 19 | void Image(const std::shared_ptr& texture, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1)); 20 | void RemoveImage(const std::shared_ptr& texture); 21 | 22 | private: 23 | std::string m_configFilePath; 24 | std::shared_ptr m_imguiProvider; 25 | ImGuiStyle m_defaultStyle; 26 | }; 27 | 28 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Project/Project.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | RTTR_REGISTRATION 8 | { 9 | engine::registration::CommandLineArgs() 10 | .Argument( 11 | engine::registration::CommandLineArg("-prj", "--project") 12 | .Help("Absolute path to a project file") 13 | .DefaultValue("") 14 | ); 15 | } 16 | 17 | namespace 18 | { 19 | constexpr std::string_view C_TYPE_KEY = "__type__"; 20 | constexpr std::string_view C_PROJECT_NAME_KEY = "name"; 21 | constexpr std::string_view C_VERSION_KEY = "version"; 22 | constexpr std::string_view C_SETTINGS_KEY = "settings"; 23 | constexpr uint8_t C_VERSION = 0; // Please up project settings version each time you change the format 24 | } // unnamed 25 | 26 | namespace engine 27 | { 28 | 29 | using namespace nlohmann; 30 | 31 | Project::Project(const io::fs::path& path) : m_path(path) 32 | { 33 | ENGINE_ASSERT(!path.empty()); 34 | ENGINE_ASSERT(io::fs::exists(path)); 35 | ENGINE_ASSERT(path.extension() == ".project"); 36 | ENGINE_ASSERT(path.is_absolute()); 37 | 38 | std::ifstream file(path); 39 | 40 | auto j = json::parse(file); 41 | m_name = j[C_PROJECT_NAME_KEY]; 42 | m_version = j[C_VERSION_KEY]; 43 | 44 | ENGINE_ASSERT(m_version == C_VERSION); 45 | 46 | // TODO: Implement smart settings parsing using reflection from RTTR 47 | 48 | auto& vfsSettingsJson = j[C_SETTINGS_KEY][0]; 49 | auto type = vfsSettingsJson[C_TYPE_KEY]; 50 | ENGINE_ASSERT(type == "engine::io::VFSSettings"); 51 | 52 | auto& vfsSettingsArray = vfsSettingsJson[C_SETTINGS_KEY]; 53 | ENGINE_ASSERT(vfsSettingsArray.is_array()); 54 | 55 | io::VFSSettings vfsSettings; 56 | for (auto& settingJson : vfsSettingsArray) 57 | { 58 | auto settingType = settingJson[C_TYPE_KEY]; 59 | ENGINE_ASSERT(settingType == "engine::io::VFSSettings::Setting"); 60 | io::VFSSettings::Setting setting; 61 | setting.m_alias = settingJson["alias"]; 62 | setting.m_path = settingJson["path"]; 63 | vfsSettings.m_settings.emplace_back(std::move(setting)); 64 | } 65 | 66 | m_settings.emplace_back(std::move(vfsSettings)); 67 | } 68 | 69 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Project/Project.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | namespace io 11 | { 12 | namespace fs = std::filesystem; 13 | } // io 14 | 15 | class ENGINE_API Project 16 | { 17 | public: 18 | // Absolute path to a project file 19 | Project(const io::fs::path& path); 20 | 21 | template 22 | T& Setting() 23 | { 24 | auto it = eastl::find_if(m_settings.begin(), m_settings.end(), [](const rttr::variant& variant) 25 | { 26 | return variant.get_type() == rttr::type::get(); 27 | }); 28 | 29 | ENGINE_ASSERT(it != m_settings.end()); 30 | 31 | return it->template get_value_safe(); 32 | } 33 | 34 | private: 35 | std::string m_name; 36 | [[maybe_unused]] const io::fs::path& m_path; 37 | uint8_t m_version; 38 | eastl::vector m_settings; 39 | }; 40 | 41 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Project/ProjectService.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | RTTR_REGISTRATION 5 | { 6 | engine::registration::Service("engine::ProjectService"); 7 | } 8 | 9 | namespace engine 10 | { 11 | 12 | ProjectService::ProjectService() 13 | { 14 | } 15 | 16 | ProjectService::~ProjectService() 17 | { 18 | } 19 | 20 | void ProjectService::Update(float dt) 21 | { 22 | } 23 | 24 | void ProjectService::PostUpdate(float dt) 25 | { 26 | } 27 | 28 | void ProjectService::Load(const io::fs::path& path) 29 | { 30 | ENGINE_ASSERT(!m_project); 31 | 32 | if (path.is_relative()) 33 | { 34 | const io::fs::path absPath = io::fs::absolute(path); 35 | m_project = std::make_unique(absPath); 36 | core::log::info("Successfully loaded project '{}'", absPath.generic_u8string()); 37 | } 38 | else 39 | { 40 | m_project = std::make_unique(path); 41 | core::log::info("Successfully loaded project '{}'", path.generic_u8string()); 42 | } 43 | } 44 | 45 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Project/ProjectService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | class ENGINE_API ProjectService : public Service 11 | { 12 | public: 13 | ProjectService(); 14 | ~ProjectService(); 15 | 16 | virtual void Update(float dt) override; 17 | virtual void PostUpdate(float dt) override; 18 | 19 | void Load(const io::fs::path& path); 20 | 21 | const std::unique_ptr& CurrentProject() const { ENGINE_ASSERT(m_project); return m_project; } 22 | 23 | private: 24 | std::unique_ptr m_project; 25 | }; 26 | 27 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Render/Mesh.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace engine 4 | { 5 | 6 | void render::Mesh::AddSubMesh(const std::shared_ptr& submesh) 7 | { 8 | ENGINE_ASSERT(eastl::find(m_submeshes.begin(), m_submeshes.end(), submesh) == m_submeshes.end()); 9 | 10 | m_submeshes.emplace_back(submesh); 11 | } 12 | 13 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Render/Mesh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine::render 7 | { 8 | 9 | class ENGINE_API SubMesh 10 | { 11 | public: 12 | SubMesh(const std::shared_ptr& vb, const std::shared_ptr& ib = {}) : m_vertexBuffer(vb), m_indexBuffer(ib) 13 | {} 14 | 15 | const std::shared_ptr& VertexBuffer() { ENGINE_ASSERT(m_vertexBuffer); return m_vertexBuffer; } 16 | const std::shared_ptr& IndexBuffer() { return m_indexBuffer; } 17 | 18 | private: 19 | std::shared_ptr m_vertexBuffer; 20 | std::shared_ptr m_indexBuffer; 21 | }; 22 | 23 | class ENGINE_API Mesh 24 | { 25 | public: 26 | using SubMeshList = eastl::vector>; 27 | 28 | const std::shared_ptr& GetSubMesh(uint32_t index) const { ENGINE_ASSERT(index < m_submeshes.size()); return m_submeshes[index]; } 29 | 30 | const SubMeshList& GetSubMeshList() const { return m_submeshes; } 31 | 32 | void AddSubMesh(const std::shared_ptr& submesh); 33 | 34 | private: 35 | eastl::vector> m_submeshes; 36 | }; 37 | 38 | } // engine::render -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/EnvironmentMapResource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace engine 10 | { 11 | 12 | struct EnvironmentMap 13 | { 14 | ResPtr m_material; 15 | RPtr m_cubemap; 16 | RPtr m_irradianceTexture; 17 | RPtr m_prefilterTexture; 18 | RPtr m_brdfTexture; 19 | }; 20 | 21 | class EnvironmentMapResource; 22 | 23 | class ENGINE_API EnvironmentMapLoader final : public Loader 24 | { 25 | public: 26 | EnvironmentMapLoader(); 27 | 28 | virtual void Update() override; 29 | 30 | virtual ResPtr Load(const fs::path& path, bool immediate) override; 31 | 32 | virtual ResPtr Get(const fs::path& path) const override; 33 | 34 | virtual void LoadSystemResources() override; 35 | 36 | const ResPtr& SkyboxMaterial() const { return m_skyboxMaterial; } 37 | 38 | private: 39 | bool Load(const ResPtr& resource); 40 | 41 | mutable std::mutex m_mutex; 42 | eastl::vector> m_loadingTasks; 43 | eastl::unordered_map> m_cache; 44 | 45 | ResPtr m_equirectToCubemapMaterial; 46 | ResPtr m_envmapIrradianceMaterial; 47 | ResPtr m_envmapPrefilterMaterial; 48 | ResPtr m_irradianceLoadMaterial; 49 | ResPtr m_prefilterLoadMaterial; 50 | ResPtr m_skyboxMaterial; 51 | }; 52 | 53 | class ENGINE_API EnvironmentMapResource final : public Resource 54 | { 55 | public: 56 | EnvironmentMapResource(const io::fs::path& path); 57 | virtual ~EnvironmentMapResource() {} 58 | 59 | const EnvironmentMap& Raw() const { ENGINE_ASSERT(Ready()); return m_map; } 60 | 61 | friend class EnvironmentMapLoader; 62 | 63 | private: 64 | EnvironmentMap m_map; 65 | }; 66 | 67 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/Loader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace engine 4 | { 5 | 6 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/Loader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | template 11 | using ResPtr = std::shared_ptr; 12 | 13 | template 14 | ResPtr MakeResPtr(Args&&... args) 15 | { 16 | static_assert(std::is_base_of_v); 17 | return std::make_shared(std::forward(args)...); 18 | } 19 | 20 | namespace fs = std::filesystem; 21 | 22 | class ENGINE_API Loader : public core::NonCopyable 23 | { 24 | public: 25 | struct MetaInfo 26 | { 27 | Domain m_domain = Domain::ALL; 28 | }; 29 | 30 | virtual ~Loader() {} 31 | 32 | virtual void Update() = 0; 33 | 34 | // Async load of a resource 35 | virtual ResPtr Load(const fs::path& path, bool immediate) = 0; 36 | 37 | virtual void LoadSystemResources() = 0; 38 | 39 | // Return resource pointer if it was already loaded, if not returns nullptr 40 | virtual ResPtr Get(const fs::path& path) const = 0; 41 | }; 42 | 43 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/MeshResource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace engine 10 | { 11 | 12 | class MeshResource; 13 | 14 | class ENGINE_API MeshLoader final : public Loader 15 | { 16 | public: 17 | MeshLoader(); 18 | 19 | virtual void Update() override; 20 | 21 | virtual ResPtr Load(const fs::path& path, bool immediate) override; 22 | 23 | virtual ResPtr Get(const fs::path& path) const override; 24 | 25 | virtual void LoadSystemResources() override {} 26 | 27 | private: 28 | bool Load(const ResPtr& resource); 29 | 30 | void ProcessAiNode(const aiNode* node, const aiScene* scene, const ResPtr& resource); 31 | void ProcessAiMesh(const aiMesh* mesh, const ResPtr& resource); 32 | 33 | std::mutex m_mutex; 34 | eastl::vector> m_loadingTasks; 35 | Assimp::Importer m_importer; 36 | eastl::unordered_map> m_cache; 37 | }; 38 | 39 | class ENGINE_API MeshResource final : public Resource 40 | { 41 | public: 42 | MeshResource(const io::fs::path & path); 43 | virtual ~MeshResource() {} 44 | 45 | const ResPtr& Mesh() const { return m_mesh; } 46 | 47 | friend class MeshLoader; 48 | 49 | private: 50 | ResPtr m_mesh; 51 | }; 52 | 53 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/Resource.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace engine 4 | { 5 | 6 | IResource::IResource(const io::fs::path& path) : m_srcPath(path) 7 | { 8 | } 9 | 10 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/Resource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | class ENGINE_API IResource : core::NonCopyable 11 | { 12 | RTTR_DECLARE_ROOT() 13 | RTTR_ENABLE_OBJECT_INFO() 14 | 15 | public: 16 | enum class Status : uint8_t 17 | { 18 | UNKNOWN = 0, 19 | LOADING = 1, 20 | FAILED = 2, 21 | READY = 3 22 | }; 23 | 24 | IResource(const io::fs::path& path); 25 | virtual ~IResource() {} 26 | 27 | const io::fs::path& SourcePath() const { return m_srcPath; } 28 | bool Ready() const { return m_status == Status::READY; } 29 | void Wait() const { while (!Ready()) { std::this_thread::yield(); } } 30 | 31 | io::fs::path m_srcPath; 32 | protected: 33 | Status m_status = Status::UNKNOWN; 34 | }; 35 | 36 | template 37 | class Resource : public IResource 38 | { 39 | RTTR_DECLARE_ANCESTORS(IResource) 40 | RTTR_ENABLE_OBJECT_INFO_AS(T) 41 | 42 | public: 43 | explicit Resource(const io::fs::path& path) 44 | : IResource(path) 45 | { 46 | } 47 | }; 48 | 49 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/ResourceService.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | RTTR_REGISTRATION 6 | { 7 | engine::registration::Service("engine::ResourceService") 8 | .UpdateBefore(); 9 | } 10 | 11 | namespace engine 12 | { 13 | 14 | ResourceService::ResourceService() 15 | { 16 | } 17 | 18 | ResourceService::~ResourceService() 19 | { 20 | core::log::debug("[ResourceService] Started destroying resource loaders"); 21 | 22 | for (auto& [type, loader] : m_loadersMap) 23 | { 24 | loader.reset(); 25 | core::log::debug("[ResourceService] Destroyed loader '{}' successfully", type.get_name()); 26 | } 27 | 28 | core::log::debug("[ResourceService] Destroyed all resource loaders successfully"); 29 | } 30 | 31 | void ResourceService::Update(float dt) 32 | { 33 | PROFILER_CPU_ZONE; 34 | 35 | for (auto& [_, loader] : m_loadersMap) 36 | { 37 | loader->Update(); 38 | } 39 | } 40 | 41 | void ResourceService::PostUpdate(float dt) 42 | { 43 | } 44 | 45 | void ResourceService::InitializeLoaders() 46 | { 47 | for (auto& [_, loader] : m_loadersMap) 48 | { 49 | loader->LoadSystemResources(); 50 | } 51 | } 52 | 53 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/STBIntegration.cpp: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include "stb_image.h" 3 | 4 | #define STB_IMAGE_WRITE_IMPLEMENTATION 5 | #include "stb_image_write.h" -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Resource/TextureResource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace engine 9 | { 10 | 11 | class TextureResource; 12 | 13 | class ENGINE_API TextureLoader final : public Loader 14 | { 15 | public: 16 | TextureLoader(); 17 | 18 | virtual void Update() override; 19 | 20 | virtual ResPtr Load(const fs::path& path, bool immediate) override; 21 | 22 | virtual ResPtr Get(const fs::path& path) const override; 23 | 24 | virtual void LoadSystemResources() override {} 25 | 26 | private: 27 | bool Load(const ResPtr& resource); 28 | 29 | std::mutex m_mutex; 30 | eastl::vector> m_loadingTasks; 31 | eastl::unordered_map> m_cache; 32 | }; 33 | 34 | class ENGINE_API TextureResource final : public Resource 35 | { 36 | public: 37 | TextureResource(const io::fs::path& path); 38 | virtual ~TextureResource() {} 39 | 40 | const ResPtr& Texture() const { return m_texture; } 41 | 42 | friend class TextureLoader; 43 | 44 | private: 45 | ResPtr m_texture; 46 | }; 47 | 48 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/ThreadService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine 7 | { 8 | 9 | class CustomThread; 10 | 11 | class ENGINE_API ThreadService final : public Service 12 | { 13 | public: 14 | 15 | ThreadService(); 16 | virtual ~ThreadService() override; 17 | 18 | virtual void Update(float dt) override; 19 | virtual void PostUpdate(float dt) override; 20 | 21 | template 22 | auto AddBackgroundTask(F&& f) 23 | { 24 | return m_bgExecutor->async(std::move(f)); 25 | } 26 | 27 | tf::Future AddBackgroundTaskflow(tf::Taskflow&& taskflow); 28 | 29 | tf::Future AddForegroundTaskflow(tf::Taskflow& taskflow); 30 | 31 | std::unique_ptr SpawnThread(std::string_view name); 32 | 33 | // Consider using SpawnThread at first time 34 | std::shared_ptr NamedExecutor(std::string_view name, int threadAmount) const; 35 | 36 | private: 37 | std::unique_ptr m_bgExecutor; 38 | std::unique_ptr m_fgExecutor; 39 | std::list m_taskflows; 40 | std::mutex m_mutex; 41 | }; 42 | 43 | class ENGINE_API CustomThread : core::NonCopyable 44 | { 45 | public: 46 | CustomThread(std::string_view name); 47 | ~CustomThread(); 48 | 49 | template 50 | auto AddTask(F&& f) 51 | { 52 | return m_executor->async(std::move(f)); 53 | } 54 | 55 | void WaitForAll(); 56 | 57 | friend class ThreadService; 58 | 59 | private: 60 | std::shared_ptr m_executor; 61 | }; 62 | 63 | } // namespace engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/Window/WindowService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace engine 9 | { 10 | 11 | // Service is responsible for current window drawing and input events processing 12 | class ENGINE_API WindowService final : public Service 13 | { 14 | public: 15 | WindowService(); 16 | virtual ~WindowService() override; 17 | 18 | virtual void Update(float dt) override; 19 | virtual void PostUpdate(float dt) override; 20 | 21 | glm::ivec2 FramebufferExtent() const; 22 | glm::vec2 WindowScale() const; 23 | 24 | GLFWwindow* Window() { return m_window; } 25 | const GLFWwindow* Window() const { return m_window; } 26 | 27 | // All keycodes are in GLFW documentation 28 | // https://www.glfw.org/docs/3.3/group__keys.html 29 | bool KeyButtonPressed(KeyButton button) const; 30 | 31 | // All mouse buttons are written here 32 | // https://www.glfw.org/docs/3.3/group__buttons.html 33 | bool MouseButtonPressed(MouseButton button) const; 34 | 35 | glm::vec2 MousePos() const; 36 | // Mouse position from the last frame 37 | glm::vec2 PrevMousePos() const; 38 | 39 | private: 40 | GLFWwindow* m_window = nullptr; 41 | }; 42 | 43 | } // namespace engine 44 | -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/World/WorldSerializer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RGameStudio/RightEngine/94a004aa9af31f41c2bf1ba7b1591b22581117e7/Src/Engine/Engine/Service/World/WorldSerializer.cpp -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/World/WorldSerializer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | 11 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Service/World/WorldService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace engine 8 | { 9 | 10 | struct WorldEntity 11 | { 12 | std::string m_uuid; 13 | std::string m_name; 14 | eastl::vector m_components; 15 | }; 16 | 17 | struct WorldData 18 | { 19 | int m_version = 0; 20 | std::string m_name; 21 | eastl::vector m_entities; 22 | }; 23 | 24 | class ENGINE_API WorldService : public Service 25 | { 26 | public: 27 | WorldService(); 28 | virtual ~WorldService() override; 29 | 30 | virtual void Update(float dt) override; 31 | virtual void PostUpdate(float dt) override; 32 | 33 | std::unique_ptr& CurrentWorld() { return m_world; } 34 | 35 | void SaveWorld(); 36 | 37 | WorldData CollectWorldData(const std::unique_ptr& world); 38 | 39 | private: 40 | std::unique_ptr m_world; 41 | }; 42 | 43 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/System/SkyboxSystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine 7 | { 8 | 9 | struct ENGINE_API SkyboxComponent : public ecs::Component 10 | { 11 | SkyboxComponent() = default; 12 | ~SkyboxComponent() = default; 13 | 14 | RPtr m_skyboxMaterial; 15 | RPtr m_environmentMap; 16 | }; 17 | 18 | class ENGINE_API SkyboxSystem : public ecs::System 19 | { 20 | public: 21 | SkyboxSystem(ecs::World* world); 22 | virtual ~SkyboxSystem() = default; 23 | 24 | virtual void Update(float dt) override; 25 | 26 | private: 27 | std::shared_ptr m_skyboxVB; 28 | }; 29 | 30 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/System/TransformSystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | RTTR_REGISTRATION 7 | { 8 | using namespace engine::ecs; 9 | 10 | engine::registration::System("engine::TransformSystem"); 11 | 12 | engine::registration::Component(IComponent::Type::ENGINE, "engine::TransformComponent") 13 | .Property("position", &engine::TransformComponent::m_position) 14 | .Property("rotation", &engine::TransformComponent::m_rotation) 15 | .Property("scale", &engine::TransformComponent::m_scale); 16 | } 17 | 18 | namespace engine 19 | { 20 | 21 | TransformSystem::TransformSystem(ecs::World* world) : System(world) 22 | { 23 | } 24 | 25 | void TransformSystem::Update(float dt) 26 | { 27 | PROFILER_CPU_ZONE; 28 | 29 | for (auto [e, t] : W()->View()) 30 | { 31 | const glm::mat4 rotationMatrix = glm::toMat4(glm::quat(t.m_rotation)); 32 | 33 | t.m_worldTransform = glm::translate(glm::mat4(1.0f), t.m_position) * rotationMatrix * glm::scale(glm::mat4(1.0f), t.m_scale); 34 | } 35 | } 36 | 37 | } // engine 38 | -------------------------------------------------------------------------------- /Src/Engine/Engine/System/TransformSystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace engine 11 | { 12 | 13 | struct ENGINE_API TransformComponent : public ecs::Component 14 | { 15 | TransformComponent() = default; 16 | 17 | glm::quat m_rotation = glm::identity(); 18 | glm::vec3 m_position = glm::vec3(0.0f, 0.0f, 0.0f); 19 | glm::vec3 m_scale = glm::vec3(1.0f, 1.0f, 1.0f); 20 | 21 | glm::mat4 m_worldTransform = glm::mat4(1.0f); 22 | }; 23 | 24 | class ENGINE_API TransformSystem : public ecs::System 25 | { 26 | public: 27 | TransformSystem(ecs::World* world); 28 | virtual ~TransformSystem() = default; 29 | 30 | virtual void Update(float dt) override; 31 | }; 32 | 33 | } // engine -------------------------------------------------------------------------------- /Src/Engine/Engine/Tests/Service/Config.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS 4 | #include -------------------------------------------------------------------------------- /Src/Engine/Engine/Tests/Service/Doctest.cpp: -------------------------------------------------------------------------------- 1 | #define DOCTEST_CONFIG_IMPLEMENT 2 | #include -------------------------------------------------------------------------------- /Src/Engine/Engine/Tests/Service/DoctestService.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace tests 8 | { 9 | 10 | DoctestService::DoctestService() 11 | { 12 | m_testThread = std::make_unique("Test thread"); 13 | } 14 | 15 | DoctestService::~DoctestService() 16 | { 17 | } 18 | 19 | void DoctestService::Update(float dt) 20 | { 21 | 22 | } 23 | 24 | void DoctestService::PostUpdate(float dt) 25 | { 26 | if (!m_waitFuture.valid()) 27 | { 28 | m_waitFuture = m_testThread->AddTask([this]() 29 | { 30 | return m_context->run(); 31 | }); 32 | } 33 | 34 | if (m_waitFuture.wait_for(std::chrono::nanoseconds(0)) == std::future_status::ready) 35 | { 36 | [[maybe_unused]] const auto status = m_waitFuture.get(); 37 | ENGINE_ASSERT(status == 0); 38 | engine::Instance().Stop(status); 39 | } 40 | } 41 | 42 | } // tests 43 | -------------------------------------------------------------------------------- /Src/Engine/Engine/Tests/Service/DoctestService.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace tests 9 | { 10 | 11 | class ENGINE_API DoctestService final : public engine::Service 12 | { 13 | public: 14 | DoctestService(); 15 | virtual ~DoctestService() override; 16 | 17 | virtual void Update(float dt) override; 18 | virtual void PostUpdate(float dt) override; 19 | 20 | void Context(std::unique_ptr&& context) 21 | { 22 | m_context = std::move(context); 23 | } 24 | 25 | private: 26 | std::unique_ptr m_context; 27 | std::unique_ptr m_testThread; 28 | std::future m_waitFuture; 29 | }; 30 | 31 | } // tests -------------------------------------------------------------------------------- /Src/Engine/Engine/Tests/Service/TestResource.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace tests 4 | { 5 | 6 | TestResourceLoader::TestResourceLoader() 7 | { 8 | } 9 | 10 | void TestResourceLoader::Update() 11 | { 12 | PROFILER_CPU_ZONE; 13 | } 14 | 15 | engine::ResPtr TestResourceLoader::Load(const engine::io::fs::path& path, bool immediate) 16 | { 17 | std::lock_guard l(m_mutex); 18 | 19 | if (auto res = Get(path)) 20 | { 21 | return res; 22 | } 23 | 24 | auto resource = engine::MakeResPtr(path); 25 | resource->m_status = engine::IResource::Status::LOADING; 26 | m_cache[path] = resource; 27 | 28 | auto& ts = engine::Instance().Service(); 29 | 30 | ts.AddBackgroundTask([this, resource]() 31 | { 32 | PROFILER_CPU_ZONE_NAME("Load test"); 33 | const auto result = Load(resource); 34 | resource->m_status = result ? engine::IResource::Status::READY : engine::IResource::Status::FAILED; 35 | }); 36 | 37 | return resource; 38 | } 39 | 40 | engine::ResPtr TestResourceLoader::Get(const engine::io::fs::path& path) const 41 | { 42 | if (const auto it = m_cache.find(path); it != m_cache.end()) 43 | { 44 | return it->second; 45 | } 46 | return {}; 47 | } 48 | 49 | bool TestResourceLoader::Load(const engine::ResPtr& resource) 50 | { 51 | return true; 52 | } 53 | 54 | TestResource::TestResource(const engine::io::fs::path& path) : Resource(path) 55 | { 56 | } 57 | 58 | } // tests -------------------------------------------------------------------------------- /Src/Engine/Engine/Tests/Service/TestResource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace tests 7 | { 8 | 9 | class TestResource; 10 | 11 | class ENGINE_API TestResourceLoader final : public engine::Loader 12 | { 13 | public: 14 | TestResourceLoader(); 15 | 16 | virtual void Update() override; 17 | 18 | virtual engine::ResPtr Load(const engine::io::fs::path& path, bool immediate) override; 19 | 20 | virtual engine::ResPtr Get(const engine::io::fs::path& path) const override; 21 | 22 | virtual void LoadSystemResources() override {} 23 | 24 | private: 25 | bool Load(const engine::ResPtr& resource); 26 | 27 | std::mutex m_mutex; 28 | eastl::vector> m_loadingTasks; 29 | eastl::unordered_map> m_cache; 30 | }; 31 | 32 | class ENGINE_API TestResource final : public engine::Resource 33 | { 34 | public: 35 | TestResource(const engine::io::fs::path& path); 36 | virtual ~TestResource() override {} 37 | 38 | friend class TestResourceLoader; 39 | }; 40 | 41 | } // tests -------------------------------------------------------------------------------- /Src/Engine/Engine/Tests/WorldTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | TEST_CASE("Simple entity manipulations") 7 | { 8 | constexpr std::string_view C_TEST_ENTITY_NAME = "Test Entity"; 9 | 10 | auto& ws = engine::Instance().Service(); 11 | auto& em = ws.CurrentWorld()->GetEntityManager(); 12 | 13 | const auto uuid = em->CreateEntity(C_TEST_ENTITY_NAME); 14 | em->Update(); 15 | const auto e = em->GetEntity(uuid); 16 | 17 | em->AddComponent(uuid, engine::MeshComponent()); 18 | CHECK_EQ(em->GetEntityInfo(uuid).m_name, C_TEST_ENTITY_NAME); 19 | CHECK_NE(em->TryGetComponent(uuid), nullptr); 20 | CHECK_NE(em->TryGetComponent(e), nullptr); 21 | 22 | em->RemoveComponent(uuid); 23 | CHECK_EQ(em->TryGetComponent(uuid), nullptr); 24 | 25 | em->RemoveEntity(uuid); 26 | em->Update(); 27 | CHECK_EQ(em->GetEntity(uuid), entt::entity()); 28 | } 29 | -------------------------------------------------------------------------------- /Src/Engine/Engine/Timer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace engine 7 | { 8 | 9 | class ENGINE_API Timer 10 | { 11 | public: 12 | using Clock = std::chrono::high_resolution_clock; 13 | 14 | inline Timer() 15 | { 16 | Start(); 17 | } 18 | 19 | inline void Start() 20 | { 21 | m_startTime = Clock::now(); 22 | m_running = true; 23 | } 24 | 25 | inline void Stop() 26 | { 27 | m_endTime = Clock::now(); 28 | m_running = false; 29 | } 30 | 31 | inline void Restart() 32 | { 33 | m_startTime = m_endTime = Clock::now(); 34 | m_running = true; 35 | } 36 | 37 | inline float TimeInMilliseconds() 38 | { 39 | std::chrono::time_point endTime; 40 | 41 | if (m_running) 42 | { 43 | endTime = std::chrono::high_resolution_clock::now(); 44 | } 45 | else 46 | { 47 | endTime = m_endTime; 48 | } 49 | 50 | return static_cast(std::chrono::duration_cast(endTime - m_startTime).count()); 51 | } 52 | 53 | inline float TimeInSeconds() 54 | { 55 | return TimeInMilliseconds() / 1000.0f; 56 | } 57 | 58 | private: 59 | std::chrono::time_point m_startTime; 60 | std::chrono::time_point m_endTime; 61 | bool m_running = false; 62 | }; 63 | 64 | } // engine -------------------------------------------------------------------------------- /Src/Engine/PCH.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include -------------------------------------------------------------------------------- /Src/EngineLauncher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(PROJECT_NAME EngineLauncher) 5 | 6 | file(GLOB_RECURSE SOURCE_FILES 7 | "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.cpp" 8 | "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.hpp" 9 | ) 10 | 11 | add_executable(${PROJECT_NAME} ${SOURCE_FILES}) 12 | target_link_libraries(${PROJECT_NAME} PRIVATE Engine) 13 | 14 | if (MSVC) 15 | set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/.bin/${CMAKE_BUILD_TYPE}") 16 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") 17 | endif() 18 | 19 | # Create source groups for each directory 20 | foreach(FILE ${SOURCE_FILES}) 21 | # Get the path relative to the source directory 22 | file(RELATIVE_PATH RELATIVE_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE}) 23 | # Get the directory of the file 24 | get_filename_component(DIR ${RELATIVE_FILE} DIRECTORY) 25 | # Create the source group 26 | source_group(${DIR} FILES ${FILE}) 27 | endforeach() -------------------------------------------------------------------------------- /Src/EngineLauncher/Src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) 5 | { 6 | engine::Engine engine(argc, argv); 7 | return engine.Run(); 8 | } 9 | -------------------------------------------------------------------------------- /Src/RHI/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | file(GLOB_RECURSE SOURCE_FILES 6 | "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.cpp" 7 | "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.hpp" 8 | "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.h" 9 | ) 10 | 11 | find_package(glslang REQUIRED CONFIG) 12 | find_package(spirv-cross REQUIRED) 13 | find_package(imgui REQUIRED) 14 | find_package(VulkanHeaders REQUIRED) 15 | find_package(Vulkan REQUIRED) 16 | 17 | add_subdirectory(Lib/vk-tools/) 18 | add_subdirectory(Lib/VulkanMemoryAllocator) 19 | set_target_properties(vk-tools PROPERTIES FOLDER ${THIRD_PARTY_PROJECT_DIR_NAME}) 20 | set_target_properties(VulkanMemoryAllocator PROPERTIES FOLDER ${THIRD_PARTY_PROJECT_DIR_NAME}) 21 | 22 | add_library(RHI STATIC ${SOURCE_FILES}) 23 | 24 | target_link_libraries(RHI PUBLIC 25 | Core 26 | spirv-cross::spirv-cross 27 | glslang::glslang 28 | glslang::SPIRV 29 | imgui::imgui 30 | vulkan-headers::vulkan-headers 31 | ${Vulkan_LIBRARY} 32 | VulkanMemoryAllocator 33 | vk-tools 34 | ) 35 | 36 | target_compile_definitions(RHI PRIVATE RHI_EXPORT) 37 | target_precompile_headers(RHI PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Src/PCH.hpp") 38 | 39 | target_include_directories(RHI PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/Src/Public") 40 | target_include_directories(RHI PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Src/") 41 | target_include_directories(RHI PRIVATE "${CMAKE_SOURCE_DIR}/Lib/VulkanMemoryAllocator/include") 42 | target_include_directories(RHI PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/Lib/vk-tools") 43 | 44 | target_link_directories(RHI PRIVATE ${CMAKE_BINARY_DIR}/.bin) 45 | 46 | # Create source groups for each directory 47 | foreach(FILE ${SOURCE_FILES}) 48 | # Get the path relative to the source directory 49 | file(RELATIVE_PATH RELATIVE_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE}) 50 | # Get the directory of the file 51 | get_filename_component(DIR ${RELATIVE_FILE} DIRECTORY) 52 | # Create the source group 53 | source_group(${DIR} FILES ${FILE}) 54 | endforeach() 55 | -------------------------------------------------------------------------------- /Src/RHI/Lib/VulkanMemoryAllocator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.17) 2 | project(VulkanMemoryAllocator) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | if (WIN32) 7 | set(Vulkan_LIBRARY $ENV{Vulkan_LIBRARY}) 8 | find_package(Vulkan REQUIRED) 9 | elseif (APPLE) 10 | find_package(Vulkan REQUIRED) 11 | endif() 12 | 13 | add_library(VulkanMemoryAllocator STATIC vk_mem_alloc.cpp) 14 | 15 | target_include_directories(VulkanMemoryAllocator PRIVATE ${Vulkan_INCLUDE_DIR}) 16 | target_include_directories(VulkanMemoryAllocator PUBLIC include) 17 | 18 | if (${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") 19 | target_compile_options(VulkanMemoryAllocator PRIVATE 20 | /WX- 21 | /MP # Enable parallel compilation 22 | /Gy # Enable function level linking 23 | /Gw # Optimize Global Data 24 | /GR- # Disable Run-Time Type Information 25 | /Oi # Enable intrinsics, irrelevant of optimization level 26 | /fp:fast # Enable fast floating point arithmetics by default 27 | /Zc:__cplusplus # Enable reporting real C++ version by __cplusplus macro - necessary for some libraries 28 | /Zc:lambda # Enable updated lambda processor 29 | 30 | /wd4189 31 | /wd4127 32 | /wd4324 33 | ) 34 | endif() 35 | 36 | if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") 37 | target_compile_options(VulkanMemoryAllocator PRIVATE 38 | -w # Disable all warnings 39 | ) 40 | endif() 41 | -------------------------------------------------------------------------------- /Src/RHI/Lib/VulkanMemoryAllocator/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Src/RHI/Lib/VulkanMemoryAllocator/vk_mem_alloc.cpp: -------------------------------------------------------------------------------- 1 | #define VMA_IMPLEMENTATION 2 | #include -------------------------------------------------------------------------------- /Src/RHI/Lib/vk-tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.17) 2 | project(vk-tools) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | if (WIN32) 7 | set(Vulkan_LIBRARY $ENV{Vulkan_LIBRARY}) 8 | find_package(Vulkan REQUIRED) 9 | elseif (APPLE) 10 | find_package(Vulkan REQUIRED) 11 | endif() 12 | 13 | set(VK_TOOLS_SRC 14 | vk-tools/VulkanTools.cpp 15 | ) 16 | 17 | add_library(vk-tools STATIC ${VK_TOOLS_SRC}) 18 | 19 | target_include_directories(vk-tools PRIVATE ${Vulkan_INCLUDE_DIR}) -------------------------------------------------------------------------------- /Src/RHI/Lib/vk-tools/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Sascha Willems 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Src/RHI/Src/Device.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vulkan/VulkanDevice.hpp" 3 | #include "Vulkan/VulkanContext.hpp" 4 | 5 | namespace rhi 6 | { 7 | std::shared_ptr Device::Create(const std::shared_ptr& context) 8 | { 9 | static bool created = false; 10 | if (!created) 11 | { 12 | created = true; 13 | return std::make_shared(std::static_pointer_cast(context)); 14 | } 15 | RHI_ASSERT(false); 16 | return nullptr; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Src/RHI/Src/IContext.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vulkan/VulkanContext.hpp" 3 | 4 | namespace rhi 5 | { 6 | 7 | namespace vulkan 8 | { 9 | 10 | std::shared_ptr CreateContext(VulkanInitContext&& ctx) 11 | { 12 | return std::make_shared(std::move(ctx)); 13 | } 14 | 15 | } // namespace vulkan 16 | 17 | } // namespace rhi -------------------------------------------------------------------------------- /Src/RHI/Src/IImguiProvider.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace rhi::imgui 5 | { 6 | 7 | std::shared_ptr IImguiProvider::Create() 8 | { 9 | static bool created = false; 10 | RHI_ASSERT(!created); 11 | created = true; 12 | 13 | return std::make_shared(); 14 | } 15 | 16 | } // rhi::imgui -------------------------------------------------------------------------------- /Src/RHI/Src/PCH.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Assert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef R_ENABLE_ASSERTS 6 | #define RHI_ASSERT(x) do { if(!(x)) { core::Assert("RHI", #x); } } while(false) 7 | #define RHI_ASSERT_WITH_MESSAGE(x, ...) do { if(!(x)) { core::Assert("RHI", #x, __VA_ARGS__); } } while(false) 8 | #else 9 | #define RHI_ASSERT(x) 10 | #define RHI_ASSERT_WITH_MESSAGE(x, ...) 11 | #endif -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Buffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace rhi 9 | { 10 | 11 | class RHI_API Buffer : public core::NonCopyable 12 | { 13 | public: 14 | Buffer(const BufferDescriptor& descriptor) : m_descriptor(descriptor) 15 | {} 16 | 17 | virtual ~Buffer() = default; 18 | 19 | virtual void* Map() const = 0; 20 | virtual void UnMap() const = 0; 21 | 22 | inline void CopyToBuffer(const void* ptr, size_t size) 23 | { 24 | std::lock_guard l(m_copyMutex); 25 | 26 | RHI_ASSERT(size <= m_descriptor.m_size); 27 | 28 | auto* dst = Map(); 29 | std::memcpy(dst, ptr, size); 30 | UnMap(); 31 | } 32 | 33 | const BufferDescriptor& Descriptor() const 34 | { return m_descriptor; } 35 | 36 | protected: 37 | BufferDescriptor m_descriptor; 38 | std::mutex m_copyMutex; 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/BufferDescriptor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi 6 | { 7 | enum class BufferType : uint8_t 8 | { 9 | VERTEX = Bit(0), 10 | TRANSFER_SRC = Bit(1), 11 | TRANSFER_DST = Bit(2), 12 | INDEX = Bit(3), 13 | UNIFORM = Bit(4), 14 | CONSTANT = Bit(5), 15 | }; 16 | 17 | struct BufferDescriptor 18 | { 19 | std::string m_name; 20 | uint32_t m_size; 21 | BufferType m_type; 22 | MemoryType m_memoryType; 23 | }; 24 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/ComputeState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi 6 | { 7 | struct RHI_API ComputeState 8 | {}; 9 | } // rhi -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Config.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Platform-specific macros for importing/exporting symbols 4 | #if defined(R_OS_WIN32) & 0 5 | 6 | #ifdef RHI_EXPORT 7 | // We are building the library, so export the symbols 8 | #define RHI_API __declspec(dllexport) 9 | #else 10 | // We are using the library, so import the symbols 11 | #define RHI_API __declspec(dllimport) 12 | #endif 13 | 14 | #else 15 | #define RHI_API 16 | #endif -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/GPUMaterial.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi 7 | { 8 | 9 | class RHI_API GPUMaterial 10 | { 11 | public: 12 | virtual ~GPUMaterial() = default; 13 | 14 | virtual void SetTexture(const std::shared_ptr& texture, uint8_t slot, uint8_t mipLevel = 0) = 0; 15 | virtual void SetBuffer(const std::shared_ptr& buffer, 16 | uint8_t slot, 17 | ShaderStage stage, 18 | int offset = 0) = 0; 19 | 20 | virtual void Sync() = 0; 21 | 22 | protected: 23 | bool m_dirty = false; 24 | }; 25 | 26 | } // rhi -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Helpers.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi::helpers 6 | { 7 | 8 | inline uint8_t FormatComponents(Format format) 9 | { 10 | RHI_ASSERT(format != Format::NONE); 11 | 12 | switch (format) 13 | { 14 | case Format::R32_SFLOAT: return 1; 15 | case Format::R32_UINT: return 1; 16 | case Format::R8_UINT: return 1; 17 | case Format::RG16_SFLOAT: return 2; 18 | case Format::RGB8_UINT: return 3; 19 | case Format::RGBA8_UINT: return 4; 20 | case Format::RGBA8_UNORM: return 4; 21 | case Format::RGB16_SFLOAT: return 3; 22 | case Format::RG32_SFLOAT: return 2; 23 | case Format::RGB32_SFLOAT: return 3; 24 | case Format::RGBA16_SFLOAT: return 4; 25 | case Format::RGBA32_SFLOAT: return 4; 26 | case Format::RGBA16_UNORM: return 4; 27 | case Format::RGB16_UNORM: return 3; 28 | case Format::BGRA8_UNORM: return 4; 29 | case Format::R8_SRGB: return 1; 30 | case Format::RGB8_SRGB: return 3; 31 | case Format::RGBA8_SRGB: return 4; 32 | case Format::BGRA8_SRGB: return 4; 33 | case Format::D24_UNORM_S8_UINT: return 1; 34 | case Format::D32_SFLOAT_S8_UINT: return 1; 35 | case Format::D32_SFLOAT: return 1; 36 | } 37 | 38 | RHI_ASSERT(false); 39 | return 0; 40 | } 41 | 42 | inline std::string_view FormatToString(Format format) 43 | { 44 | switch (format) 45 | { 46 | case Format::R8_UINT: return "R8_UINT"; 47 | case Format::RGBA8_UINT: return "RGBA8_UINT"; 48 | case Format::RGBA8_UNORM: return "RGBA8_UNORM"; 49 | case Format::RGBA32_SFLOAT: return "RGBA32_SFLOAT"; 50 | } 51 | 52 | RHI_ASSERT(false); 53 | return 0; 54 | } 55 | 56 | } // rhi::helpers 57 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/IContext.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace rhi 10 | { 11 | 12 | class RHI_API IContext : public core::NonCopyable 13 | { 14 | public: 15 | virtual ~IContext() = default; 16 | 17 | protected: 18 | IContext() = default; 19 | }; 20 | 21 | namespace vulkan 22 | { 23 | 24 | // To be filled by user 25 | struct VulkanInitContext 26 | { 27 | using VulkanSurfaceFn = std::function; 28 | 29 | VulkanSurfaceFn m_surfaceConstructor; 30 | eastl::vector m_requiredExtensions; 31 | }; 32 | 33 | std::shared_ptr RHI_API CreateContext(VulkanInitContext&& ctx); 34 | 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/IImguiProvider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace rhi::imgui 9 | { 10 | 11 | class RHI_API IImguiProvider : public core::NonCopyable 12 | { 13 | public: 14 | virtual ~IImguiProvider() {} 15 | 16 | virtual void Begin() = 0; 17 | virtual void End() = 0; 18 | [[nodiscard]] virtual ImTextureID Image(const std::shared_ptr& texture, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1) = 0; 19 | 20 | // Removes image of the internal cache 21 | virtual void RemoveImage(const std::shared_ptr& texture) = 0; 22 | virtual void DestroyFontTexture() = 0; 23 | 24 | void SetRenderPass(const std::shared_ptr& pass) { m_renderPass = pass; } 25 | 26 | static std::shared_ptr Create(); 27 | 28 | protected: 29 | std::shared_ptr m_renderPass; 30 | }; 31 | 32 | } // rhi::imgui -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Log.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi::log 6 | { 7 | constexpr const std::string_view C_RHI_LOG_PREFIX = "[RHI] "; 8 | 9 | template 10 | void debug(std::string_view message, Args... args) 11 | { 12 | core::log::debug(std::string(C_RHI_LOG_PREFIX).append(message), std::forward(args)...); 13 | } 14 | 15 | template 16 | void info(std::string_view message, Args... args) 17 | { 18 | core::log::info(std::string(C_RHI_LOG_PREFIX).append(message), std::forward(args)...); 19 | } 20 | 21 | template 22 | void warning(std::string_view message, Args... args) 23 | { 24 | core::log::warning(std::string(C_RHI_LOG_PREFIX).append(message), std::forward(args)...); 25 | } 26 | 27 | template 28 | void error(std::string_view message, Args... args) 29 | { 30 | core::log::error(std::string(C_RHI_LOG_PREFIX).append(message), std::forward(args)...); 31 | } 32 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Pipeline.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace rhi 10 | { 11 | 12 | class RHI_API Pipeline 13 | { 14 | public: 15 | virtual ~Pipeline() = default; 16 | 17 | const PipelineDescriptor& Descriptor() const { return m_descriptor; } 18 | 19 | inline uint32_t VertexCount(const std::shared_ptr& buffer) const 20 | { 21 | const auto& desc = buffer->Descriptor(); 22 | RHI_ASSERT(desc.m_type == BufferType::VERTEX); 23 | return desc.m_size / m_descriptor.m_shader->Descriptor().m_reflection.m_inputLayout.Stride(); 24 | } 25 | 26 | protected: 27 | PipelineDescriptor m_descriptor; 28 | 29 | Pipeline(const PipelineDescriptor& descriptor) : m_descriptor(descriptor) 30 | { 31 | RHI_ASSERT(descriptor.m_shader); 32 | if (descriptor.m_compute) 33 | { 34 | RHI_ASSERT(descriptor.m_computePass); 35 | } 36 | } 37 | }; 38 | 39 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/PipelineDescriptor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi 6 | { 7 | 8 | class Shader; 9 | class RenderPass; 10 | 11 | enum class CompareOp : uint8_t 12 | { 13 | LESS = 0, 14 | LESS_OR_EQUAL, 15 | GREATER 16 | }; 17 | 18 | enum class CullMode : uint8_t 19 | { 20 | NONE = 0, 21 | BACK, 22 | FRONT 23 | }; 24 | 25 | struct ComputePass 26 | { 27 | eastl::vector> m_textures; 28 | eastl::vector> m_storageTextures; 29 | }; 30 | 31 | struct PipelineDescriptor 32 | { 33 | std::shared_ptr m_shader; 34 | std::shared_ptr m_computePass; 35 | std::shared_ptr m_pass; // ignored in compute 36 | CompareOp m_depthCompareOp = CompareOp::LESS; // ignored in compute 37 | CullMode m_cullMode = CullMode::BACK; // ignored in compute 38 | bool m_offscreen = true; // ignored in compute 39 | bool m_compute = false; 40 | }; 41 | 42 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/RHI.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi 6 | { 7 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/RenderPass.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi 7 | { 8 | 9 | class RHI_API RenderPass 10 | { 11 | public: 12 | virtual ~RenderPass() = default; 13 | 14 | bool HasDepth() const { return m_descriptor.m_depthStencilAttachment.m_texture != nullptr; } 15 | 16 | const RenderPassDescriptor& Descriptor() const { return m_descriptor; } 17 | 18 | protected: 19 | RenderPassDescriptor m_descriptor; 20 | 21 | RenderPass(const RenderPassDescriptor& descriptor) : m_descriptor(descriptor) 22 | {} 23 | }; 24 | 25 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/RenderPassDescriptor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace rhi 9 | { 10 | 11 | enum class AttachmentLoadOperation : uint8_t 12 | { 13 | UNDEFINED = 0, 14 | LOAD, 15 | CLEAR 16 | }; 17 | 18 | enum class AttachmentStoreOperation : uint8_t 19 | { 20 | UNDEFINED = 0, 21 | STORE 22 | }; 23 | 24 | struct ClearValue 25 | { 26 | glm::vec4 m_color{ 0.0f, 0.0f, 0.0f, 1.0f }; 27 | float m_depth = 1.0f; 28 | uint32_t m_stencil = 0; 29 | }; 30 | 31 | struct AttachmentDescriptor 32 | { 33 | std::shared_ptr m_texture; 34 | ClearValue m_clearValue; 35 | AttachmentLoadOperation m_loadOperation = AttachmentLoadOperation::CLEAR; 36 | AttachmentStoreOperation m_storeOperation = AttachmentStoreOperation::STORE; 37 | }; 38 | 39 | struct RenderPassDescriptor 40 | { 41 | glm::ivec2 m_extent{ 0, 0 }; 42 | eastl::vector m_colorAttachments; 43 | AttachmentDescriptor m_depthStencilAttachment; 44 | std::string m_name; 45 | }; 46 | 47 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Sampler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi 7 | { 8 | class RHI_API Sampler 9 | { 10 | public: 11 | virtual ~Sampler() = default; 12 | 13 | protected: 14 | SamplerDescriptor m_descriptor; 15 | 16 | Sampler(const SamplerDescriptor& desc) : m_descriptor(desc) 17 | {} 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/SamplerDescriptor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi 6 | { 7 | enum class SamplerFilter : uint8_t 8 | { 9 | NEAREST = 0, 10 | LINEAR 11 | }; 12 | 13 | enum class AddressMode : uint8_t 14 | { 15 | REPEAT = 0, 16 | CLAMP_TO_EDGE, 17 | CLAMP_TO_BORDER 18 | }; 19 | 20 | struct SamplerDescriptor 21 | { 22 | float m_minLod = 0.0f; 23 | float m_maxLod = 1.0f; 24 | SamplerFilter m_minFilter = SamplerFilter::LINEAR; 25 | SamplerFilter m_magFilter = SamplerFilter::LINEAR; 26 | SamplerFilter m_mipMapFilter = SamplerFilter::LINEAR; 27 | AddressMode m_addressModeU = AddressMode::REPEAT; 28 | AddressMode m_addressModeV = AddressMode::REPEAT; 29 | AddressMode m_addressModeW = AddressMode::REPEAT; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Shader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace rhi 8 | { 9 | 10 | class RHI_API Shader 11 | { 12 | public: 13 | virtual ~Shader() = default; 14 | 15 | const ShaderDescriptor& Descriptor() const { return m_descriptor; } 16 | 17 | protected: 18 | ShaderDescriptor m_descriptor; 19 | 20 | Shader(const ShaderDescriptor& descriptor) : m_descriptor(descriptor) 21 | {} 22 | }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/ShaderCompiler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace rhi 8 | { 9 | 10 | struct CompiledShaderData 11 | { 12 | ShaderReflection m_reflection; 13 | eastl::unordered_map m_stageBlob; 14 | bool m_valid = false; 15 | }; 16 | 17 | // API assumes that there will be only one instance of shader compiler in application, please follow that rule! 18 | class RHI_API ShaderCompiler 19 | { 20 | public: 21 | // TODO: Implement options: switch Vulkan API version, shader code version, etc 22 | struct Options 23 | {}; 24 | 25 | ShaderCompiler(Options options) : m_options(options) 26 | {} 27 | 28 | virtual ~ShaderCompiler() = default; 29 | 30 | // TODO: Implement compiling from already giving shader text 31 | // Path must be absolute 32 | virtual CompiledShaderData Compile(std::string_view path, ShaderType type = ShaderType::FX) = 0; 33 | 34 | protected: 35 | Options m_options; 36 | }; 37 | 38 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/ShaderDescriptor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace rhi 11 | { 12 | 13 | enum class ShaderType : uint8_t 14 | { 15 | NONE = 0, 16 | FX, 17 | COMPUTE 18 | }; 19 | 20 | enum class ShaderStage : uint8_t 21 | { 22 | NONE = 0, 23 | VERTEX, 24 | FRAGMENT, 25 | COMPUTE 26 | }; 27 | 28 | inline std::string_view ShaderStageToString(ShaderStage stage) 29 | { 30 | switch (stage) 31 | { 32 | case ShaderStage::NONE: return "None"; 33 | case ShaderStage::VERTEX: return "Vertex"; 34 | case ShaderStage::FRAGMENT: return "Fragment"; 35 | case ShaderStage::COMPUTE: return "Compute"; 36 | default: 37 | { 38 | RHI_ASSERT(false); 39 | return ""; 40 | } 41 | } 42 | } 43 | 44 | struct ShaderReflection 45 | { 46 | struct BufferInfo 47 | { 48 | std::string m_name; 49 | uint32_t m_size = 0; 50 | BufferType m_type; 51 | ShaderStage m_stage = ShaderStage::NONE; 52 | }; 53 | 54 | struct TextureInfo 55 | { 56 | std::string m_name; 57 | uint8_t m_slot; 58 | bool m_isCubemap = false; 59 | 60 | inline bool operator<(const TextureInfo& other) const 61 | { 62 | return m_slot < other.m_slot; 63 | } 64 | }; 65 | 66 | using BufferMap = eastl::unordered_map; 67 | using TextureList = eastl::vector_set; 68 | 69 | BufferMap m_bufferMap; 70 | BufferMap m_storageBufferMap; 71 | // Only in vertex shader now 72 | BufferInfo m_pushConstant; 73 | TextureList m_textures; 74 | TextureList m_storageImages; 75 | VertexBufferLayout m_inputLayout; 76 | // Only in fragment shader now 77 | uint8_t m_outputAmount; 78 | }; 79 | 80 | struct ShaderDescriptor 81 | { 82 | std::string m_name; 83 | std::string m_path; 84 | ShaderType m_type = ShaderType::NONE; 85 | ShaderReflection m_reflection; 86 | 87 | using BlobMap = eastl::unordered_map; 88 | 89 | BlobMap m_blobByStage; 90 | }; 91 | 92 | } 93 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Texture.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace rhi 8 | { 9 | 10 | class RHI_API Texture 11 | { 12 | public: 13 | virtual ~Texture() = default; 14 | 15 | const TextureDescriptor& Descriptor() const { return m_descriptor; } 16 | 17 | const std::shared_ptr& GetSampler() const { return m_sampler; } 18 | 19 | uint16_t Width() const { return m_descriptor.m_width; } 20 | uint16_t Height() const { return m_descriptor.m_height; } 21 | 22 | inline uint8_t CalculateMipCount() 23 | { 24 | return (uint8_t)glm::floor(glm::log2(glm::min(Width(), Height()))) + 1; 25 | } 26 | 27 | protected: 28 | struct InternalParams 29 | { 30 | uint8_t m_mipLevels = 0; 31 | }; 32 | 33 | TextureDescriptor m_descriptor; 34 | InternalParams m_params; 35 | std::shared_ptr m_sampler; 36 | 37 | Texture(const TextureDescriptor& desc, const std::shared_ptr& sampler) : m_descriptor(desc), m_sampler(sampler) 38 | { 39 | if (m_descriptor.m_mipmapped) 40 | { 41 | m_params.m_mipLevels = CalculateMipCount(); 42 | } 43 | else 44 | { 45 | m_params.m_mipLevels = 1; 46 | } 47 | } 48 | }; 49 | 50 | } // rhi 51 | -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/TextureDescriptor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace rhi 9 | { 10 | 11 | enum class TextureType : uint8_t 12 | { 13 | NONE, 14 | TEXTURE_2D, 15 | TEXTURE_2D_ARRAY, 16 | TEXTURE_CUBEMAP 17 | }; 18 | 19 | constexpr uint8_t C_MAX_MIPMAP = 255; 20 | 21 | struct RHI_API TextureDescriptor 22 | { 23 | uint16_t m_width = 0; 24 | uint16_t m_height = 0; 25 | uint8_t m_layersAmount = 1; 26 | bool m_mipmapped = false; 27 | Format m_format = Format::NONE; 28 | TextureType m_type = TextureType::NONE; 29 | 30 | // Texture size in bytes 31 | inline uint32_t Size() const 32 | { 33 | const uint32_t size = m_width * m_height; 34 | return PixelSize() * size; 35 | } 36 | 37 | // One pixel size in bytes 38 | inline uint8_t PixelSize() const 39 | { 40 | const auto components = helpers::FormatComponents(m_format); 41 | RHI_ASSERT(m_format != Format::NONE && m_width > 0 && m_height > 0 && components > 0); 42 | 43 | switch (m_format) 44 | { 45 | case Format::R8_UINT: 46 | case Format::RGB8_UINT: 47 | case Format::RGBA8_UINT: 48 | case Format::RGBA8_UNORM: 49 | return sizeof(uint8_t) * components; 50 | case Format::RGB16_SFLOAT: 51 | case Format::RGBA16_SFLOAT: 52 | return sizeof(float) / 2 * components; 53 | case Format::RGB32_SFLOAT: 54 | case Format::RGBA32_SFLOAT: 55 | return sizeof(float) * components; 56 | case Format::R8_SRGB: 57 | case Format::RGB8_SRGB: 58 | case Format::RGBA8_SRGB: 59 | return sizeof(uint8_t) * components; 60 | case Format::BGRA8_UNORM: 61 | return sizeof(float) * components; 62 | default: 63 | RHI_ASSERT(false); 64 | return 0; 65 | } 66 | } 67 | 68 | inline bool operator==(const TextureDescriptor& otherSpec) 69 | { 70 | return m_width == otherSpec.m_width 71 | && m_height == otherSpec.m_height 72 | && helpers::FormatComponents(m_format) == helpers::FormatComponents(otherSpec.m_format) 73 | && m_format == otherSpec.m_format; 74 | } 75 | }; 76 | 77 | } // rhi -------------------------------------------------------------------------------- /Src/RHI/Src/Public/RHI/Types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi 6 | { 7 | 8 | constexpr uint32_t Bit(uint32_t x) 9 | { 10 | return 1 << x; 11 | } 12 | 13 | enum class MemoryType : uint8_t 14 | { 15 | CPU_ONLY, 16 | CPU_GPU, 17 | GPU_ONLY 18 | }; 19 | 20 | enum class Format : uint8_t 21 | { 22 | NONE, 23 | R32_SFLOAT, 24 | R32_UINT, 25 | R8_UINT, 26 | RG16_SFLOAT, 27 | RGB8_UINT, 28 | RGBA8_UINT, 29 | RGBA8_UNORM, 30 | RGB16_SFLOAT, 31 | RG32_SFLOAT, 32 | RGB32_SFLOAT, 33 | RGBA16_SFLOAT, 34 | RGBA32_SFLOAT, 35 | RGBA16_UNORM, 36 | RGB16_UNORM, 37 | BGRA8_UNORM, 38 | 39 | //sRGB formats 40 | R8_SRGB, 41 | RGB8_SRGB, 42 | RGBA8_SRGB, 43 | BGRA8_SRGB, 44 | 45 | //Depth buffer formats 46 | D24_UNORM_S8_UINT, 47 | D32_SFLOAT_S8_UINT, 48 | D32_SFLOAT 49 | }; 50 | 51 | } -------------------------------------------------------------------------------- /Src/RHI/Src/RHI.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace rhi 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /Src/RHI/Src/ShaderCompiler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace rhi 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/CommandBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandBuffer.hpp" 2 | #include "VulkanDevice.hpp" 3 | 4 | namespace rhi::vulkan 5 | { 6 | 7 | CommandBuffer::CommandBuffer() 8 | { 9 | VkCommandBufferAllocateInfo allocInfo{}; 10 | allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 11 | allocInfo.commandPool = VulkanDevice::s_ctx.m_instance->CommandPool(); 12 | allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 13 | allocInfo.commandBufferCount = 1; 14 | 15 | [[maybe_unused]] auto res = vkAllocateCommandBuffers(VulkanDevice::s_ctx.m_device, &allocInfo, &m_handle); 16 | 17 | RHI_ASSERT(res == VK_SUCCESS); 18 | } 19 | 20 | CommandBuffer::~CommandBuffer() 21 | { 22 | } 23 | 24 | void CommandBuffer::Begin(bool oneTimeUsage) 25 | { 26 | VkCommandBufferBeginInfo beginInfo{}; 27 | beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 28 | if (oneTimeUsage) 29 | { 30 | beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 31 | } 32 | 33 | [[maybe_unused]] const auto result = vkBeginCommandBuffer(m_handle, &beginInfo); 34 | RHI_ASSERT(result == VK_SUCCESS); 35 | } 36 | 37 | void CommandBuffer::End() 38 | { 39 | [[maybe_unused]] const auto result = vkEndCommandBuffer(m_handle); 40 | RHI_ASSERT(result == VK_SUCCESS); 41 | } 42 | 43 | void CommandBuffer::Reset() 44 | { 45 | [[maybe_unused]] const auto result = vkResetCommandBuffer(m_handle, 0); 46 | RHI_ASSERT(result == VK_SUCCESS); 47 | } 48 | 49 | } // namespace rhi::vulkan 50 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/CommandBuffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | class RHI_API CommandBuffer 10 | { 11 | public: 12 | CommandBuffer(); 13 | 14 | ~CommandBuffer(); 15 | 16 | using PayloadFn = std::function; 17 | 18 | inline void Push(PayloadFn&& fn) { fn(m_handle); } 19 | 20 | void Begin(bool oneTimeUsage = true); 21 | void End(); 22 | void Reset(); 23 | 24 | VkCommandBuffer Raw() { return m_handle; } 25 | 26 | private: 27 | VkCommandBuffer m_handle; 28 | }; 29 | 30 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/Fence.cpp: -------------------------------------------------------------------------------- 1 | #include "Fence.hpp" 2 | #include "VulkanDevice.hpp" 3 | 4 | namespace rhi::vulkan 5 | { 6 | 7 | Fence::Fence(bool signaled) 8 | { 9 | VkFenceCreateInfo fenceInfo{}; 10 | fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 11 | fenceInfo.flags = signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0; 12 | 13 | [[maybe_unused]] auto res = vkCreateFence(VulkanDevice::s_ctx.m_device, &fenceInfo, nullptr, &m_handle); 14 | 15 | RHI_ASSERT(res == VK_SUCCESS); 16 | } 17 | 18 | Fence::~Fence() 19 | { 20 | vkDestroyFence(VulkanDevice::s_ctx.m_device, m_handle, nullptr); 21 | } 22 | 23 | void Fence::Wait() 24 | { 25 | vkWaitForFences(VulkanDevice::s_ctx.m_device, 1, &m_handle, VK_TRUE, UINT64_MAX); 26 | } 27 | 28 | void Fence::Reset() 29 | { 30 | vkResetFences(VulkanDevice::s_ctx.m_device, 1, &m_handle); 31 | } 32 | 33 | bool Fence::IsSignaled() 34 | { 35 | const auto res = vkGetFenceStatus(VulkanDevice::s_ctx.m_device, m_handle); 36 | 37 | switch (res) 38 | { 39 | case VK_SUCCESS: return true; 40 | case VK_NOT_READY: return false; 41 | default: 42 | { 43 | RHI_ASSERT(false); 44 | return false; 45 | } 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/Fence.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | class RHI_API Fence 10 | { 11 | public: 12 | Fence(bool signaled = false); 13 | ~Fence(); 14 | 15 | void Wait(); 16 | void Reset(); 17 | bool IsSignaled(); 18 | 19 | VkFence* Raw() { return &m_handle; } 20 | 21 | private: 22 | VkFence m_handle; 23 | }; 24 | 25 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/Imgui/VulkanImguiProvider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace rhi::vulkan::imgui 8 | { 9 | 10 | class RHI_API VulkanImguiProvider : public rhi::imgui::IImguiProvider 11 | { 12 | public: 13 | VulkanImguiProvider(); 14 | virtual ~VulkanImguiProvider() override; 15 | 16 | virtual void Begin() override; 17 | virtual void End() override; 18 | virtual ImTextureID Image(const std::shared_ptr& texture, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1) override; 19 | virtual void RemoveImage(const std::shared_ptr& texture) override; 20 | virtual void DestroyFontTexture() override; 21 | 22 | private: 23 | void CreateDescriptorPool(); 24 | 25 | VkDescriptorSet GetDescriptorSet(const std::shared_ptr& texture); 26 | 27 | VkDescriptorPool m_descriptorPool = nullptr; 28 | eastl::unordered_map m_imageViewToDescSet; 29 | std::shared_mutex m_imageMapMutex; 30 | }; 31 | 32 | } // rhi::vulkan::imgui -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/Semaphore.cpp: -------------------------------------------------------------------------------- 1 | #include "Semaphore.hpp" 2 | #include "VulkanDevice.hpp" 3 | 4 | namespace rhi::vulkan 5 | { 6 | 7 | Semaphore::Semaphore() 8 | { 9 | VkSemaphoreCreateInfo semaphoreInfo{}; 10 | semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 11 | 12 | [[maybe_unused]] auto res = vkCreateSemaphore(VulkanDevice::s_ctx.m_device, &semaphoreInfo, nullptr, &m_handle); 13 | RHI_ASSERT(res == VK_SUCCESS); 14 | } 15 | 16 | Semaphore::~Semaphore() 17 | { 18 | vkDestroySemaphore(VulkanDevice::s_ctx.m_device, m_handle, nullptr); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/Semaphore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | class RHI_API Semaphore 10 | { 11 | public: 12 | Semaphore(); 13 | ~Semaphore(); 14 | 15 | VkSemaphore* Raw() { return &m_handle; } 16 | 17 | private: 18 | VkSemaphore m_handle; 19 | }; 20 | 21 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/Swapchain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Semaphore.hpp" 6 | #include 7 | #include 8 | 9 | namespace rhi::vulkan 10 | { 11 | 12 | struct CommandBufferSync; 13 | 14 | struct SwapchainDescriptor 15 | { 16 | VkPresentModeKHR m_presentMode; 17 | VkSurfaceKHR m_surface; 18 | glm::uvec2 m_extent; 19 | }; 20 | 21 | class RHI_API Swapchain 22 | { 23 | public: 24 | Swapchain(const SwapchainDescriptor& desc); 25 | ~Swapchain(); 26 | 27 | uint32_t AcquireNextImage(VkDevice device, VkSemaphore presentSemaphore); 28 | inline VkImage Image(uint32_t idx) const { RHI_ASSERT(idx < m_images.size()); return m_images[idx]; } 29 | inline VkImageView ImageView(uint32_t idx) const { RHI_ASSERT(idx < m_imageViews.size()); return m_imageViews[idx]; } 30 | const SwapchainDescriptor& Descriptor() const { return m_descriptor; } 31 | VkSwapchainKHR* Raw() { return &m_swapchain; } 32 | 33 | private: 34 | SwapchainDescriptor m_descriptor; 35 | VkSwapchainKHR m_swapchain; 36 | eastl::vector m_images; 37 | eastl::vector m_imageViews; 38 | }; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanBuffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "VulkanDevice.hpp" 6 | 7 | namespace rhi::vulkan 8 | { 9 | class RHI_API VulkanBuffer : public Buffer 10 | { 11 | public: 12 | VulkanBuffer(const BufferDescriptor& desc, const void* data); 13 | 14 | virtual ~VulkanBuffer(); 15 | 16 | virtual void* Map() const; 17 | virtual void UnMap() const; 18 | 19 | VkBuffer Raw() const { return m_buffer; } 20 | 21 | private: 22 | VkBuffer m_buffer = nullptr; 23 | VmaAllocation m_allocation = nullptr; 24 | 25 | // Is used only for constant buffer 26 | mutable uint8_t* m_bufferData = nullptr; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanComputeState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | struct RHI_API VulkanComputeState : public ComputeState 10 | { 11 | VulkanComputeState() 12 | { 13 | m_cmdBuffer.Begin(); 14 | } 15 | 16 | CommandBuffer m_cmdBuffer; 17 | }; 18 | 19 | } // rhi::vulkan -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanContext.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace rhi::vulkan 6 | { 7 | 8 | class RHI_API VulkanContext : public IContext 9 | { 10 | public: 11 | VulkanContext(VulkanInitContext&& ctx); 12 | 13 | virtual ~VulkanContext() override; 14 | 15 | inline VkInstance Instance() const { return m_instance; } 16 | inline VkSurfaceKHR Surface() const { return m_surface; } 17 | 18 | const eastl::vector& ValidationLayers() const; 19 | 20 | void RecreateSurface(); 21 | 22 | private: 23 | uint32_t m_extensionAmount{ 0 }; 24 | VkSurfaceKHR m_surface; 25 | VkInstance m_instance; 26 | VulkanInitContext m_ctx; 27 | }; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanGPUMaterial.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "VulkanShader.hpp" 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | class RHI_API VulkanGPUMaterial : public GPUMaterial 10 | { 11 | public: 12 | VulkanGPUMaterial(const std::shared_ptr& shader); 13 | virtual ~VulkanGPUMaterial() override; 14 | 15 | VkDescriptorSet DescriptorSet() const { return m_descriptorSet; } 16 | 17 | virtual void SetTexture(const std::shared_ptr& texture, uint8_t slot, uint8_t mipLevel = 0) override; 18 | virtual void SetBuffer(const std::shared_ptr& buffer, 19 | uint8_t slot, 20 | ShaderStage stage, 21 | int offset = 0) override; 22 | 23 | virtual void Sync() override; 24 | 25 | static void Destroy(); 26 | 27 | private: 28 | static void AllocateDescriptorPool(); 29 | VkDescriptorType DescriptorType(uint8_t slot); 30 | 31 | struct BufferInfo 32 | { 33 | std::weak_ptr m_buffer; 34 | uint32_t m_offset = 0; 35 | uint8_t m_slot = 0; 36 | rhi::ShaderStage m_stage = ShaderStage::NONE; 37 | }; 38 | 39 | struct TextureInfo 40 | { 41 | std::weak_ptr m_texture; 42 | uint8_t m_slot = 0; 43 | uint8_t m_mipLevel = 0; 44 | }; 45 | 46 | eastl::vector m_buffersToSync; 47 | eastl::vector m_texturesToSync; 48 | 49 | const ShaderDescriptor* m_shaderDesc = nullptr; 50 | VkDescriptorSet m_descriptorSet = nullptr; 51 | 52 | inline static VkDescriptorPool s_descriptorPool = nullptr; 53 | }; 54 | 55 | } // rhi::vulkan -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanPipeline.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | class RHI_API VulkanPipeline : public Pipeline 10 | { 11 | public: 12 | VulkanPipeline(const PipelineDescriptor& descriptor); 13 | 14 | virtual ~VulkanPipeline() override; 15 | 16 | VkPipeline GetPipeline() const { return m_pipeline; } 17 | VkPipelineLayout Layout() const { return m_layout; } 18 | 19 | private: 20 | void CreateFxPipeline(); 21 | void CreateComputePipeline(); 22 | 23 | VkPipelineLayout m_layout; 24 | VkPipeline m_pipeline; 25 | }; 26 | 27 | } // namespace rhi::vulkan -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanRenderPass.cpp: -------------------------------------------------------------------------------- 1 | #include "VulkanRenderPass.hpp" 2 | #include "VulkanDevice.hpp" 3 | #include "VulkanTexture.hpp" 4 | #include "VulkanHelpers.hpp" 5 | #include 6 | 7 | namespace rhi::vulkan 8 | { 9 | 10 | VulkanRenderPass::VulkanRenderPass(const RenderPassDescriptor& descriptor) : RenderPass(descriptor) 11 | { 12 | // Color 13 | for (const auto& attachment : descriptor.m_colorAttachments) 14 | { 15 | const glm::vec4 color = attachment.m_clearValue.m_color; 16 | VkClearValue clearValue{}; 17 | clearValue.color = { color.r, color.g, color.b, color.a }; 18 | 19 | VkRenderingAttachmentInfoKHR colorAttachment{}; 20 | colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, 21 | colorAttachment.loadOp = helpers::LoadOperation(attachment.m_loadOperation); 22 | colorAttachment.storeOp = helpers::StoreOperation(attachment.m_storeOperation); 23 | colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 24 | colorAttachment.clearValue = clearValue; 25 | colorAttachment.imageView = std::static_pointer_cast(attachment.m_texture)->ImageView(0); 26 | 27 | m_colorAttachmentInfos.push_back(colorAttachment); 28 | } 29 | 30 | if (!HasDepth()) 31 | { 32 | return; 33 | } 34 | 35 | // Depth 36 | const glm::vec4 color = descriptor.m_depthStencilAttachment.m_clearValue.m_color; 37 | VkClearValue clearValue{}; 38 | clearValue.color = { color.r, color.g, color.b, color.a }; 39 | clearValue.depthStencil.depth = descriptor.m_depthStencilAttachment.m_clearValue.m_depth; 40 | clearValue.depthStencil.stencil = descriptor.m_depthStencilAttachment.m_clearValue.m_stencil; 41 | 42 | std::memset(&m_depthAttachmentInfo, 0, sizeof(m_depthAttachmentInfo)); 43 | m_depthAttachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; 44 | m_depthAttachmentInfo.clearValue = clearValue; 45 | m_depthAttachmentInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 46 | m_depthAttachmentInfo.imageView = std::static_pointer_cast(descriptor.m_depthStencilAttachment.m_texture)->ImageView(0); 47 | m_depthAttachmentInfo.loadOp = helpers::LoadOperation(descriptor.m_depthStencilAttachment.m_loadOperation); 48 | m_depthAttachmentInfo.storeOp = helpers::StoreOperation(descriptor.m_depthStencilAttachment.m_storeOperation); 49 | } 50 | 51 | VulkanRenderPass::~VulkanRenderPass() 52 | { 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanRenderPass.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | class RHI_API VulkanRenderPass : public RenderPass 10 | { 11 | public: 12 | VulkanRenderPass(const RenderPassDescriptor& descriptor); 13 | 14 | virtual ~VulkanRenderPass() override; 15 | 16 | using AttachmentInfo = VkRenderingAttachmentInfoKHR; 17 | using AttachmentInfoList = eastl::vector; 18 | 19 | const AttachmentInfoList& ColorAttachments() const { return m_colorAttachmentInfos; } 20 | const AttachmentInfo& DepthAttachment() const { return m_depthAttachmentInfo; } 21 | 22 | private: 23 | AttachmentInfoList m_colorAttachmentInfos; 24 | AttachmentInfo m_depthAttachmentInfo; 25 | }; 26 | 27 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanSampler.cpp: -------------------------------------------------------------------------------- 1 | #include "VulkanSampler.hpp" 2 | #include "VulkanDevice.hpp" 3 | #include "VulkanHelpers.hpp" 4 | 5 | namespace rhi::vulkan 6 | { 7 | 8 | VulkanSampler::VulkanSampler(const SamplerDescriptor& descriptor) : Sampler(descriptor) 9 | { 10 | // TODO: Set magFilter, minFilter and mipmapMode through descriptor data 11 | 12 | VkSamplerCreateInfo samplerInfo{}; 13 | samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 14 | samplerInfo.magFilter = VK_FILTER_LINEAR; 15 | samplerInfo.minFilter = VK_FILTER_LINEAR; 16 | samplerInfo.addressModeU = helpers::AddressMode(descriptor.m_addressModeU); 17 | samplerInfo.addressModeV = helpers::AddressMode(descriptor.m_addressModeV); 18 | samplerInfo.addressModeW = helpers::AddressMode(descriptor.m_addressModeW); 19 | samplerInfo.anisotropyEnable = VK_TRUE; 20 | samplerInfo.maxAnisotropy = VulkanDevice::s_ctx.m_instance->m_parameters.m_maxSamplerAnisotropy; 21 | samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; 22 | samplerInfo.unnormalizedCoordinates = VK_FALSE; 23 | #ifdef R_OS_MACOS 24 | samplerInfo.compareEnable = VK_FALSE; 25 | #else 26 | samplerInfo.compareEnable = VK_TRUE; 27 | #endif 28 | samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; 29 | samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 30 | samplerInfo.mipLodBias = 0.0f; 31 | samplerInfo.minLod = descriptor.m_minLod; 32 | samplerInfo.maxLod = descriptor.m_maxLod; 33 | 34 | [[maybe_unused]] auto res = vkCreateSampler(VulkanDevice::s_ctx.m_device, &samplerInfo, nullptr, &m_sampler); 35 | 36 | RHI_ASSERT(res == VK_SUCCESS); 37 | } 38 | 39 | VulkanSampler::~VulkanSampler() 40 | { 41 | vkDestroySampler(VulkanDevice::s_ctx.m_device, m_sampler, nullptr); 42 | } 43 | 44 | } // namespace rhi::vulkan 45 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanSampler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | class RHI_API VulkanSampler : public Sampler 9 | { 10 | public: 11 | VulkanSampler(const SamplerDescriptor& descriptor); 12 | 13 | virtual ~VulkanSampler() override; 14 | 15 | VkSampler Raw() const { return m_sampler; } 16 | 17 | private: 18 | VkSampler m_sampler; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanShader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rhi::vulkan 7 | { 8 | 9 | class RHI_API VulkanShader : public Shader 10 | { 11 | public: 12 | VulkanShader(const ShaderDescriptor& descriptor); 13 | 14 | virtual ~VulkanShader() override; 15 | 16 | using InputAttributeDescription = eastl::vector; 17 | 18 | const InputAttributeDescription& AttributeDescription() const { return m_attributesDescription; } 19 | 20 | const VkVertexInputBindingDescription& InputDescription() const { return m_inputDescription; } 21 | 22 | VkShaderModule Module(ShaderStage stage) const { return m_modules[stage]; } 23 | 24 | VkDescriptorSetLayout Layout() const { return m_layout; } 25 | 26 | const eastl::vector& Constants() const { return m_constants; } 27 | 28 | private: 29 | using ModuleMap = eastl::unordered_map; 30 | 31 | mutable ModuleMap m_modules; 32 | eastl::vector m_attributesDescription; 33 | eastl::vector m_constants; 34 | VkVertexInputBindingDescription m_inputDescription; 35 | 36 | VkDescriptorSetLayout m_layout = nullptr; 37 | 38 | void FillVertexData(); 39 | void CreateDescriptorSetLayout(); 40 | void FillPushContansts(); 41 | }; 42 | 43 | } -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanShaderCompiler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace rhi::vulkan 11 | { 12 | 13 | class RHI_API VulkanShaderCompiler : public ShaderCompiler 14 | { 15 | public: 16 | VulkanShaderCompiler(Options options); 17 | 18 | virtual ~VulkanShaderCompiler() override; 19 | 20 | virtual CompiledShaderData Compile(std::string_view path, ShaderType type) override; 21 | 22 | private: 23 | using ReflectionMap = eastl::unordered_map; 24 | using ShaderMap = eastl::unordered_map; 25 | 26 | struct Context 27 | { 28 | std::string_view m_path; 29 | ShaderMap m_stageCodeStr; 30 | ShaderType m_type; 31 | }; 32 | 33 | void ReadShader(const std::string& text, Context& ctx) const; 34 | std::string ReadShader(std::string_view path); 35 | void PreprocessShader(Context& ctx); 36 | ShaderReflection MergeReflection(const ReflectionMap& reflectionMap, std::string_view path); 37 | [[nodiscard]] ShaderReflection ReflectShader(const core::Blob& shaderBlob, std::string_view path, ShaderStage stage); 38 | [[nodiscard]] core::Blob CompileShader(const std::string& shaderCode, std::string_view path, ShaderStage stage); 39 | 40 | eastl::unordered_map m_includeCache; 41 | std::mutex m_includeCacheMutex; 42 | std::mutex m_glslangMutex; 43 | }; 44 | 45 | } // rhi::vulkan 46 | -------------------------------------------------------------------------------- /Src/RHI/Src/Vulkan/VulkanTexture.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma warning(push) 8 | #pragma warning(disable : 4189) 9 | #include 10 | #pragma warning(pop) 11 | 12 | namespace rhi::vulkan 13 | { 14 | 15 | class RHI_API VulkanTexture : public Texture 16 | { 17 | public: 18 | VulkanTexture(const TextureDescriptor& desc, const std::shared_ptr& sampler, const void* data = nullptr); 19 | 20 | virtual ~VulkanTexture() override; 21 | 22 | void ChangeImageLayout(VkCommandBuffer cmdBuffer, VkImageLayout oldLayout, VkImageLayout newLayout); 23 | void ChangeImageLayout(VkImageLayout oldLayout, VkImageLayout newLayout); 24 | 25 | VkImageLayout Layout() const { return m_layout; } 26 | VkImage Image() const { return m_image; } 27 | VkImageView ImageView(uint32_t idx) const { RHI_ASSERT(idx < m_imageViews.size()); return m_imageViews[idx]; } 28 | 29 | private: 30 | void ChangeImageLayout(VkCommandBuffer cmdBuffer, 31 | VkImage image, 32 | VkImageLayout oldLayout, 33 | VkImageLayout newLayout, 34 | Format format, 35 | int layers, 36 | int mipmaps, 37 | bool isDepth = false); 38 | 39 | // Immediate change, may cause deadlocks! 40 | void ChangeImageLayout(VkImage image, 41 | VkImageLayout oldLayout, 42 | VkImageLayout newLayout, 43 | Format format, 44 | int layers, 45 | int mipmaps, 46 | bool isDepth = false); 47 | 48 | std::shared_ptr m_stagingBuffer; 49 | VkImage m_image = nullptr; 50 | eastl::vector m_imageViews; 51 | VmaAllocation m_allocation = nullptr; 52 | VkImageLayout m_layout; 53 | }; 54 | 55 | } // rhi::vulkan 56 | -------------------------------------------------------------------------------- /Src/TestLauncher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(PROJECT_NAME TestLauncher) 5 | 6 | file(GLOB_RECURSE SOURCE_FILES 7 | "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" 8 | "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" 9 | ) 10 | 11 | add_executable(${PROJECT_NAME} ${SOURCE_FILES}) 12 | target_link_libraries(${PROJECT_NAME} PRIVATE Engine) 13 | 14 | if (MSVC) 15 | set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/.bin/${CMAKE_BUILD_TYPE}") 16 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") 17 | endif() 18 | 19 | # Create source groups for each directory 20 | foreach(FILE ${SOURCE_FILES}) 21 | # Get the path relative to the source directory 22 | file(RELATIVE_PATH RELATIVE_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE}) 23 | # Get the directory of the file 24 | get_filename_component(DIR ${RELATIVE_FILE} DIRECTORY) 25 | # Create the source group 26 | source_group(${DIR} FILES ${FILE}) 27 | endforeach() -------------------------------------------------------------------------------- /Src/TestLauncher/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | RTTR_REGISTRATION 6 | { 7 | engine::registration::Service("tests::DoctestService") 8 | .PostUpdateAfter() 9 | .Domain(engine::Domain::CLIENT_NO_UI); 10 | } 11 | 12 | int main(int argc, char* argv[]) 13 | { 14 | engine::Engine engine(argc, argv); 15 | 16 | engine.GetServiceManager()->RegisterService(); 17 | engine.GetServiceManager()->UpdateDependencyOrder(); 18 | 19 | auto context = std::make_unique(); 20 | context->applyCommandLine(argc, argv); 21 | context->setOption("no-breaks", true); 22 | 23 | engine.Service().Context(std::move(context)); 24 | 25 | return engine.Run(); 26 | } 27 | 28 | EASTL_ALLOCATOR_IMPL 29 | -------------------------------------------------------------------------------- /prepare_env.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | poetry install --no-root 4 | poetry env use python 5 | poetry env activate 6 | poetry run conan remote update conancenter --url https://center2.conan.io 7 | poetry run python scripts/prepare_env.py win-64-ninja-clang false 8 | 9 | pause -------------------------------------------------------------------------------- /prepare_env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | poetry install --no-root 7 | poetry env use python3 8 | poetry env activate 9 | poetry run conan remote update conancenter --url https://center2.conan.io 10 | poetry run python3 Scripts/prepare_env.py mac-arm64-ninja-clang false -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "rightengine" 3 | version = "0.0.1" 4 | description = "C++ Vulkan game engine" 5 | authors = [ 6 | {name = "rbetik12", email = "mr.prikota@gmail.com"} 7 | ] 8 | license = {text = "MIT"} 9 | readme = "README.md" 10 | requires-python = ">=3.9" 11 | dependencies = [ 12 | "conan (==2.9.1)" 13 | ] 14 | 15 | 16 | [build-system] 17 | requires = ["poetry-core>=2.0.0,<3.0.0"] 18 | build-backend = "poetry.core.masonry.api" 19 | 20 | [tool.poetry] 21 | package-mode = false 22 | 23 | --------------------------------------------------------------------------------