From 271f17d1781ec65ab751c2529162cd6413ccb36c Mon Sep 17 00:00:00 2001 From: Facundo Villa Date: Tue, 20 Jun 2023 01:17:14 -0300 Subject: [PATCH] Initial Rust commit. --- .cargo/config.toml | 2 + .github/ISSUE_TEMPLATE/bug_report.md | 31 - .github/ISSUE_TEMPLATE/feature_request.md | 20 - .gitignore | 22 +- .vscode/c_cpp_properties.json | 17 - .vscode/launch.json | 37 +- .vscode/settings.json | 68 - .vscode/tasks.json | 12 - CMakeLists.txt | 160 - CMakeUserPresets.json | 9 - Cargo.lock | 1714 +++++++++++ Cargo.toml | 30 + LICENSE | 2 +- README.md | 10 +- _config.yml | 1 - aux.txt | 560 ++++ build.sh | 1 - conanfile.txt | 7 - configuration.json | 4 + docs/_includes/head.html | 5 + docs/design/index.yml | 2 + docs/design/readme.md | 1 + docs/design/render_design.md | 5 + docs/logo.png | Bin 0 -> 25252 bytes docs/retype.yml | 15 + docs/sample_project/index.yml | 2 + docs/sample_project/project_configuration.md | 11 + docs/setup/index.yml | 2 + docs/setup/installation.md | 11 + docs/static/custom.css | 0 docs/welcome.md | 1 + install.sh | 24 - meson.build | 61 - rust-toolchain.toml | 2 + src/AAL/AudioCore.h | 104 - src/AAL/AudioDevice.h | 387 --- src/AAL/Platform/Windows/WindowsAudioDevice.h | 265 -- src/ByteEngine.h | 6 - src/ByteEngine/Animation/AnimationSystem.h | 52 - src/ByteEngine/Animation/Skeletal Mesh.h | 33 - .../Application/AllocatorReferences.cpp | 20 - .../Application/AllocatorReferences.h | 83 - src/ByteEngine/Application/Application.cpp | 207 -- src/ByteEngine/Application/Application.h | 185 -- src/ByteEngine/Application/Clock.cpp | 159 - src/ByteEngine/Application/Clock.h | 82 - src/ByteEngine/Application/CommandMap.h | 31 - src/ByteEngine/Application/Console.h | 15 - src/ByteEngine/Application/EditorInterface.h | 38 - src/ByteEngine/Application/EntryPoint.h | 45 - src/ByteEngine/Application/Handle.hpp | 1 - src/ByteEngine/Application/InputManager.cpp | 26 - src/ByteEngine/Application/InputManager.h | 483 --- src/ByteEngine/Application/PoolAllocator.cpp | 215 -- src/ByteEngine/Application/PoolAllocator.h | 92 - .../Application/ScriptingSystem.cpp | 1 - .../Application/ScriptingSystem.hpp | 131 - src/ByteEngine/Application/StackAllocator.cpp | 43 - src/ByteEngine/Application/StackAllocator.h | 359 --- .../Application/SystemAllocator.cpp | 39 - src/ByteEngine/Application/SystemAllocator.h | 61 - .../Application/Templates/GameApplication.cpp | 334 -- .../Application/Templates/GameApplication.h | 44 - src/ByteEngine/Application/ThreadPool.h | 127 - src/ByteEngine/Application/WindowSystem.hpp | 186 -- src/ByteEngine/Core.h | 24 - src/ByteEngine/Debug/Assert.h | 17 - src/ByteEngine/Debug/FunctionTimer.cpp | 16 - src/ByteEngine/Debug/FunctionTimer.h | 21 - src/ByteEngine/Debug/Logger.cpp | 101 - src/ByteEngine/Debug/Logger.h | 163 - src/ByteEngine/Game/ApplicationManager.cpp | 290 -- src/ByteEngine/Game/ApplicationManager.h | 966 ------ src/ByteEngine/Game/CameraSystem.h | 76 - src/ByteEngine/Game/System.hpp | 58 - src/ByteEngine/Game/Tasks.h | 118 - src/ByteEngine/Game/World.cpp | 20 - src/ByteEngine/Game/World.h | 30 - src/ByteEngine/Game/WorldSystem.hpp | 62 - src/ByteEngine/Graph.hpp | 87 - src/ByteEngine/Handle.hpp | 49 - src/ByteEngine/Id.h | 50 - src/ByteEngine/Light.cpp | 90 - src/ByteEngine/Light.h | 29 - src/ByteEngine/MetaStruct.hpp | 43 - src/ByteEngine/Network/ConnectionHandler.hpp | 179 -- src/ByteEngine/Object.cpp | 10 - src/ByteEngine/Object.h | 64 - src/ByteEngine/Physics/ForceGenerator.h | 19 - src/ByteEngine/Physics/ForceGenerators.h | 55 - src/ByteEngine/Physics/HitResult.h | 32 - src/ByteEngine/Physics/PhysicsWorld.cpp | 90 - src/ByteEngine/Physics/PhysicsWorld.h | 128 - src/ByteEngine/Physics/Queries.h | 20 - src/ByteEngine/Physics/RigidBody.h | 12 - src/ByteEngine/PlayableAsset.h | 19 - src/ByteEngine/Render/Culling.h | 68 - src/ByteEngine/Render/LightsRenderGroup.h | 85 - src/ByteEngine/Render/RenderOrchestrator.cpp | 1682 ---------- src/ByteEngine/Render/RenderOrchestrator.h | 2391 --------------- src/ByteEngine/Render/RenderSystem.cpp | 450 --- src/ByteEngine/Render/RenderSystem.h | 718 ----- src/ByteEngine/Render/RenderTypes.h | 119 - src/ByteEngine/Render/RendererAllocator.cpp | 314 -- src/ByteEngine/Render/RendererAllocator.h | 132 - src/ByteEngine/Render/ShaderGenerator.h | 1467 --------- src/ByteEngine/Render/StaticMeshSystem.cpp | 42 - src/ByteEngine/Render/StaticMeshSystem.h | 55 - src/ByteEngine/Render/Types.hpp | 28 - src/ByteEngine/Render/UIManager.cpp | 173 -- src/ByteEngine/Render/UIManager.h | 494 --- src/ByteEngine/Render/WorldRenderPipeline.cpp | 287 -- src/ByteEngine/Render/WorldRenderPipeline.hpp | 314 -- .../Resources/AnimationResourceManager.cpp | 186 -- .../Resources/AnimationResourceManager.h | 148 - .../Resources/AudioResourceManager.cpp | 92 - .../Resources/AudioResourceManager.h | 93 - src/ByteEngine/Resources/BC7.cpp | 2702 ----------------- .../Resources/CommonPermutation.hpp | 183 -- .../Resources/CurvesResourceManager.hpp | 77 - src/ByteEngine/Resources/DebugPermutation.hpp | 7 - .../Resources/FontResourceManager.cpp | 73 - .../Resources/FontResourceManager.h | 56 - .../Resources/ForwardPermutation.hpp | 61 - src/ByteEngine/Resources/LUTResourceManager.h | 31 - .../Resources/PermutationManager.hpp | 122 - .../PipelineCacheResourceManager.cpp | 14 - .../Resources/PipelineCacheResourceManager.h | 29 - .../Resources/RayTracePermutation.hpp | 25 - src/ByteEngine/Resources/ResourceData.h | 13 - src/ByteEngine/Resources/ResourceManager.cpp | 43 - src/ByteEngine/Resources/ResourceManager.h | 243 -- .../Resources/ShaderCompilation.hpp | 209 -- .../Resources/ShaderResourceManager.h | 1417 --------- .../Resources/StaticMeshResourceManager.cpp | 410 --- .../Resources/StaticMeshResourceManager.h | 119 - src/ByteEngine/Resources/TextRendering.h | 203 -- .../Resources/TextureResourceManager.cpp | 124 - .../Resources/TextureResourceManager.h | 49 - src/ByteEngine/Resources/UIPermutation.hpp | 51 - .../Resources/VisibilityPermutation.hpp | 377 --- src/ByteEngine/SIMDMath.ixx | 715 ----- src/ByteEngine/Sound/AudioSystem.cpp | 211 -- src/ByteEngine/Sound/AudioSystem.h | 151 - src/ByteEngine/Sound/Effect.h | 9 - src/ByteEngine/Sound/SoundListener.h | 9 - src/ByteEngine/Sound/SoundMixer.h | 127 - src/ByteEngine/Sound/SoundPlayer.h | 10 - src/ByteEngine/Utility/AStar.cpp | 32 - src/ByteEngine/Utility/Collision.hpp | 24 - src/ByteEngine/Utility/Shapes/Box.h | 30 - .../Utility/Shapes/BoxWithFalloff.h | 8 - src/ByteEngine/Utility/Shapes/Cone.cpp | 12 - src/ByteEngine/Utility/Shapes/Cone.h | 37 - .../Utility/Shapes/ConeWithFalloff.cpp | 16 - .../Utility/Shapes/ConeWithFalloff.h | 29 - .../Utility/Shapes/SphereWithFallof.h | 23 - src/ByteEngine/Utility/StringLookup.hpp | 38 - src/GAL/Bindings.h | 41 - src/GAL/Buffer.h | 10 - src/GAL/CommandList.h | 112 - src/GAL/DX12/DX12.h | 161 - src/GAL/DX12/DX12AccelerationStructure.hpp | 21 - src/GAL/DX12/DX12Bindings.h | 244 -- src/GAL/DX12/DX12Buffer.h | 54 - src/GAL/DX12/DX12CommandList.h | 304 -- src/GAL/DX12/DX12Memory.h | 40 - src/GAL/DX12/DX12Pipelines.h | 219 -- src/GAL/DX12/DX12QueryPool.h | 7 - src/GAL/DX12/DX12Queue.h | 59 - src/GAL/DX12/DX12RenderContext.h | 128 - src/GAL/DX12/DX12RenderDevice.h | 133 - src/GAL/DX12/DX12RenderPass.h | 15 - src/GAL/DX12/DX12Synchronization.h | 36 - src/GAL/DX12/DX12Texture.h | 125 - src/GAL/Framebuffer.h | 12 - src/GAL/Memory.h | 10 - src/GAL/Pipelines.h | 283 -- src/GAL/Queue.h | 23 - src/GAL/RenderContext.h | 25 - src/GAL/RenderCore.h | 517 ---- src/GAL/RenderDevice.h | 91 - src/GAL/RenderPass.h | 44 - src/GAL/Serialize.hpp | 21 - src/GAL/Synchronization.h | 15 - src/GAL/Texture.h | 124 - src/GAL/Vulkan/Vulkan.h | 594 ---- src/GAL/Vulkan/VulkanAccelerationStructures.h | 228 -- src/GAL/Vulkan/VulkanAsyncHostOperation.h | 48 - src/GAL/Vulkan/VulkanBindings.h | 279 -- src/GAL/Vulkan/VulkanBuffer.h | 54 - src/GAL/Vulkan/VulkanCommandList.h | 483 --- src/GAL/Vulkan/VulkanMemory.h | 51 - src/GAL/Vulkan/VulkanPipelines.h | 578 ---- src/GAL/Vulkan/VulkanQueryPool.h | 38 - src/GAL/Vulkan/VulkanQueue.h | 84 - src/GAL/Vulkan/VulkanRenderContext.h | 234 -- src/GAL/Vulkan/VulkanRenderDevice.h | 1005 ------ src/GAL/Vulkan/VulkanRenderPass.h | 127 - src/GAL/Vulkan/VulkanSynchronization.h | 109 - src/GAL/Vulkan/VulkanTexture.h | 123 - src/application.rs | 202 ++ src/beshader_compiler.rs | 431 +++ src/executor.rs | 178 ++ src/file_tracker.rs | 116 + src/gdeflate.rs | 1228 ++++++++ src/input_manager.rs | 1193 ++++++++ src/lib.rs | 192 ++ src/orchestrator.rs | 217 ++ src/render_backend.rs | 727 +++++ src/render_debugger.rs | 34 + src/render_system.rs | 1916 ++++++++++++ src/resource_manager.rs | 751 +++++ src/shader_generator.rs | 620 ++++ src/vulkan_render_backend.rs | 1310 ++++++++ src/window_system.rs | 607 ++++ tests/CMakeLists.txt | 16 - tests/TestApplication.cpp | 40 - 218 files changed, 12100 insertions(+), 31685 deletions(-) create mode 100644 .cargo/config.toml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 .vscode/c_cpp_properties.json delete mode 100644 .vscode/settings.json delete mode 100644 .vscode/tasks.json delete mode 100644 CMakeLists.txt delete mode 100644 CMakeUserPresets.json create mode 100644 Cargo.lock create mode 100644 Cargo.toml delete mode 100644 _config.yml create mode 100644 aux.txt delete mode 100644 build.sh delete mode 100644 conanfile.txt create mode 100644 configuration.json create mode 100644 docs/_includes/head.html create mode 100644 docs/design/index.yml create mode 100644 docs/design/readme.md create mode 100644 docs/design/render_design.md create mode 100644 docs/logo.png create mode 100644 docs/retype.yml create mode 100644 docs/sample_project/index.yml create mode 100644 docs/sample_project/project_configuration.md create mode 100644 docs/setup/index.yml create mode 100644 docs/setup/installation.md create mode 100644 docs/static/custom.css create mode 100644 docs/welcome.md delete mode 100644 install.sh delete mode 100644 meson.build create mode 100644 rust-toolchain.toml delete mode 100644 src/AAL/AudioCore.h delete mode 100644 src/AAL/AudioDevice.h delete mode 100644 src/AAL/Platform/Windows/WindowsAudioDevice.h delete mode 100644 src/ByteEngine.h delete mode 100644 src/ByteEngine/Animation/AnimationSystem.h delete mode 100644 src/ByteEngine/Animation/Skeletal Mesh.h delete mode 100644 src/ByteEngine/Application/AllocatorReferences.cpp delete mode 100644 src/ByteEngine/Application/AllocatorReferences.h delete mode 100644 src/ByteEngine/Application/Application.cpp delete mode 100644 src/ByteEngine/Application/Application.h delete mode 100644 src/ByteEngine/Application/Clock.cpp delete mode 100644 src/ByteEngine/Application/Clock.h delete mode 100644 src/ByteEngine/Application/CommandMap.h delete mode 100644 src/ByteEngine/Application/Console.h delete mode 100644 src/ByteEngine/Application/EditorInterface.h delete mode 100644 src/ByteEngine/Application/EntryPoint.h delete mode 100644 src/ByteEngine/Application/Handle.hpp delete mode 100644 src/ByteEngine/Application/InputManager.cpp delete mode 100644 src/ByteEngine/Application/InputManager.h delete mode 100644 src/ByteEngine/Application/PoolAllocator.cpp delete mode 100644 src/ByteEngine/Application/PoolAllocator.h delete mode 100644 src/ByteEngine/Application/ScriptingSystem.cpp delete mode 100644 src/ByteEngine/Application/ScriptingSystem.hpp delete mode 100644 src/ByteEngine/Application/StackAllocator.cpp delete mode 100644 src/ByteEngine/Application/StackAllocator.h delete mode 100644 src/ByteEngine/Application/SystemAllocator.cpp delete mode 100644 src/ByteEngine/Application/SystemAllocator.h delete mode 100644 src/ByteEngine/Application/Templates/GameApplication.cpp delete mode 100644 src/ByteEngine/Application/Templates/GameApplication.h delete mode 100644 src/ByteEngine/Application/ThreadPool.h delete mode 100644 src/ByteEngine/Application/WindowSystem.hpp delete mode 100644 src/ByteEngine/Core.h delete mode 100644 src/ByteEngine/Debug/Assert.h delete mode 100644 src/ByteEngine/Debug/FunctionTimer.cpp delete mode 100644 src/ByteEngine/Debug/FunctionTimer.h delete mode 100644 src/ByteEngine/Debug/Logger.cpp delete mode 100644 src/ByteEngine/Debug/Logger.h delete mode 100644 src/ByteEngine/Game/ApplicationManager.cpp delete mode 100644 src/ByteEngine/Game/ApplicationManager.h delete mode 100644 src/ByteEngine/Game/CameraSystem.h delete mode 100644 src/ByteEngine/Game/System.hpp delete mode 100644 src/ByteEngine/Game/Tasks.h delete mode 100644 src/ByteEngine/Game/World.cpp delete mode 100644 src/ByteEngine/Game/World.h delete mode 100644 src/ByteEngine/Game/WorldSystem.hpp delete mode 100644 src/ByteEngine/Graph.hpp delete mode 100644 src/ByteEngine/Handle.hpp delete mode 100644 src/ByteEngine/Id.h delete mode 100644 src/ByteEngine/Light.cpp delete mode 100644 src/ByteEngine/Light.h delete mode 100644 src/ByteEngine/MetaStruct.hpp delete mode 100644 src/ByteEngine/Network/ConnectionHandler.hpp delete mode 100644 src/ByteEngine/Object.cpp delete mode 100644 src/ByteEngine/Object.h delete mode 100644 src/ByteEngine/Physics/ForceGenerator.h delete mode 100644 src/ByteEngine/Physics/ForceGenerators.h delete mode 100644 src/ByteEngine/Physics/HitResult.h delete mode 100644 src/ByteEngine/Physics/PhysicsWorld.cpp delete mode 100644 src/ByteEngine/Physics/PhysicsWorld.h delete mode 100644 src/ByteEngine/Physics/Queries.h delete mode 100644 src/ByteEngine/Physics/RigidBody.h delete mode 100644 src/ByteEngine/PlayableAsset.h delete mode 100644 src/ByteEngine/Render/Culling.h delete mode 100644 src/ByteEngine/Render/LightsRenderGroup.h delete mode 100644 src/ByteEngine/Render/RenderOrchestrator.cpp delete mode 100644 src/ByteEngine/Render/RenderOrchestrator.h delete mode 100644 src/ByteEngine/Render/RenderSystem.cpp delete mode 100644 src/ByteEngine/Render/RenderSystem.h delete mode 100644 src/ByteEngine/Render/RenderTypes.h delete mode 100644 src/ByteEngine/Render/RendererAllocator.cpp delete mode 100644 src/ByteEngine/Render/RendererAllocator.h delete mode 100644 src/ByteEngine/Render/ShaderGenerator.h delete mode 100644 src/ByteEngine/Render/StaticMeshSystem.cpp delete mode 100644 src/ByteEngine/Render/StaticMeshSystem.h delete mode 100644 src/ByteEngine/Render/Types.hpp delete mode 100644 src/ByteEngine/Render/UIManager.cpp delete mode 100644 src/ByteEngine/Render/UIManager.h delete mode 100644 src/ByteEngine/Render/WorldRenderPipeline.cpp delete mode 100644 src/ByteEngine/Render/WorldRenderPipeline.hpp delete mode 100644 src/ByteEngine/Resources/AnimationResourceManager.cpp delete mode 100644 src/ByteEngine/Resources/AnimationResourceManager.h delete mode 100644 src/ByteEngine/Resources/AudioResourceManager.cpp delete mode 100644 src/ByteEngine/Resources/AudioResourceManager.h delete mode 100644 src/ByteEngine/Resources/BC7.cpp delete mode 100644 src/ByteEngine/Resources/CommonPermutation.hpp delete mode 100644 src/ByteEngine/Resources/CurvesResourceManager.hpp delete mode 100644 src/ByteEngine/Resources/DebugPermutation.hpp delete mode 100644 src/ByteEngine/Resources/FontResourceManager.cpp delete mode 100644 src/ByteEngine/Resources/FontResourceManager.h delete mode 100644 src/ByteEngine/Resources/ForwardPermutation.hpp delete mode 100644 src/ByteEngine/Resources/LUTResourceManager.h delete mode 100644 src/ByteEngine/Resources/PermutationManager.hpp delete mode 100644 src/ByteEngine/Resources/PipelineCacheResourceManager.cpp delete mode 100644 src/ByteEngine/Resources/PipelineCacheResourceManager.h delete mode 100644 src/ByteEngine/Resources/RayTracePermutation.hpp delete mode 100644 src/ByteEngine/Resources/ResourceData.h delete mode 100644 src/ByteEngine/Resources/ResourceManager.cpp delete mode 100644 src/ByteEngine/Resources/ResourceManager.h delete mode 100644 src/ByteEngine/Resources/ShaderCompilation.hpp delete mode 100644 src/ByteEngine/Resources/ShaderResourceManager.h delete mode 100644 src/ByteEngine/Resources/StaticMeshResourceManager.cpp delete mode 100644 src/ByteEngine/Resources/StaticMeshResourceManager.h delete mode 100644 src/ByteEngine/Resources/TextRendering.h delete mode 100644 src/ByteEngine/Resources/TextureResourceManager.cpp delete mode 100644 src/ByteEngine/Resources/TextureResourceManager.h delete mode 100644 src/ByteEngine/Resources/UIPermutation.hpp delete mode 100644 src/ByteEngine/Resources/VisibilityPermutation.hpp delete mode 100644 src/ByteEngine/SIMDMath.ixx delete mode 100644 src/ByteEngine/Sound/AudioSystem.cpp delete mode 100644 src/ByteEngine/Sound/AudioSystem.h delete mode 100644 src/ByteEngine/Sound/Effect.h delete mode 100644 src/ByteEngine/Sound/SoundListener.h delete mode 100644 src/ByteEngine/Sound/SoundMixer.h delete mode 100644 src/ByteEngine/Sound/SoundPlayer.h delete mode 100644 src/ByteEngine/Utility/AStar.cpp delete mode 100644 src/ByteEngine/Utility/Collision.hpp delete mode 100644 src/ByteEngine/Utility/Shapes/Box.h delete mode 100644 src/ByteEngine/Utility/Shapes/BoxWithFalloff.h delete mode 100644 src/ByteEngine/Utility/Shapes/Cone.cpp delete mode 100644 src/ByteEngine/Utility/Shapes/Cone.h delete mode 100644 src/ByteEngine/Utility/Shapes/ConeWithFalloff.cpp delete mode 100644 src/ByteEngine/Utility/Shapes/ConeWithFalloff.h delete mode 100644 src/ByteEngine/Utility/Shapes/SphereWithFallof.h delete mode 100644 src/ByteEngine/Utility/StringLookup.hpp delete mode 100644 src/GAL/Bindings.h delete mode 100644 src/GAL/Buffer.h delete mode 100644 src/GAL/CommandList.h delete mode 100644 src/GAL/DX12/DX12.h delete mode 100644 src/GAL/DX12/DX12AccelerationStructure.hpp delete mode 100644 src/GAL/DX12/DX12Bindings.h delete mode 100644 src/GAL/DX12/DX12Buffer.h delete mode 100644 src/GAL/DX12/DX12CommandList.h delete mode 100644 src/GAL/DX12/DX12Memory.h delete mode 100644 src/GAL/DX12/DX12Pipelines.h delete mode 100644 src/GAL/DX12/DX12QueryPool.h delete mode 100644 src/GAL/DX12/DX12Queue.h delete mode 100644 src/GAL/DX12/DX12RenderContext.h delete mode 100644 src/GAL/DX12/DX12RenderDevice.h delete mode 100644 src/GAL/DX12/DX12RenderPass.h delete mode 100644 src/GAL/DX12/DX12Synchronization.h delete mode 100644 src/GAL/DX12/DX12Texture.h delete mode 100644 src/GAL/Framebuffer.h delete mode 100644 src/GAL/Memory.h delete mode 100644 src/GAL/Pipelines.h delete mode 100644 src/GAL/Queue.h delete mode 100644 src/GAL/RenderContext.h delete mode 100644 src/GAL/RenderCore.h delete mode 100644 src/GAL/RenderDevice.h delete mode 100644 src/GAL/RenderPass.h delete mode 100644 src/GAL/Serialize.hpp delete mode 100644 src/GAL/Synchronization.h delete mode 100644 src/GAL/Texture.h delete mode 100644 src/GAL/Vulkan/Vulkan.h delete mode 100644 src/GAL/Vulkan/VulkanAccelerationStructures.h delete mode 100644 src/GAL/Vulkan/VulkanAsyncHostOperation.h delete mode 100644 src/GAL/Vulkan/VulkanBindings.h delete mode 100644 src/GAL/Vulkan/VulkanBuffer.h delete mode 100644 src/GAL/Vulkan/VulkanCommandList.h delete mode 100644 src/GAL/Vulkan/VulkanMemory.h delete mode 100644 src/GAL/Vulkan/VulkanPipelines.h delete mode 100644 src/GAL/Vulkan/VulkanQueryPool.h delete mode 100644 src/GAL/Vulkan/VulkanQueue.h delete mode 100644 src/GAL/Vulkan/VulkanRenderContext.h delete mode 100644 src/GAL/Vulkan/VulkanRenderDevice.h delete mode 100644 src/GAL/Vulkan/VulkanRenderPass.h delete mode 100644 src/GAL/Vulkan/VulkanSynchronization.h delete mode 100644 src/GAL/Vulkan/VulkanTexture.h create mode 100644 src/application.rs create mode 100644 src/beshader_compiler.rs create mode 100644 src/executor.rs create mode 100644 src/file_tracker.rs create mode 100644 src/gdeflate.rs create mode 100644 src/input_manager.rs create mode 100644 src/lib.rs create mode 100644 src/orchestrator.rs create mode 100644 src/render_backend.rs create mode 100644 src/render_debugger.rs create mode 100644 src/render_system.rs create mode 100644 src/resource_manager.rs create mode 100644 src/shader_generator.rs create mode 100644 src/vulkan_render_backend.rs create mode 100644 src/window_system.rs delete mode 100644 tests/CMakeLists.txt delete mode 100644 tests/TestApplication.cpp diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..3b5ff24a --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["-C", "link-arg=-fuse-ld=mold"] \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 43cb39fc..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: Bug Report -labels: 'Topic: Bug :bug:' -assignees: Facundo961 - ---- - -#Bug Report -## Description -### Expected behavior -__A clear and concise description of what you expected to happen.__ - -### Current behavior -__A clear and concise description of what is actually happening.__ - -### To Reproduce -**Steps to reproduce the behavior:** -1. ... - -### Code Snippets -__If applicable, add code to help explain your problem.__ - -## Enviroment -### Device - - OS: [e.g. iOS] - - Compiler: [e.g. MSVC v.19, Env. Vars: BE_DEBUG] - -### Additional context -__Add any other context about the problem here.__ diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore index aa138990..6fb8b962 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,3 @@ -# Directories -.vs/ -bin/ -bin-int/ -.git/ -.github/ -ext/ -out/ -build/ - -# Files -*.user -*.DotSettings -*.sln.DotSettings -*.DotSettings.user -*.sln.DotSettings.user -*.log -*.ifc -*.cmake \ No newline at end of file +**/target +**/resources +**/assets \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 237b707b..00000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/src/**" - ], - "defines": [], - "compilerPath": "/usr/bin/gcc", - "cStandard": "c17", - "cppStandard": "c++23", - "intelliSenseMode": "linux-gcc-x64", - "configurationProvider": "mesonbuild.mesonbuild" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 72bb3b17..91b425d9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,34 +1,7 @@ { - "configurations": [ - { - "name": "(gdb) Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/build/TestByteEngine", - "args": ["--threads 1"], - "stopAtEntry": false, - "cwd": "${fileDirname}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "preLaunchTask": "build", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "description": "Set Disassembly Flavor to Intel", - "text": "-gdb-set disassembly-flavor intel", - "ignoreFailures": true - }, - { - "description": "Enable break on all exceptions", - "text": "catch throw", - "ignoreFailures": true - } - ] - } - ], + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 577e1ce2..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "files.associations": { - "*.tcc": "cpp", - "fstream": "cpp", - "sstream": "cpp", - "regex": "cpp", - "any": "cpp", - "istream": "cpp", - "ostream": "cpp", - "typeinfo": "cpp", - "algorithm": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "cerrno": "cpp", - "chrono": "cpp", - "climits": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "codecvt": "cpp", - "compare": "cpp", - "concepts": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "map": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "filesystem": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "random": "cpp", - "ratio": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "ios": "cpp", - "iosfwd": "cpp", - "limits": "cpp", - "locale": "cpp", - "new": "cpp", - "numbers": "cpp", - "queue": "cpp", - "stack": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "cinttypes": "cpp", - "cstdbool": "cpp" - } -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 982b67ee..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "type": "shell", - "problemMatcher": "$gcc", - "group": "build", - "command": "ninja -C build" - } - ] -} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 368386e3..00000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,160 +0,0 @@ -cmake_minimum_required(VERSION 3.24) - -if(UNIX) - add_compile_options(-mavx2) -endif() - -project(ByteEngine LANGUAGES CXX VERSION 1.0.0) - -include(FetchContent) - -# GTSL -FetchContent_Declare(GTSL GIT_REPOSITORY "https://github.com/Game-Tek/Game-Tek-Standard-Library" GIT_TAG "889283d1d17aaa0b7478a4cfa68e8781d2dff28e") -FetchContent_MakeAvailable(GTSL) -# GTSL - -# ByteEngine options -set(BE_GAPI "vulkan") -set(BE_CSHARP_SCRIPTING true) -set(BE_DEBUG true) -# ByteEngine options - -add_library(ByteEngine STATIC "${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/EntryPoint.h" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Physics/PhysicsWorld.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Render/RenderOrchestrator.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/AllocatorReferences.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/PoolAllocator.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/StackAllocator.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/SystemAllocator.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/Templates/GameApplication.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Debug/FunctionTimer.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Game/ApplicationManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Object.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Render/RendererAllocator.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Render/RenderSystem.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Game/World.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Light.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Render/StaticMeshSystem.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Render/UIManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/AnimationResourceManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/AudioResourceManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/FontResourceManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/PipelineCacheResourceManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/ResourceManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/StaticMeshResourceManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/TextureResourceManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Sound/AudioSystem.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Utility/Shapes/Cone.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Utility/Shapes/ConeWithFalloff.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/InputManager.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Debug/Logger.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/ScriptingSystem.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/Clock.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Application/Application.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Resources/BC7.cpp" -"${PROJECT_SOURCE_DIR}/src/ByteEngine/Render/WorldRenderPipeline.cpp") - -set_target_properties(ByteEngine PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO) -set_target_properties(ByteEngine PROPERTIES PUBLIC_HEADER "${PROJECT_SOURCE_DIR}/src/ByteEngine.h") -target_compile_options(ByteEngine PRIVATE $<$,$,$>:-Wall>$<$:/W4>) -target_compile_features(ByteEngine PUBLIC cxx_std_20) - -target_include_directories(ByteEngine PUBLIC "${PROJECT_SOURCE_DIR}/src") -target_include_directories(ByteEngine PUBLIC "${PROJECT_SOURCE_DIR}/ext") - -# assimp -find_package(assimp CONFIG REQUIRED) - -set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE) -set(ASSIMP_BUILD_TESTS OFF CACHE INTERNAL "" FORCE) -set(ASSIMP_BUILD_ZLIB ON CACHE INTERNAL "" FORCE) -set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE INTERNAL "" FORCE) -set(ASSIMP_INSTALL_PDB OFF CACHE INTERNAL "" FORCE) -set(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT OFF CACHE INTERNAL "" FORCE) -set(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT OFF CACHE INTERNAL "" FORCE) -set(ASSIMP_BUILD_OBJ_IMPORTER ON CACHE INTERNAL "" FORCE) -set(ASSIMP_BUILD_FBX_IMPORTER ON CACHE INTERNAL "" FORCE) - -target_link_libraries(ByteEngine INTERFACE assimp::assimp) -target_include_directories(ByteEngine PUBLIC assimp::assimp) -target_include_directories(ByteEngine INTERFACE assimp_INCLUDE_DIRS) -# assimp - -find_package(stb REQUIRED) -target_include_directories(ByteEngine PUBLIC stb::stb) - -# GTSL -target_include_directories(ByteEngine PUBLIC "${gtsl_SOURCE_DIR}") -target_link_libraries(ByteEngine INTERFACE GTSL) -# GTSL - -enable_testing() - -add_subdirectory(tests) - -if (CMAKE_BUILD_TYPE MATCHES Debug) - target_compile_definitions(ByteEngine PUBLIC BE_DEBUG=1) -else() - target_compile_definitions(ByteEngine PUBLIC BE_DEBUG=0) -endif() - -if (WIN32) - target_compile_definitions(ByteEngine PUBLIC BE_PLATFORM_WINDOWS=1) - target_compile_definitions(ByteEngine PUBLIC BE_PLATFORM_LINUX=0) - - if(BE_CSHARP_SCRIPTING) - target_include_directories(ByteEngine PUBLIC "C:/Program Files/Mono/include/mono-2.0") - target_link_libraries(ByteEngine PRIVATE "C:/Program Files/Mono/lib/mono-2.0-sgen.lib") - endif() - - if (BE_GAPI STREQUAL "vulkan") - find_package(Vulkan REQUIRED COMPONENTS shaderc_combined) - - target_include_directories(ByteEngine PUBLIC Vulkan::Vulkan) - target_link_libraries(ByteEngine PUBLIC Vulkan::Vulkan) - target_link_libraries(ByteEngine PUBLIC Vulkan::shaderc_combined) - - target_compile_definitions(ByteEngine PUBLIC BE_VULKAN=1) - target_compile_definitions(ByteEngine PUBLIC BE_DX12=0) - elseif(BE_GAPI STREQUAL "dx12") - target_link_libraries(ByteEngine INTERFACE d3d12.lib) - - target_compile_definitions(ByteEngine PUBLIC BE_VULKAN=0) - target_compile_definitions(ByteEngine PUBLIC BE_DX12=1) - endif() - - target_link_libraries(ByteEngine INTERFACE Hid.lib) - target_link_libraries(ByteEngine INTERFACE XInput.lib) - - target_compile_definitions(ByteEngine PUBLIC NOMINMAX) - target_compile_definitions(ByteEngine PUBLIC VC_EXTRALEAN) - target_compile_definitions(ByteEngine PUBLIC WIN32_LEAN_AND_MEAN) -endif() - -if (UNIX) - target_compile_definitions(ByteEngine PUBLIC BE_PLATFORM_WINDOWS=0) - target_compile_definitions(ByteEngine PUBLIC BE_PLATFORM_LINUX=1) - - if(BE_CSHARP_SCRIPTING) - target_include_directories(ByteEngine PUBLIC "/usr/include/mono-2.0") - target_link_libraries(ByteEngine PRIVATE "/lib/libmono-2.0.a") - endif() - - find_package(ALSA REQUIRED) - target_include_directories(ByteEngine PUBLIC ALSA::ALSA) - target_link_libraries(ByteEngine PUBLIC ALSA::ALSA) - - if (BE_GAPI STREQUAL "vulkan") - find_package(Vulkan REQUIRED COMPONENTS shaderc_combined) - - target_include_directories(ByteEngine PUBLIC Vulkan::Vulkan) - target_link_libraries(ByteEngine PUBLIC Vulkan::Vulkan) - target_link_libraries(ByteEngine PUBLIC Vulkan::shaderc_combined) - - target_compile_definitions(ByteEngine PUBLIC BE_VULKAN=1) - target_compile_definitions(ByteEngine PUBLIC BE_DX12=0) - elseif(BE_GAPI STREQUAL "dx12") - target_compile_definitions(ByteEngine PUBLIC BE_VULKAN=0) - target_compile_definitions(ByteEngine PUBLIC BE_DX12=0) - endif() -endif() \ No newline at end of file diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json deleted file mode 100644 index 2a10d86a..00000000 --- a/CMakeUserPresets.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "version": 4, - "vendor": { - "conan": {} - }, - "include": [ - "/home/facundovilla/development/Byte-Engine/build/CMakePresets.json" - ] -} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..8a526590 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1714 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] + +[[package]] +name = "approx" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ash" +version = "0.37.0+1.3.246" +source = "git+https://github.com/ash-rs/ash?branch=master#53c395b6b6603faa5cc68d472f8d991f1e3fa126" +dependencies = [ + "libloading", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "bson" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aeb8bae494e49dbc330dd23cf78f6f7accee22f640ce3ab17841badaa4ce232" +dependencies = [ + "ahash 0.7.6", + "base64", + "bitvec", + "hex", + "indexmap", + "js-sys", + "lazy_static", + "rand", + "serde", + "serde_bytes", + "serde_json", + "time", + "uuid", +] + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "byte_engine" +version = "0.1.0" +dependencies = [ + "ash", + "bitflags 2.2.1", + "cgmath", + "cooked-waker", + "dual_quaternion", + "futures", + "gltf", + "half", + "intel_tex_2", + "json", + "libdeflater", + "notify", + "png", + "polodb_core", + "renderdoc", + "serde_json", + "shaderc", + "ureq", + "x11", + "xcb", +] + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cgmath" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317" +dependencies = [ + "approx", + "num-traits", +] + +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "cooked-waker" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crc64fast" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd3d10c557924c719a61e583165e31a0d8131b20415d6858983e67d1eb8a82bd" + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "dual_quaternion" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0776815172fe551fc69eaab7b271cefa7d19902d5723e12873d0cc6ec465575c" +dependencies = [ + "quaternion", + "vecmath", +] + +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "filetime" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.48.0", +] + +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gltf" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd7703af6975def3b32573c60aaa5ebfebfab5d879da1e1315d87155ba57bcd" +dependencies = [ + "base64", + "byteorder", + "gltf-json", + "image", + "lazy_static", + "urlencoding", +] + +[[package]] +name = "gltf-derive" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b33dbe598480111e3b2e5a1e9a7e52ad5df0f836e04b8c80fc96f52a9c9f2e" +dependencies = [ + "inflections", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "gltf-json" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5511a759d99beeeef064bd6f81e207c77e3a3431c7499d7590929e35de371f31" +dependencies = [ + "gltf-derive", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "image" +version = "0.24.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "jpeg-decoder", + "num-rational", + "num-traits", + "png", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "intel_tex_2" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8183b892d72cefc079675302f0e69658fe8dec871f5551f556c65b394b63ccbf" +dependencies = [ + "ispc_rt", +] + +[[package]] +name = "ispc_rt" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0220406fa868139b6368b69f66118d211ec927a88ba41909622e67f08a11de" +dependencies = [ + "libc", + "num_cpus", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" + +[[package]] +name = "js-sys" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" + +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" + +[[package]] +name = "libdeflate-sys" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "012437ac39c1e7d7ba12af3aceceb5c93149779aa17c2b1c483f33954957ddc8" +dependencies = [ + "cc", +] + +[[package]] +name = "libdeflater" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b30f982ddb14aae2a24a7ed7b3d512d687c2483493f95de7a6d167942a19c3" +dependencies = [ + "libdeflate-sys", +] + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lz4_flex" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8c72594ac26bfd34f2d99dfced2edfaddfe8a476e3ff2ca0eb293d925c4f83" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d9ba6c734de18ca27c8cef5cd7058aa4ac9f63596131e4c7e41e579319032a2" +dependencies = [ + "bitflags 1.3.2", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piston-float" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "png" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polodb_core" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fef3dbdf0bd44fa0d6e5630bc02f721f8238f7e58a0b50661c099fc759d355de" +dependencies = [ + "bson", + "byteorder", + "crc64fast", + "getrandom", + "hashbrown 0.13.2", + "indexmap", + "js-sys", + "libc", + "lz4_flex", + "memmap2", + "num_enum", + "regex", + "serde", + "serde-wasm-bindgen", + "smallvec", + "thiserror", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winapi", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quaternion" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "098443236d1445368525aa1874295cb9d9fc7699b52907c78692f0b18bd8c216" +dependencies = [ + "vecmath", +] + +[[package]] +name = "quick-xml" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" + +[[package]] +name = "renderdoc" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "272da9ec1e28b0ef17df4dcefad820b13f098ebe9c82697111fc57ccff621e12" +dependencies = [ + "bitflags 1.3.2", + "float-cmp", + "libloading", + "once_cell", + "renderdoc-sys", + "winapi", + "wio", +] + +[[package]] +name = "renderdoc-sys" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "roxmltree" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "serde" +version = "1.0.163" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.163" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shaderc" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31cef52787a0db5108788ea20bed13d6bf4b96287c5c5201e55725f7070f3443" +dependencies = [ + "libc", + "shaderc-sys", +] + +[[package]] +name = "shaderc-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8f8439fffcffd6efcd74197204addf935dbab5752696bd990a6cd36d54cf64" +dependencies = [ + "cmake", + "libc", + "roxmltree", +] + +[[package]] +name = "simd-adler32" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "time" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" + +[[package]] +name = "toml_edit" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "ureq" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" +dependencies = [ + "base64", + "flate2", + "log", + "once_cell", + "rustls", + "url", + "webpki", + "webpki-roots", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "urlencoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" + +[[package]] +name = "uuid" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +dependencies = [ + "atomic", + "getrandom", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "vecmath" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ae1e0d85bca567dee1dcf87fb1ca2e792792f66f87dced8381f99cd91156a" +dependencies = [ + "piston-float", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.15", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" + +[[package]] +name = "web-sys" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +dependencies = [ + "memchr", +] + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "xcb" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b90c622d513012e7419594a2138953603c63848cb189041e7b5dc04d3895da5" +dependencies = [ + "bitflags 1.3.2", + "libc", + "quick-xml", +] + +[[package]] +name = "xmlparser" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..7a5830f4 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "byte_engine" +version = "0.1.0" +edition = "2021" + +[dependencies] +x11 = "2.21.0" +xcb = { version = "1.2.1", features=['xtest'] } +# ash = { version = "0.37.2", features=['linked'] } +ash = { git = "https://github.com/ash-rs/ash", branch = "master", features=['linked'] } +futures = "0.3.28" +shaderc = "0.8.2" +bitflags = "2.2.1" +renderdoc = "0.11.0" +png = "0.17.8" +json = "0.12.4" +polodb_core = "4.4.0" +intel_tex_2 = "0.2.2" +gltf = "1.1.0" +ureq = "2.6.2" +libdeflater = "0.14.0" +notify = "6.0.0" +serde_json = "1.0.96" +cooked-waker = "5.0.0" +half = "2.2.1" +dual_quaternion = "0.2.0" +cgmath = "0.18.0" + +[profile.dev] +incremental = true diff --git a/LICENSE b/LICENSE index bd32eaab..da684cc7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Facundo Villa +Copyright (c) 2023 Facundo Villa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 87516af0..781f6233 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Byte Engine](https://i.imgur.com/VRRaCOp.png) -**BYTΞ Engine** is a C++ based game engine with focus on control and speed. +**BYTΞ Engine** is a Rust based game engine/application framework with focus on control, modularity and speed. --- @@ -8,10 +8,6 @@ - **Current Features:** :heavy_check_mark: - Cache Conscious Design - - SIMD Optimized Math Library - - Custom Allocators - - [Custom Standard Library](https://github.com/Game-Tek/Game-Tek-Standard-Library) - - Resource Manager with Asynchronous IO - Heavily multithreaded task driven work distribution - **Features in development:** :construction_worker: @@ -21,11 +17,9 @@ - [Accompanying Editor](https://github.com/Game-Tek/Byte-Engine-Editor) - Custom GPU font and vector rendering - Extensible renderer - - Linux Support - Custom Physics Engine - **Intended features:** :brain: - - AI Driven Animation - Console support (Nintendoâ„¢ Switch, Sonyâ„¢ PS5, Microsoftâ„¢ Xbox X) **You can check the project's roadmap [here](https://github.com/Game-Tek/Byte-Engine/projects).** @@ -41,4 +35,4 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/5ed3417026d846cf994dd0f971111677)](https://www.codacy.com/gh/Game-Tek/Byte-Engine?utm_source=github.com&utm_medium=referral&utm_content=Game-Tek/Byte-Engine&utm_campaign=Badge_Grade) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/Game-Tek/Game-Studio-Engine.svg)](http://isitmaintained.com/project/Game-Tek/Game-Studio-Engine "Average time to resolve an issue") -[![Percentage of issues still open](http://isitmaintained.com/badge/open/Game-Tek/Game-Studio-Engine.svg)](http://isitmaintained.com/project/Game-Tek/Game-Studio-Engine "Percentage of issues still open") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/Game-Tek/Game-Studio-Engine.svg)](http://isitmaintained.com/project/Game-Tek/Game-Studio-Engine "Percentage of issues still open") \ No newline at end of file diff --git a/_config.yml b/_config.yml deleted file mode 100644 index c7418817..00000000 --- a/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-slate \ No newline at end of file diff --git a/aux.txt b/aux.txt new file mode 100644 index 00000000..86accb59 --- /dev/null +++ b/aux.txt @@ -0,0 +1,560 @@ +//! Async runtime for functionality crossing multiple ticks + +use std::cell::RefCell; +use std::collections::VecDeque; +use std::hint::unreachable_unchecked; +use std::ops::{Deref, DerefMut}; +use std::rc::{Rc, Weak}; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::task::Poll; + +use cooked_waker::{IntoWaker, ViaRawPointer, Wake, WakeRef}; +use futures::channel::oneshot::Sender; +use futures::future::LocalBoxFuture; +use futures::prelude::*; +use futures::task::Context; + +/// Task must be manually readied up by runtime +#[derive(Default)] +pub struct ParkUntilWakeupFuture(ParkState); + +#[derive(Copy, Clone, Debug, Default)] +enum ParkState { + #[default] + Unpolled, + Parked, + Complete, +} + +impl Future for ParkUntilWakeupFuture { + type Output = (); + + fn poll(mut self: std::pin::Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + match self.0 { + ParkState::Unpolled => { + // first call + self.0 = ParkState::Parked; + + // intentionally does use waker - this will be done by the runtime + Poll::Pending + } + ParkState::Parked => { + // woken up + self.0 = ParkState::Complete; + Poll::Ready(()) + } + ParkState::Complete => unreachable!("task has already been unparked"), + } + } +} + +#[derive(Debug)] +struct RuntimeInner { + ready: Vec, + /// Swapped out with `ready` during tick + ready_double_buf: Vec, + + next_task: TaskHandle, + + /// Stores all triggered events for use by e2e tests + #[cfg(feature = "testing")] + event_log: Vec, +} + +#[derive(Clone, Debug)] +pub struct Runtime(std::rc::Rc>); + +#[derive(Eq, PartialEq, Copy, Clone, Default, Debug)] +pub struct TaskHandle(u64); + +type BoxedResult = Result>; + +pub struct Peepee(LocalBoxFuture<'static, T>); + +impl std::fmt::Debug for Peepee { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("LocalBoxFuture") + .field("type", &std::any::type_name::()) + .finish() + } +} + +impl Deref for Peepee { + type Target = LocalBoxFuture<'static, T>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Peepee { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[derive(Debug)] +pub enum TaskFuture { + Running(Peepee>), + Polling, + Done(TaskResult), + DoneButConsumed, +} + +#[derive(Debug)] +pub enum TaskResult { + Cancelled, + Finished(BoxedResult<()>), +} + +#[derive(Debug)] +pub struct Task { + runtime: Runtime, + handle: TaskHandle, + future: RefCell, + // TODO reuse/share/pool this allocation between tasks, maybe own it in the runtime + //event_sink: RefCell>, + ready: AtomicBool, +} + +impl Drop for Task { + fn drop(&mut self) { + println!("dropping task {:?}", self.handle); + } +} + +#[derive(Clone, Debug)] +pub struct TaskRef(std::rc::Rc); + +#[derive(Debug)] +pub struct WeakTaskRef(Weak); + +// everything will run on the main thread +unsafe impl Send for TaskRef {} +unsafe impl Sync for TaskRef {} +unsafe impl Send for WeakTaskRef {} +unsafe impl Sync for WeakTaskRef {} + +impl Runtime { + pub fn spawn(&self, gimme_task_ref: Sender, future: impl Future> + 'static,) -> TaskRef { + let mut runtime = self.0.borrow_mut(); + let task = Task { + runtime: self.clone(), + handle: runtime.next_task_handle(), + future: RefCell::new(TaskFuture::Running(Peepee(future.boxed_local()))), + //event_sink: RefCell::new(VecDeque::new()), + ready: AtomicBool::new(false), + }; + + let task = TaskRef(Rc::new(task)); + + // send task ref to future + let _ = gimme_task_ref.send(task.clone()); + + // task is ready immediately + runtime.ready.push(task.weak()); + task.0.ready.store(true, Ordering::Relaxed); + task + } + + /// Polls all ready tasks + pub fn tick(&self) { + let mut runtime = self.0.borrow_mut(); + if !runtime.ready.is_empty() { + println!("{} ready tasks", runtime.ready.len()); + } + + // temporarily move ready tasks out of runtime so we can release the mutable ref + let mut ready_tasks = { + let to_consume = std::mem::take(&mut runtime.ready); + // use cached double buf allocation for any tasks readied up during tick + let runtime = &mut *runtime; // pls borrowck + std::mem::swap(&mut runtime.ready, &mut runtime.ready_double_buf); + debug_assert!(runtime.ready.is_empty()); + to_consume + }; + + drop(runtime); + for task in ready_tasks.drain(..).filter_map(|t| t.upgrade()) { + let was_ready = task.0.ready.swap(false, Ordering::Relaxed); + debug_assert!(was_ready, "task should've been ready but wasn't"); + + task.poll_task(); + } + + // swap ready list back + let mut runtime = self.0.borrow_mut(); + let mut double_buf = std::mem::replace(&mut runtime.ready, ready_tasks); + + // move any newly ready tasks into proper ready queue out of double buf + runtime.ready.append(&mut double_buf); + + // store double buf allocation again + let dummy = std::mem::replace(&mut runtime.ready_double_buf, double_buf); + debug_assert!(dummy.is_empty()); + std::mem::forget(dummy); + } + + /// Can be called multiple times + pub fn mark_ready(&self, task: &TaskRef) { + //println!("marking task as ready"; "task" => ?task.handle()); + if !task.0.ready.swap(true, Ordering::Relaxed) { + debug_assert!( + !self.is_ready(task.handle()), + "task handle ready flag is wrong, should be not ready" + ); + self.0.borrow_mut().ready.push(task.weak()); + } else { + debug_assert!( + self.is_ready(task.handle()), + "task handle ready flag is wrong, should be ready" + ); + } + } + + fn is_ready(&self, task: TaskHandle) -> bool { + self.find_ready(task).is_some() + } + + fn find_ready(&self, task: TaskHandle) -> Option { + self.0 + .borrow() + .ready + .iter() + .filter_map(|t| t.upgrade()) + .position(|t| t.handle() == task) + } +} + +#[cfg(feature = "testing")] +impl Runtime { + pub fn post_events(&self, events: impl Iterator) { + let mut inner = self.0.borrow_mut(); + inner.event_log.extend(events); + } + + /// Only used in tests, so allocation waste doesn't matter + pub fn event_log(&self) -> Vec { + let inner = self.0.borrow(); + inner.event_log.clone() + } + + pub fn clear_event_log(&self) { + let mut inner = self.0.borrow_mut(); + inner.event_log.clear(); + } +} + +impl RuntimeInner { + fn next_task_handle(&mut self) -> TaskHandle { + let this = self.next_task; + self.next_task.0 += 1; + this + } +} + +impl Default for Runtime { + fn default() -> Self { + let inner = RefCell::new(RuntimeInner { + ready: Vec::with_capacity(128), + ready_double_buf: Vec::with_capacity(128), + next_task: TaskHandle::default(), + #[cfg(feature = "testing")] + event_log: Vec::new(), + }); + + Runtime(Rc::new(inner)) + } +} + +impl TaskRef { + pub fn is_finished(&self) -> bool { + let fut = self.0.future.borrow(); + match &*fut { + TaskFuture::DoneButConsumed | TaskFuture::Done(_) => true, + TaskFuture::Running(_) => false, + TaskFuture::Polling => unreachable!(), + } + } + + /// Call once only, panics the second time + pub fn result(&self) -> Option { + let mut fut = self.0.future.borrow_mut(); + match &*fut { + TaskFuture::Running(_) => None, + TaskFuture::Polling => unreachable!(), + TaskFuture::DoneButConsumed => panic!("result has already been consumed"), + TaskFuture::Done(_) => { + let done = std::mem::replace(&mut *fut, TaskFuture::DoneButConsumed); + let result = match done { + TaskFuture::Done(res) => res, + _ => unsafe { unreachable_unchecked() }, // already checked + }; + Some(result) + } + } + } + + pub fn is_ready(&self) -> bool { + self.0.ready.load(Ordering::Relaxed) + } + + /// Only wakes up when the runtime manually wakes it up via event + pub async fn park_until_triggered(&self) { + ParkUntilWakeupFuture::default().await + } + + pub fn cancel(self) { + let mut fut = self.0.future.borrow_mut(); + match &mut *fut { + TaskFuture::Running(_) => { + //trace!("cancelling task {:?}", self.0.handle); + // drop future + *fut = TaskFuture::Done(TaskResult::Cancelled); + } + TaskFuture::Done(res) => { + // consume + //debug!("cancelling finished task {:?}, consuming result", self.0.handle; "result" => ?res); + *fut = TaskFuture::Done(TaskResult::Cancelled); + } + TaskFuture::Polling => unreachable!("task is in invalid state"), + TaskFuture::DoneButConsumed => { + drop(fut); + //warn!("cancelling task that's already consumed"; "task" => ?self.0); + } + } + } + + fn poll_task(self) { + let mut fut_slot = self.0.future.borrow_mut(); + + // take ownership for poll + let fut = std::mem::replace(&mut *fut_slot, TaskFuture::Polling); + + if let TaskFuture::Running(mut fut) = fut { + // TODO reimplement raw waiter manually to avoid this unconditional clone + let waker = self.clone().into_waker(); + let mut ctx = Context::from_waker(&waker); + //trace!("polling task"; "task" => ?self.0.handle); + match fut.as_mut().poll(&mut ctx) { + Poll::Ready(result) => { + //trace!("task is complete"; "task" => ?self.0.handle, "result" => ?result); + *fut_slot = TaskFuture::Done(TaskResult::Finished(result)); + } + Poll::Pending => { + //trace!("task is still ongoing"; "task" => ?self.0.handle); + *fut_slot = TaskFuture::Running(fut); + } + } + } + } + + // pub fn push_event(&self, event: EntityEvent) { + // self.0.event_sink.borrow_mut().push_back(event); + // } + + // pub fn pop_event(&self) -> Option { + // self.0.event_sink.borrow_mut().pop_front() + // } + + pub fn handle(&self) -> TaskHandle { + self.0.handle + } + + pub fn weak(&self) -> WeakTaskRef { + WeakTaskRef(Rc::downgrade(&self.0)) + } +} + +impl WeakTaskRef { + pub fn upgrade(&self) -> Option { + self.0.upgrade().map(TaskRef) + } + + #[cfg(test)] + pub fn dangling() -> Self { + Self(Weak::default()) + } +} + +impl WakeRef for TaskRef { + fn wake_by_ref(&self) { + self.0.runtime.mark_ready(self); + } +} + +impl Wake for TaskRef {} + +unsafe impl ViaRawPointer for TaskRef { + type Target = Task; + + fn into_raw(self) -> *mut Task { + Rc::into_raw(self.0) as *mut Task + } + + unsafe fn from_raw(ptr: *mut Task) -> Self { + Self(Rc::from_raw(ptr as *const Task)) + } +} + +#[cfg(test)] +pub mod manual { + use std::cell::RefCell; + use std::future::Future; + use std::mem::MaybeUninit; + use std::pin::Pin; + use std::rc::Rc; + use std::task::{Context, Poll, Waker}; + + /// Beware, contains allocation + #[derive(Clone)] + pub struct ManualFuture(Rc>>); + + #[derive(Copy, Clone)] + enum TriggerStatus { + NotTriggered, + Triggered, + Cancelled, + } + + struct ManualFutureInner { + state: TriggerStatus, + waker: Option, + value: MaybeUninit, + } + + // only used on main thread + unsafe impl Send for ManualFuture {} + + impl Default for ManualFuture { + fn default() -> Self { + Self(Rc::new(RefCell::new(ManualFutureInner { + state: TriggerStatus::NotTriggered, + waker: None, + value: MaybeUninit::uninit(), + }))) + } + } + + impl Drop for ManualFutureInner { + fn drop(&mut self) { + if matches!(self.state, TriggerStatus::Triggered) { + // safety: value was initialised on trigger and not consumed + unsafe { std::ptr::drop_in_place(self.value.as_mut_ptr()) } + } + } + } + + impl ManualFuture { + pub fn trigger(&self, val: V) { + let mut inner = self.0.borrow_mut(); + inner.value = MaybeUninit::new(val); + inner.state = TriggerStatus::Triggered; + inner + .waker + .take() + .expect("waker not set for triggered event") + .wake(); + } + + fn state(&self) -> TriggerStatus { + self.0.borrow().state + } + } + + impl Future for ManualFuture { + type Output = V; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut inner = self.0.borrow_mut(); + if let TriggerStatus::Triggered = inner.state { + inner.state = TriggerStatus::Cancelled; // dont drop value again in destructor + + let val = std::mem::replace(&mut inner.value, MaybeUninit::uninit()); + + // safety: value is initialised on trigger + let val = unsafe { val.assume_init() }; + Poll::Ready(val) + } else { + inner.waker = Some(cx.waker().clone()); + Poll::Pending + } + } + } +} + +#[cfg(test)] +mod tests { + use std::sync::atomic::{AtomicBool, Ordering}; + + use futures::channel::oneshot::channel; + + //use common::bumpalo::core_alloc::sync::Arc; + + use super::*; + + #[test] + fn basic_operation() { + let runtime = Runtime::default(); + let fut = manual::ManualFuture::default(); + let it_worked = std::sync::Arc::new(AtomicBool::new(false)); + let (tx, rx) = channel(); + + let fut2 = fut.clone(); + let it_worked2 = it_worked.clone(); + let task = runtime.spawn(tx, async move { + let _taskref = rx.await.unwrap(); + + let msg = fut2.await; + it_worked2.store(true, Ordering::Relaxed); + Ok(()) + }); + + assert!(!task.is_finished()); + + for _ in 0..4 { + runtime.tick(); + assert!(!task.is_finished()); + } + + fut.trigger("nice"); + assert!(!task.is_finished()); + + for _ in 0..2 { + runtime.tick(); + } + + assert!(task.is_finished()); + assert!(it_worked.load(Ordering::Relaxed), "future did not complete"); + } + + +} + +pub struct SystemHandle(u32); + +pub trait System { + fn as_any(&mut self) -> &mut dyn std::any::Any; +} + +pub struct Orchestrator { + +} + +impl Orchestrator { + pub fn new() -> Orchestrator { + Orchestrator {} + } + + pub fn initialize(&self) {} + pub fn deinitialize(&self) {} + pub fn update(&self) {} + + pub fn add_system(&mut self, system: T) -> SystemHandle { + SystemHandle(0) + } + + pub fn get_system(&self, system_handle: SystemHandle) -> Option<&dyn System> { + todo!() + } +} \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100644 index f916715a..00000000 --- a/build.sh +++ /dev/null @@ -1 +0,0 @@ -meson compile -C build \ No newline at end of file diff --git a/conanfile.txt b/conanfile.txt deleted file mode 100644 index 7524340c..00000000 --- a/conanfile.txt +++ /dev/null @@ -1,7 +0,0 @@ -[requires] -assimp/5.2.2 -stb/cci.20220909 - -[generators] -PkgConfigDeps -MesonToolchain \ No newline at end of file diff --git a/configuration.json b/configuration.json new file mode 100644 index 00000000..7d4fc6b9 --- /dev/null +++ b/configuration.json @@ -0,0 +1,4 @@ +{ + "name": "test", + "new_field": "who dis?" +} \ No newline at end of file diff --git a/docs/_includes/head.html b/docs/_includes/head.html new file mode 100644 index 00000000..2aaab36d --- /dev/null +++ b/docs/_includes/head.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/docs/design/index.yml b/docs/design/index.yml new file mode 100644 index 00000000..6e5dab0f --- /dev/null +++ b/docs/design/index.yml @@ -0,0 +1,2 @@ +order: -2 +icon: gear \ No newline at end of file diff --git a/docs/design/readme.md b/docs/design/readme.md new file mode 100644 index 00000000..39e21d2e --- /dev/null +++ b/docs/design/readme.md @@ -0,0 +1 @@ +sjkskjsk \ No newline at end of file diff --git a/docs/design/render_design.md b/docs/design/render_design.md new file mode 100644 index 00000000..4cd0767e --- /dev/null +++ b/docs/design/render_design.md @@ -0,0 +1,5 @@ +# Render Design + +## Overview + +:::code source="../../src/window_system.rs" language="rust"::: \ No newline at end of file diff --git a/docs/logo.png b/docs/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2cb1384c1fb4ca2d3044deb8d3c383669828261c GIT binary patch literal 25252 zcmce;2UwF?w>G>(R|Hg4kZuE|iu4++U;$KAs(>IxKoIFQ8T&}nK}9->0!o)69TW{B zRp}i>Kzb*Hgyh>#Ac%9m>wM?EuK)b+%M6)^wO6@U*=v_4f1lOSWZTHI5dgq;QtQ}x z05-#q41k3m{<<{gu!#JZ&0+1s0Az-+lCChq|3i7qSsZ_Yb+$ZGxNE%8H-PYJ1t?7t!}aB#Qkhs#oTkIP2u9&WML zXtdhN%X7HZMx)t!C(lmaU3}_QS9kVsxbgG&LHmc=&i^!p^7^84D>1^N9-a?&as*!>`d~wNFo4 zrNl(N+G5|igFHffe8K|CxrWO5Mrxl-1!VTBmR%N77UtV0p#H^N?!{RF={;%{=4xNe zcOMZIyP>N5-cV3}pHh~AV)`YSC#QEEKCt_^n4sKVg|`<(?Ud2A7Lu4Ff(rW%SS!kg zYfEB|irOnHBmQQv))2WYC;d=!udbBTonz{iSNKJR z#2i(39}_(ka#Hk~l2W$8p+_h8TPpC2?>cz*xY9fQgZGXf`sb98ipX9aNtI%gJ(}Xe z1~R+U_e*%70m8Mza#Rm&a0MQ zRw*>zZ!WK#XSDmM=$_LOs--4^ioyr)pAdIZ-=(%+{`GmexU<3+r4QID?L95A>xigQ zmj1r;2M>jw-lcIs+(k{yNmVXZcNcp90V_qBr>7N?FYrt5mW|R;NYax})RTR#EggJP zwcJ$fx{A1~x@?5DeEhjx=mUFBN*w%KbMILx5ffQa2bD(^yoLY>fs@A$U+`=n>$1B2 z6ZayiPer?-Q!T5wXdx|J+S)o;shaw~D3_0}&%>q4ISNJFlL^zAO5+&Ao{u0+V# zb1|&of>Q&=5Cx+=2yeCt`OO0V0a)Z;|L>1<2$c}>FYy2Rh^12f&zK8QY5!jw*NOb! zV*WoLx&w!>AP?XV^#MZk ze|bP9gA_t5)rtiXMIEyG;J*hi8V)t4S`Yv0&j-EFH~|Xjj2KqhBa{ZDU-v)*tUh2sDBzC<5V{M@ z=RigRf@-83NIB5F4UWH&#e|jn9D#^(Y+m{6fAawjRImpIdQetbO$3z-w58XY4cI@F zV}$HFQ&8sGnF;XWij4pML$7sB4G(~NXh1y%5iT2{oq2}zYahxYEVNP3Fq+i=$%lVw zmU3XdiVXi>skovU!-_&shR_NOhyheQ{_h|13|$bwSD?x_q%VWWvmk)4eaJ|F@M?fE z8Zc!wMo;2HMgu?eMzxLEgjSf&jfwaU^H2JJu)<$BsOl8pY)wfN;3UdP*Dl*@lJs~Z zQ|$K;_p~b*&3oqVK%zne*j@&Umxp4OBZ!liOPrEF_2u^!af{5{Qm!85`lL8J>xje= zHH4_YzSvIw>=mQ@iueaNG%a1*TQb`a+dR~>wZA&HaOen zx}(PfXG<)Msgb!Fk0|pXJRND+qh~9T9+ikwoJx*;x|HJI)g)a@YV z{-N1^>lUtLJPi8k@pSJ-#h98opEThKeb}GS)C=thCZQE7wnuAqU&)A zt&Sta6zlzggizd2G@tJyonYsvq06x&fhFX9(zW<+0y`l1)Lf?i!pfbwg()FRS?~>3 zosa$|72up3V)&=DI}0{FtSYB$_&NK8JeIv8IG3UeEqvws#s6f)a-xn!`HaG6MO;OK z(hEV}eiJ97KN%f!KKN6LuG8gw;89hX&jiv(ZX54fH7d@lrJ4mi9xGAkl^XYx!EGs7 z)bMT~lm%Eu4Oi*^N%gIB=L9nglld(Ei9z=+-}@<-sto&k?r9%hK$VKdSU1 zYr@R<`c)_Yt&m&on-?cW=poU?H#LK|rE6zKHHpc8%DP)T_U6h7yAmnfH?=*fm83xK zp*$zaKfTto9V1|!6tknhcS6ff(y41pKVPY5W2xAmRAtfuLPyXUxPO4ux40Y^|X{DUU$SVfUsnXTU*+~eZiPs2%V z+&1_iam=4YLQzuN1yh#`E%{mx2K}uX=V1Tnp;_HJUy0DtGME?oo*^-KFk^m;6fk>C$^08ljyK&)a zk{yCve=yQY1%VcP&Ae}8S)3j?o5lxXO#ZM+D2J}TZF^r*uu}4f*NtZBEjsr4ntxEl z?Pd<}@9*xZP<$KkHint&vtlwai|qDiK=)2aDq6He@%AU_q`C8uLb!)qC*=P0LleQ^ z!!Dw2;Ozn@o2OakLw?e=!|~yil0OQK21AIL{M8N*oMMv4MJ3kmE&YKL)nqqTDywXH z;Ce6UyNezJQgv9swfx1(&$zJ=3%#KN#z$?^T<-nk>U-P?j$Dzf`EFV_4O86Q;} zx*B>6$gB=O$K5oOl(*A;;C!Yo*^ZrbEilXLNX(vpv(m!dJ#oEmS~_^R(JrCv5H6n& z^J2wXq=r#V+G~!lxqEM13DP_q7qu>1*e+c=fEiL|T7?&dGzswYg8`enB~0c+ZIH0= zVl}p+LNPSied7ufY7YiWq6Sa*S=&zXLENrrkD~<6-g~naQI+>+`S1Ko=&`KPv?KIf zR&`4`Ga_XjqTNsa&FE@Nw87P0Nk!okPx5lcDk#mDx9C_-GOjw5ZnXeE3MR4!bq-nb zeJ57=lS()Di>t@t_x}qjp~3sWQS8u7kr>YY=e6SaKC}!@sYo4fEcS20gv#38NAZ)= z?AP4msx>KP;*jnD-kDnK5qGaxp>ZKy;*hJcV4$;>;DOn17^^^;#X^aH!KGDodVyp3-3QGF8PW4TP<%%QCV-nht6752HHI1-ZTqxdhq&)(|a7}Pu5@>ww`K}b#3W;9;_tR zecK;aId;#A*Hm5xdNkbQ+TJ@i1`P5T(V$ z^NmWQm2ltKO+~1Gk~N$n^R4@yrvq;< zc|}e8>IYgD50Dlv7rXU%T+!YFO9T92z;3Iv8dbrl1$fmhjNhuj-{NL=tBm13nm+{H zwRCHTX)zsWe)11pnS}wb8Yee(i2ydgLXoPN-H)*Xn{8e8rNX##UHq1OJ$(IIW(~Mx zec1P&KM$tfDO1-U?K=RwO5cRv-~LSI^S5Po^EC!neGKWdk{12C(gEt)p1FDGDw}z{)xYC6wUgckmQw^|AQSUogcf z%|6;#U+!TS7*9Hu{!~95U?HR{%Nek_sn-8VI-S7|wKRP=3#q&>XYXFHvEUoHHeTe- z2vR$N*#{V;mbf_F(H?WYTmH$%Vk|Y5*Zo%vZ$EcW z);{Pp1aPe@_#VH-5Mj22G(lw1bqNnL3dj|G9+`FGz87=@GxOE)5s&CS%JZdzr_GGK z=QpklvnQg}J~GPQWc&**sB$8hu}v?~?4?0|W_|HX4uM_sVMl{I!YujvY&zD4XiYvY z3GtLwP(&6Ysm&PeH6K^eu}+oxuIoc^BX+~`v(wW?l{k#g$`LP=CFh0$$MQ@T%TQ4M`#0Yc#M#>+8#zk`w>2H z39deF%J?`wI9fpZ!A%?!;X-G0Sn#!c4ugFdT+^b!+nnmfP2c1$(EQ-$Q9nNRbQk*@ zLCbhQ%jy0CX`J)Cu^-LVhXIb*Vct?OhGweX$ zatYeb(=1JI>O9;9AhXS%w z63`t&pwWkUF2xUp&q8l>X}M$(XzA@xMWb(u9P$k2=9NTL8Y!kPKo_%( z$4)-XXzSMh<>E8zw}t&$ODe2xND5&eO59Y{bl|2Dd!H`j9~YtHZ>X{;>LinPYtGGc zYtFsPHA9L70?zx#{Yn<*c^a@CN+PiT;-GW9Cbh{$t0k7pved6-iP=>@uwQ8s=}*cc zpm&>?ykho}*kQb~0J$Di7w-*SpKEcJ-oAlsc;@%bYEh{iIK`NX_vF;dcO@0nV614 zxM##D&K8yDoOORY%bupy3KT@6Gi3vKJ#tUwZU}=)5;`bzh&<HKaj9pzy>Y}&+yxFDwo6}@w8+sCv3uFtJL=v_V1s=IK~CO=nw_2|LzF(*zYWQuuJ zJCJ*fzRd8PKW6fz7kl5k{iP>7pV4^k9#o3igS*FyP_|EEC0XAWviq1jJ(!*$`poiu z@Ui6k(33|~*YclbrI$9@RCSlxZDU51kX7z7KBtYNH^hRp96I4lOFf+8tlp-w^}d8bs~XORixDwd>Wr!^3+KAS&a;g~|@N@4%?mGDp1Z07>o#9LO05?>n}Iu%%H6IP9M`!mS^X#E+Q^G?L%7A!-=3IIZtvt8e-7m7astB6orT%XusMqd4hPs4g$XQkpe1oVY75(FT$i>3B8IBy6EM|xqvwWT->+_d%RT;G!<<-Fb-WaYn z6UG<9#(~VN_GbXg`<7+z!16)~+$CQ;S(6e^^r%=&eou?vy>DCmUZt}~@bXc$i2?`N z+&5MnS1PfoXblh?$nr%8PAkNY)8Z_x_OWDA+xIeR$rNV9DhQML@y@0}n6L56m5CRo z)96vuS^k23x8EW&ib=0!MUP9M)%#?I-lA>P9+Fnz_#&_1xD;6tXGVHLi_8(_fMMI2 zGBHYgP)PtYGHc060+LYYfue)8TLhkeZVl-nf5A*GaATa@%T|$DP0|aVlKnRlrvkO^ zds+vw5i;)!4A=21%j0@{qE@-DmWQMnlaGGPz1G8;H9}nV0!#RSX~-xZvzSekaewCda=$o|pwsza)Lw zLrEQ~STr_sUrh}dj+=p~TA0*5mD^4gDqnePgEGY^Umuej^({!RUD9bOM5TMH8kUOf z$)MbMP(kSA?wBdMtgyrRs?xoZc>HdGA=qAxRrSmjVt#2$lWU_p z($;!6Sd(54z1wmll34qk+1oBKh%l;48b`bQP=bU#w0wlcg#|o~sUp((7n6hO&vDEb zOS=!oQpQVX2;7)~;y?K14Bb4~D~~V9yYCH`-Nv)UXun0ld~>He=y&~xeggwgao=6? zWqWynz_9-Ot$Y<+z$`BZg_l>FjN_!0SXhb~uy%D;+iu1Z+rKau!s1srE22K9>kH!| z?`p`u3@(!Ubpjuq$$?jr&K=SpC)J@dX5VsS`jq}q@b%Emk3v7y@tvuy6@{~7+{9UZ z%8;O^TOfuq7X1h1)1jN>klT)~rTml!rCgS`{YiIA$wN}A>bO$M{XZxnPm|W5iQ;{H zGnN)(^@XM6mco6$RdK%+q)t6;_Vkmku_hm-&2F5zBeAqo*LzA3b3U+Vr|KZxAJBYt z*|6+|56%6mI1*`5q(zBfri{0IT6~YDWf`@-xZov;<|uCPGdytL4|>dfxJ7+R*NnH{ zOnvCsAM6TT+LlIpjl1-!lxD&zS`&J1lI`5c64K;>9+&ko_*NxMjf=5octYju`GQ6B zK))q>{p7@oMGth|!0&Z|5V+tjNtw}=BfldSS~xT^r~ANFR4Fm!4@fQ!y&Iaeba1N^ zzy2v!uzxC~5REHc^8G`vmo9Do_5df!*RX&)BQi*6};5QCgreyv}{SGd#q6PCs zyG`*nuY(EW^DN*!two^5`Rkaf7l}nn+ry4^jh4iB9;P_+FHoFZ*TZy5F>KbSrMhmZ zLME0xT<34CKUO^9r7Pi4AA9~jn4(p1>hdq{O841?B+9{M>F__&iOuEAFxuli#$&|t zoloiSIKhJYgHB?YRt$Pxn(&Rv!RK}{&i1`5mF7{M;rwy6QBCy<+Y{@A}WL8e#iu(9ZIa--#M|p3Lp)Mfni}l6~@*25k(T z?Scq|jC@gp4RGS(1T%^YPad8ilU*x*`qPHS>39VB;mj>fMiqFZ3hkZJ3fdL8dv_A%qTHRG8D%bvqL?0W*aG zSsT}9WbWiz9t{7M=T4uuX|_?`@aJ-h7rM&xo?6Qlg6`%)n{T$9KXWMe6@XLNR%$QF zS2H1&%)2yh{GBh)hzlhHLj;xad66)(NMb~)FezaE_vYHzj=j?`2d`Yhgk zWbit*8)3l8qQMll<&~l^b-r1VTieReY1(8J&@@`ndYP>tT=z0Kh!(8zIS56a?`AH)C7WJ?;s+Dk_WI6GFEr&s0Ac3lR^V_BQa>_^} z(?HYuVOKs)?i>|SvgkM5pv!qXKDH1JduF66AdOm7)<9OdbY(}oJap+oZH6vhWBcku z?bK1oYDxBr!)_;e;o;&h?K_{&9g|jR524!#28XtYGYv@D#S=EJj86BJ3mW=_(YC)3 z^J~o`cQS|1>^75lq6Bz>)4Ky=IGk|m67A!G@K z6%MS)yTiqscwk)oUe@_oF(y`sXmvwk!qZgy+XJh^1_wWTyguYtQmPPru8ruoHkc_; zTd6SUkEE{Q7~4!VDz*tU1+i&i!Z&x2=}7^N6`l`5}wT35%8uK2)HXRqWndE*t<1|#nAOZ?5g z=i6j(d;AKF;6P0LM_r0dcrwz9q#pD+Z^UUkib;@`q_`l9ft84xu#}M`ynVC8)spPz zl_Lh#40$Va+R86-NeOPnDcGm70R_|8_D$X=c<5(0tszqoQjgND~cL<7e@iZ!FLzefBBEBe6xnbH`oiumnOc zDM~o!BO4CxhIgjqNP)3s>xX*3?gS(Yh6hl}p_<6Hv7BI}-2(5^>tdp$MM`{32@JRd z8FYh}3IiQh;tn`_H%m&}g?&C*FroxPg6!AYsmot1?l$KSR$~RIM%=y_ulB#-7!`N~q*&NJ z408Y;tzeBpv=iF{Y~q`UlpgOOLtslJjcK1Z9roQG2lc4usX&jzjEp~JJY9v%_6X#o znQus}6<_@frHfni1&tt+XLWVic*;gBGD5hJGT2|K6F+KpzALZjr#HZ-uuI z`w;Fr8!U>msHmY<#y9kziGLK{C3giy`VT`W1llP;Lj2r;=1=`z-d9-Hn6!zyhxO zaF$gyM4qZEC?GlKc_VH8%E27Yvcb^B-p!Ml^aW2TCmZRq#P^AWXyk`WuBCSicI~qV%n~*%^GnGmUWtzA~B#>c0{UdoM>d><-XP)bjk5MvdgbhBwPRWyc3%D93*r%Zyc} zS2VQ8H`L{zf(cvgZI(4{at$aAwZ%n|)rX%YHa=s(?x?BDnQe?Sn~Ps8CNG(7P&D0z z1Z}k?`)j$#TIKlaEcBo_wN@ghl0ozu!2urG6I*Is)U>7-I7cZ_q?BKWCCcj>+^M|W zFtINe7fQ|PY)3s(5bsJX*rcDfS1x{09g4ZV=Gt0#FtRX$@=~u*JMEZOeZ+URzcr}jx?4!AN2UIT*}?8WpP@#klu&uZNU?Hb+AOUMa0g^<#xq;J+W!*KEYFG$^vpX z(`k&P<*B~jIsfpc&eHa@%djpWiJicVy%E_vR(f+s-=5E-MIQ^c^vBnX`qvr(+ZmFH z<^H8_F?uatoMmM#)RY@{X^OdH-T2g}N^ziAzrY>N*$5vV0U(Srv#u_hXQSNvA*T*D z_YF|y@%nTc@k2J`$;7D7CJx^As)tILG?3_hA>|+<``Z5;ZYM<{EN#UejdFU8Ru2{3 zcM~I9J%b~v<7?VXADt8fvey3YGw8*~W;e|Gxnz9Vs73n-GiSv4#3D5^p=5d68iy=; zjo!$mYToGj$VrkQczz-}XO}vY5W+%dCdNZyX?ElwzT*PZ>~_SdqjQ`Qdi{%uD((ZT zC*QIvfC2Mz@={jZAO&cQ?UO7Ml>o9<{tJ3Vs7PJWm`5u(N<>A}zbe?XP}$x05oy^W z0=BMz`%Y|~p~sKEdMvwA$<-L+#3?RRwmLF=5N2Uqlv8IN#U7|LP%C@Am(6RLHzl0J zt4=O`H0es#nZJi$ zOn>O}HvMMTIu`9V)uNu#(nE@8z7mdSnSP+Fp8@sH32nMRidY98Y3Xf6mF+kJlI{{4 z!Y_tR27A3M#1}f!+{gzk#$^tb@Ce=%d+fq1b6}LKhII$lof(U(t|JK5wB=ty8Bohc z`%r13OseV5Syi*)cQg=gfCqSGOWf^^@9TzZZblQbi}){P($$ZE`Y1xU)4aF`1-8kX zykVEafNfTS+p!5ve;F1vMDgEfqZyzGJ`rQ41C1ZvNZ&W;6EL4$U1^*IvXv1Z4ifzz z9v(h@rk1YWj9O~yEWd~A+u&5HWG?4Wt11kAb|8(h5jT!zUpPHP@Ta?BG%+S|9<=j; z2pP1CHuf;17#!d017Ht=l`l|>{(Jte!O)^VSL$jM-lo@Rygs$N!zcRaa=r-~Ww4-< z60i-sgBd$mU1!oUdUzk}nG(8;zLK-lKn`8lE0gKiwS8!tN7u+p8W4`)`7yswhf4Me z+KQ>`dQ)QYY#Zq`$_H)IIP5RYZTIPa7>nBs9Ck5a=lmq1!{>7pZ5FLsQdU)Pq1PC5 znu&O(#OLK-<$M0K{&Tlx2>^RgnAZWSLuzRwO1Wlz*~dV}U3m1_61i z8}VC%2g^L&hZ@e^At-06I)S7?{${08CLLf~PpY0@2)X8_`>x@MfB*w9eqhar^{i+e zy*yju;Xm1h?_M6)op^xZ@UT?Y8!dzvrSc^WSBu3U6V`FALcD<(Q$FTYD3|A3FxTx4Ku-oGcH{{6JfWyARwJ zT1Ho#PI+2fuH3_#a-9QcN5m>w52ff2WH~rp8s^+d?QA!fkrj$9JU&I{aV2IQSC=ET zMUOoEZRq|hTWx$o+#c}j28S6GZrAydI!f~0G?h?eXonz zGA=p6KYS)_=&t&Eu6*;=$dBL!OIE73x8LFR5KpIsii%A8MoZB-*dTSddivec%aNfr z=ht;tS1Q2%7797@@x%`u<$d9mZic;5YOT)Utd~~1k4#itln0N~lkB0&68oJOme@xF z)0J335VUQfkvGR^Ad#8@u60&Ee8ZzaJ)(BZ+oe^euw!0yrLfm`g0r={K{iYCSzxj< zcCUMPNJ=E-g`E{u8~>&4LvPH!&dLE7h5JY$`#SV)cEBmbnHS$gUs;`|7IsH9^YlWV zDJ`ja!KtN1$HXYhO7e#R$EJong*Qu?Z>dwv*abr4X8T)vZz}CVM3=?;jA%=ju=X|$ zpGo()tC}8LX!0ANuinFwRrgbD?ov(-I<>@Jq-?Yo!CN-rK>aI1`0{(ft!=tCn6R(r zcVS!oXffYaxNow5qVtrs_qeJ`=e6kKh5=FP;V};{NI0oxcbuZN&;!o&ZEr3C^=}E` ze(u7L5(QL$j0w_lrz5S&R&>~`(?-l5{QKeR^w9F?CcH^1a*2V537hLL=GM*D9G6`; zVckByLoK4(?A^i|SFmBHEqt?XRe3_gE%o ztp7F5Tye|((D^w|ue)yhLH0F&Yya76M|$4GE|>e4Fd+$^^dX;QyQ2UU>4F>cJjTeX zHi%B+?;g3BVa`d$(rLe#`J%ADRZVzdLp?a8`XNhw>97sC^`iw919H9z=3+0Hx`rxi zvUkXYwf`(7l*FJFhay2=;s%kaOkpZ%H{_ghqPislXw`Wl&CbrrEL(F!05an6| zdPn4Pkrn(B1NKl)u1bI)cvn(U5L(^e#089G&{-vuuKzU3oLZPfjin%%+1-##XC(<> z^%#MEdgf=i-Owlu&giLRTQJM&PG^U_E9QZnRd{STW?njTC@sP-Qy95$URV{MPil=r z^%Cf?$t|rG@IrtcCphI-lg8_JKXRTE9Pqo`b_Cc~lEyC03UTSzc}OBx!Ltf|k2$sR z9|B`4=hgtyrqjsx7+d}o85<~q)*jgsxdDtnk2Mth^)sg6P$^^CB(;%{Qwr<2UBcKa z$grm9UJw|$9eC$-CWjRr7dn^&R}Wv;)g_Iui!u*-+j(y);&C;0~{N zm=xo7z>T)E0pRS6j^dKLi&33|D4r23UtM=@ABS^((AV?guoyQES=to5O6&omB2_QI7q!p zT+|+bNijX^^3S*rhYuVp-qlQ9#J5kp^Ki_Q;c3C#@{;FT*$v|WS$h+&&0TkWSbDJp zc6DfUD5<-A?2tcOoD_9=IO5Vz7`|a6n@VBGI=OP;r-lP`?M)nBqIl=l9S|X$wsJwm z4bQq5%(A)SbPtNdoe&n_mOtHzInhwUfb@z7#b8MhdgEcB$qw4OUq=nvq=>-DamXfj z@>}daV$t_E1Ql*%Bc$yzIZgkL%4?eqG)%PAz^3m}38R$Jwp@d2{y6VlK-Smanz*Cb zu|QY6P2F53lbaRFo6nzCRq8xY3=i5@vvve!9x*5zIZ1iEHn)co^*}CbyW)!w~n4gMwv8X@KNK&o0cwFA_<_b5Yth3H2Qm*-dfhY z;s*(TQ)L~0Yr{XY)lnDNwnAwemQ26ai3ikpn_XE66imzU54FQ}Yjpt*#H|c;L0ochJo+?GO7LV^V5cb?Df=!Wn$P`?!?O-jh1_=rlryY&c6aoXUe}(Cc~JRZbM# zxaMbN;P6UWJD%LXp%k4j0%Se?YqR{O`}SW8@BaK~0nfdn97)3Co^m2(-x`3!pkCK4 z;zXB5B1vF09MpFblsX-Pa@D6dB0*6!-O1vnDJSpgS6J*`D;=c8zXkGwvKI03lV0OHzKTS zxF`ZwUM^5j=_n=>!3t`kWB064;u%%m*spnaFCW+u#0m^+eT;|!c@n6&YqQ9UD;hv+ z1~(gFE;6sUUj7v*f6yzjSYam%2#SskU0}enRZ;6wJa3(8Mkr6Z>ao?bq@@6=8L>v{ zH?MC1+L5v2ZIr}iC0=Bc)IIE5?Fj!`q-wrbGi@qv5)mS+;Ay8}3!r`|+Fc6iqApTesWV9konLX}NnJ2(~WFnoEjXuw?fz*G!*$Uxc% zoz!ZOkwi2xV?omI^h)~We_rgNS0@yoqJC4QpxrN<}_^i3xj#;;GQb z>C2M3L;Vf_SucOHv!J+G!-~EEz;JKHVe{dG5gMN+PiFJty zTe^n7xx-gB5T0vLS%Pct*ajk0(K11E39fem3(TrY}ogtH|7uH|aGJBrd&6 z&y-}uTElsW!wCalPC#JWWQ^JFN+~4}*FrB)J0B&~as1JUeTp6`t_@D(nySLj4y|0- zI}jt_PATCk@vq<3v$Xlx& z*vtb;;Of#&>@hRTafgkdCMGuEOvq%b(LL$~!UvP}7yrUj3VCxibEsvh^(Rjx4+HiL zn*Px*`;^Pnro{Ni^ik|8dsUSwGG>;2tx)3<#=xWTfaV6$t}>|193kJZUmZqNWX_3k z$yi=*XhPIFwcWuN_w9QLJF&2jhWi96Xid2ZJ!1D+D;w0)gxIY4-cty*Od z>eogP6dT*7{^C&9bJ%Gkm${V*&!2Fe1aRww2Nu6I7HWPU?Rvf09IQ}4m(nET=&Rl=+WpN*<^kXx(ff4_KRK2Jk zQZlfKdXs8%Wo@BC{G$FkC~tvB(}i>ABY9vru+6%}jPDYdOR-roV80~BA!?b@{X6ft zBRA5OW&Cs5_1vsBDsDS$9(gYm!8R5-jNDw&9~_bewQ0bOpSw<-0Oa#=2|G|iqwj|k zpBc(iFMll10K!e=gvp)>7mNPE_l;uU#6B8Np>$_W*7e?u1~fWynHN80T$() znAn|Y`V6IxWW>T1c1kR&)kJvK6V9Be;jxCqM(c`y zR^piDXJRb+noOG29^vP!iLMWlEWsBT`G%q#EjRSQ6#w>%zhi7+lJJYFg(Dk0$K= z7wqNKw!nI_!^Wd6XmB#I4)cw_;#tl-W{MMtz{apUA!vM9Z6op`11_NxWJEL#Uv7?v z(k{YX1t;~z&Cn?l$KVECJfFi4fs4S_3;Zg~7@gjXc!2Fv$xsSIx0PD0U*<+27aJRn zetAgiM;K5p5A?ly7*=1~WNL>7CjlVqyQu52f*AxbQ5SZvrHw0ffEF&OQ^UBsMc-uR8sz4pBE8%GDv@9G*T*m zGX&X5VgX1Ts-uL6$RajDOO!p)%#NNXdXPp5Gi8gE9IGUd{& z)NKlP+3o!YJy|uLI-RTh_6^Ab1gth>vZo&V0!uwN@MU(?`=Vd1cR}}OQP7C-A0&)v zx}g~#4ec*p9pJ-Tpowe@G5{oA5Oi~ zz#^5i5ft*^NTx%dn}^!NGiCDupS#6# zboDz^RtFILQ7=h!kDPAh&W9r|kLzevL(X`F05U;%Gh$WI3}?Mj`!gt9AVL~FE0GfV z59`H}4F!D()II1o#YAK-Uls731rXG)n%SZDzk~Gc+)1Y-FDRu)=SLnvyzrWwkiSlS zxeoJzrG)wO9tL+8D0CV}2W@Jd{^EYJsOA&kd%xL3cRy4jyRnH2Su(A<`qfr2Gm-IC z6nsWT=ndK^4AGmltNTPu=8+iUpc3^)g4d^DY9Pit+zit0k~i>DIJ9p&_7)L?iaRiy z73Q(q;mOQJZ1Kt3@)gL z6uXPf29G<`5z%cw*P+yYJ!8iIS$?30q0~n7Yq*FBk8LOlSvG&%>5cxi;)mhmLEZ6i z2O1`lc3S3}9wz&z_^#^6hP;mO?(9W9c@GymTQ8p9I5w#p`x?AB_5k z#eOi^E3r&J*^OKcz`?U?9w`bDQb5d1(H)MR46856XH>$hEB#=UIvwHjDg-rGa3$tE zyu(vdCnw((d7InpQk${;YvhGu1i5j~o8{{z<$oASaaO9f*ra2#_1A%wP2SY`v`6Qr zINplejPhx=bWy!@X_-mqAdF)q_#;hFab(_<`IxeT7d;I1taw#X>aJvSB;%EyghPC( zZkst3kRwbDXzl6yS)!9_ns1Y zJ3sO;HSFBY>KE6!E5b2jaMW+!w9Lb>PT`0;bXZM9Y_c1M=g?U?0}tXPD^v;|3j65I zt}|_<;Db?`*TpmCMP+S~_xw)5Q&xGjzWrnwbJs^b*Zc*+9+SN7NCj-SYrnNlSi56J zGkIwlY=~BIMCNj3t6MjjqOd2N>>g!XWR^p@h;ZkqHX9YlGyStAauDyn+EE zXPK`u3mN)M*3sYnVf8<47Bxx*;&aVUPC6mYe7%lHbp5?`(v}=Eycy*U;^#50e&P5m zN|yNKMc5)KpaZsJnFnnrx)$G=NAR>#kZr2#Zq=7lTh|5UEK_p5X<{M#&V$;*{2o)a zUst_yw9YL{Oby zDu+q$35mokx5)#rQr6aOX6y}nW7jSy;N{WH8%&JXFgq!|a^T+>n{Bl^-{fopa)-oy z9E{$7XlI$)ubrUj737xpJZ*Vt#C0FY_Vm9e3OGu3n#+0{Eb|2k?}|+wqaX)y&B}Sm zCJuE9f(=kPQ!@eG6?D`Yow7jk1e!0q$yffuz$YqPzxTFW5$P5?*VB^zljlhi5aWB4ZdB0#B@$fao5xaVaR87R%7ch ze{BT(XOl)!CiyeX${ z{hwAVv0AOq$f{P@A>(|f+42zNV(SMC+=PeKPpe%`*o~CssuGNS$EyEe_{MGFO_|$R zcGLr2Y8j>12sBG(xq8TBRsGi7S-I&&WD}yvE@IH7F=?n<7t!=h zg@2LXIt}hQWPBF|p*r0*#&BB~zOJY>ecSjI_dttgEbR@hgCkw{>#xI>-trCb+wcE}2O{>{2=fqrx{$jx1QD^EM zryyIPM)0cu(6;026gbD5;`~pCD3neLLheau`!CZBo9=hlrjh1(%YoHagM$D(vTk-DLB3FqNxzoi@Ed$YmXFUmWK`Im|WtA@rPJt0yPci9#iA z22-t***@#yA&>3S-MZ@m^C4QmRu{gn`YcN{_8F5YnQMjjjjDI!>*2Vb@pdUD$1t%h zD;3lyfQ%8hWS>hsgt<~=Dd^6GP4{=P8C?enTc`QO*&U;f>0gimZ$XBUo2YkMWYheB z6m?H$|KP)h-0|Nz6p{Zyl;YFORAqqxUPY%N7fa7Q=i@j}y`3lxiiYm0bSQtIj-~ca zag4kv@8HBSzMYB=7ewcHTeRIs7Zvw*c;>SFIcEWx4p%m|;6j?MIpb4{zD@Z@s!!?5 z-nK}|paSpFE~|4U4VBY`$| zB3YB`kTKYBzWY)a>ohDE*)rhCQ{b=?F9*SxH|3honf0!%V-h3lr`iy-<&b-ejSLwN zmYuhEz#LbwA7=#>z7siNk+jYg$=-Kt%?C%Ge9g^7?%u|8S41T=1b3()+NB}4FEyLOajgvp7Z`?FGAQ>v>ir!1NAv=wgsgX)kBrDjlEt<4($a=W~IYpsQ4aY$-)LVrvjCqxV$MSd{lfC`Rn#B&3#5zZy&9-lmK(yr!nNm)k3#UqReSQ!dW*!;>F5E0O513frq?W?>reiR^# zX~! z_IO218O3SRG_+IpB?#Ox`My_kp|rU*IP{%;RCtHhtrN;N^yNv%4`W{PmdP=iQut#0 z&Okx%YsO6UdcPm>0rKi_V-rFE(hl6XX8+Tq%U6f?cTami&Kp$(^n)=}>--7$`X)pW zYroM+VvfC7Zir&;oJNP}!vzptV#YrsO|OzTI(JjB?*a7>;D&Zz&E3Je>o|&rEh}(B zF;K1RjkqP#+kW~Ns}u^lFiaGJn3qu2a_@_N@z;f^(fT(d`(VenqN1lqQ%*~L$P2xB z>nH>c9!NShc%%@xTczDMYo*_eD22p~93vfkYF)@AluH+PuzGF0Pu0^N`pw3u3?3_* znMK8fuN}X%TTIJfJi+f-gJaocOcxIlG@2Hk*w&V-z;-KmrQ88GYj|v^FyC#`t(LFybJ-Ka;2(o zPSXidjcnPb*zH@R2}W868BOU}sPP9?@@GjyeHq_^?PUi6DEL}1M5#A|4xO#<%OI3T zkKGO-nrem*r}n3PDZ1CogDuK!NWaB=9nqHh^$=y~TlSz}cf6(K?FxtAPfKrg47>TM z-&bYe@RBP)rV7XjppOeCn!Rgdz7ZJnS|OelHd{!tO*Kd?Mb}wr7XM<$8m7V<-SGeL zN6~ohuO*WmsBPc+y8;xI2efb}~Tp(0SW154vu`p}WSwPq*Zm_)%Jj}6Psh|{Fo z(Jw37n@{XOW;d8byRGi3Z722aI+aP!mf7V0&cyCYN1j>PF!Ez4PoEYmb|z zrO5f|&0^(sqE|D`P{>jq{%DvEE-Fx}MMnGWx2qynteEmmqAwZKeF8hb4Sk9O$w7d; z=Ih(I*BAdji~XIJqSm^nPiAf`8>Z7~86@^1#RcX!R0Dm=i=j7)?$IHNll>l;$18l9 z=l}6SX@yfff>1DdQ3yVZ@zMjM7+;iD1Vu^!d9d$H-Ig8#QRsbzc>2oGP47>W}yyT*Z#15y!S|)x9ZO#nQ?8#YFzy|J;j;-;2SIHcrJ z0ZW{HY~dD-=%q796m}k?NtL=-Y4efv$qFq0!b!H2tcY55n|WO!MkZpIpuu-R!XD#LXTZ^P@g3>Y}KzD6&V^3mPA-@V_Qi4+#7N7IY|u zm1VF>0>rs{cj9AqTz4BX1s&bPnD?y!Rtp9Iy(#pqh*G^jw+l1hEM7=)u%};B^y+8+ zp%cdA;ejpvYM89ipq;DHt+C|lTQE9j@HTq`Av%ka#>+0^| z6$##Zp$ai~LK#e;Pq)8lQ%?qNrL_(8wI`$i4XM^-2SL}gGe;X7{3umK)KZCAq?c!- z;6Vy}Z<^}DFL6LMoPeff*C-d5#n8OcA_WF1G_camKsANtNYhgAoI<~9zv>aS0bd?@ zCKj6a2UyGC*)TG7LK(0@e|VH!;$z;*407gSY?N{0$hD3=9hVk3THAS#N#&Cxk2SAIWLZyVW09 zY5^tnqd(r5`hTiCFb06!qLBWhhtvKq?H2}1#^0{_KCR(!);F-bChWZ(_2!;H!YZ@Z z|G=vCgc*-%eLc(Y_QDr6U>E?w^x!^U!`5a0Htz&RJOjglt#^N|&Fo72vBCU+0Z-`W zZ+rWJaS8Or*DH0e!QsH*0OW#-7$9%}5y(uCi$G-;5D;QIfK_2P23?dm6OpW>mEq_P zBWMpPE+@rsLZOQk77!+l3?~=>7z#*mIfh<5o**rt);|C3KZg7T3_#%N L>gTe~DWM4f>H_-G literal 0 HcmV?d00001 diff --git a/docs/retype.yml b/docs/retype.yml new file mode 100644 index 00000000..0861cb21 --- /dev/null +++ b/docs/retype.yml @@ -0,0 +1,15 @@ +input: . +output: .retype +url: # Add your website address here +branding: + # title: Byte Engine + logo: logo.png + + colors: + label: + text: "#ffffff" +links: +- text: Installation + link: https://retype.com/guides/getting-started/ +footer: + copyright: "© Copyright {{ year }}. All rights reserved." \ No newline at end of file diff --git a/docs/sample_project/index.yml b/docs/sample_project/index.yml new file mode 100644 index 00000000..6ae1778e --- /dev/null +++ b/docs/sample_project/index.yml @@ -0,0 +1,2 @@ +order: -1 +icon: rocket \ No newline at end of file diff --git a/docs/sample_project/project_configuration.md b/docs/sample_project/project_configuration.md new file mode 100644 index 00000000..e9b0b35e --- /dev/null +++ b/docs/sample_project/project_configuration.md @@ -0,0 +1,11 @@ +Add a main function. + +```rust +use byte_engine; +fn main() { + let mut window_system = byte_engine::Application::new(); + window_system.run(); +} +``` + +Declare a system. diff --git a/docs/setup/index.yml b/docs/setup/index.yml new file mode 100644 index 00000000..97185a77 --- /dev/null +++ b/docs/setup/index.yml @@ -0,0 +1,2 @@ +order: 0 +icon: desktop-download \ No newline at end of file diff --git a/docs/setup/installation.md b/docs/setup/installation.md new file mode 100644 index 00000000..cf9e8c92 --- /dev/null +++ b/docs/setup/installation.md @@ -0,0 +1,11 @@ +Make sure you have the latest version of Cargo + +```bash +cargo install --force cargo-update +``` + +Install the mold linker. + +```bash +cargo install mold +``` \ No newline at end of file diff --git a/docs/static/custom.css b/docs/static/custom.css new file mode 100644 index 00000000..e69de29b diff --git a/docs/welcome.md b/docs/welcome.md new file mode 100644 index 00000000..c7953294 --- /dev/null +++ b/docs/welcome.md @@ -0,0 +1 @@ +# Byte Engine \ No newline at end of file diff --git a/install.sh b/install.sh deleted file mode 100644 index b2b6e7c6..00000000 --- a/install.sh +++ /dev/null @@ -1,24 +0,0 @@ -# Install Mono -sudo apt install gnupg ca-certificates -sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF -echo "deb https://download.mono-project.com/repo/ubuntu stable-focal main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list -sudo apt update -sudo apt install mono-devel -# Install Mono - -# Install xcb keysyms dev package -sudo apt install libxcb-keysyms1-dev -# Install xcb keysyms dev package - -# Install Vulkan SDK -wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc -sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-jammy.list http://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list -sudo apt update -sudo apt install vulkan-sdk -# Install Vulkan SDK - -conan install . --output-folder=build --build=missing - -meson setup --native-file ./build/conan_meson_native.ini build - -meson compile -C build \ No newline at end of file diff --git a/meson.build b/meson.build deleted file mode 100644 index 772003b2..00000000 --- a/meson.build +++ /dev/null @@ -1,61 +0,0 @@ -project('ByteEngine', 'cpp') - -src = [ - 'src/ByteEngine/Application/EntryPoint.h', - 'src/ByteEngine/Physics/PhysicsWorld.cpp', - 'src/ByteEngine/Render/RenderOrchestrator.cpp', - 'src/ByteEngine/Application/AllocatorReferences.cpp', - 'src/ByteEngine/Application/PoolAllocator.cpp', - 'src/ByteEngine/Application/StackAllocator.cpp', - 'src/ByteEngine/Application/SystemAllocator.cpp', - 'src/ByteEngine/Application/Templates/GameApplication.cpp', - 'src/ByteEngine/Debug/FunctionTimer.cpp', - 'src/ByteEngine/Game/ApplicationManager.cpp', - 'src/ByteEngine/Object.cpp', - 'src/ByteEngine/Render/RendererAllocator.cpp', - 'src/ByteEngine/Render/RenderSystem.cpp', - 'src/ByteEngine/Game/World.cpp', - 'src/ByteEngine/Light.cpp', - 'src/ByteEngine/Render/StaticMeshSystem.cpp', - 'src/ByteEngine/Render/UIManager.cpp', - 'src/ByteEngine/Resources/AnimationResourceManager.cpp', - 'src/ByteEngine/Resources/AudioResourceManager.cpp', - 'src/ByteEngine/Resources/FontResourceManager.cpp', - 'src/ByteEngine/Resources/PipelineCacheResourceManager.cpp', - 'src/ByteEngine/Resources/ResourceManager.cpp', - 'src/ByteEngine/Resources/StaticMeshResourceManager.cpp', - 'src/ByteEngine/Resources/TextureResourceManager.cpp', - 'src/ByteEngine/Sound/AudioSystem.cpp', - 'src/ByteEngine/Utility/Shapes/Cone.cpp', - 'src/ByteEngine/Utility/Shapes/ConeWithFalloff.cpp', - 'src/ByteEngine/Application/InputManager.cpp', - 'src/ByteEngine/Debug/Logger.cpp', - 'src/ByteEngine/Application/ScriptingSystem.cpp', - 'src/ByteEngine/Application/Clock.cpp', - 'src/ByteEngine/Application/Application.cpp', - 'src/ByteEngine/Resources/BC7.cpp', - 'src/ByteEngine/Render/WorldRenderPipeline.cpp', -] - -assimp = dependency('assimp', version: '>=5.0.0') -stb = dependency('stb') -gtsl = dependency('GTSL') -mono = dependency('mono-2') -monosgen = dependency('monosgen-2') -vulkan = dependency('vulkan') -shaderc = dependency('shaderc') -alsa = dependency('alsa') - -args = [ - '-mavx', - '-DBE_DEBUG=1', '-DBE_PLATFORM_WINDOWS=0', '-DBE_PLATFORM_LINUX=1', '-DBE_VULKAN=1', '-DBE_DX12=0', - '-Db_sanitize=address', -] - -ByteEngine = library('ByteEngine', src, dependencies: [assimp, stb, gtsl, mono, monosgen, vulkan, shaderc, alsa], include_directories: include_directories('src'), cpp_args: args) - -test_src = ['tests/TestApplication.cpp'] - -test = executable('TestByteEngine', test_src, link_with: [ByteEngine], include_directories: include_directories('src')) - -test('TestByteEngine', test) \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000..271800cb --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" \ No newline at end of file diff --git a/src/AAL/AudioCore.h b/src/AAL/AudioCore.h deleted file mode 100644 index ca45d325..00000000 --- a/src/AAL/AudioCore.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include - -#include "GTSL/Math/Math.hpp" - -namespace AAL -{ - /** - * \brief Names all possible audio channel counts. - */ - enum class AudioChannelCount : GTSL::uint8 - { - /** - * \brief Audio is mono, has only one channel. - */ - CHANNELS_MONO = 1, - - /** - * \brief Audio is stereo, has two channels. Typical for speakers or headphones. - */ - CHANNELS_STEREO = 2, - - /** - * \brief Audio is in 5.1, has five channels and one sub-woofer channel. Typical for home cinema setups. - */ - CHANNELS_5_1 = 5, - - /** - * \brief Audio is in 7.1, has seven channels and one sub-woofer channel. Typical for home cinema setups. - */ - CHANNELS_7_1 = 7 - }; - - /** - * \brief Names all possible audio bit depths. - */ - enum class AudioBitDepth : GTSL::uint8 - { - /** - * \brief Audio bit depth is 8 bit. - */ - BIT_DEPTH_8 = 8, - - /** - * \brief Audio bit depth is 16 bit. - */ - BIT_DEPTH_16 = 16, - - /** - * \brief Audio bit depth is 24 bit. - */ - BIT_DEPTH_24 = 24, - - BIT_DEPTH_32 = 32 - }; - - /** - * \brief Names all possible audio sample rates (kHz). - */ - enum class AudioSampleRate : GTSL::uint8 - { - /** - * \brief Audio sample rate is 44.100 Hz. - */ - KHZ_44_1 = 44, - - /** - * \brief Audio sample rate is 48.000 Hz. - */ - KHZ_48 = 48, - - /** - * \brief Audio sample rate is 96.000 Hz. - */ - KHZ_96 = 96 - }; - - /** - * \brief Names all possible audio output device types. - */ - enum class AudioOutputDeviceType : GTSL::uint8 - { - /** - * \brief Audio output device are speakers. - */ - SPEAKERS, - - /** - * \brief Audio output device are headphones. - */ - HEADPHONES - }; - - enum class StreamShareMode : GTSL::uint8 - { - SHARED, - EXCLUSIVE - }; - - inline float dBToVolume(const float db) { return GTSL::Math::Power(10.0f, 0.05f * db); } - - inline float VolumeTodB(const float volume) { return 20.0f * GTSL::Math::Log10(volume); } -} diff --git a/src/AAL/AudioDevice.h b/src/AAL/AudioDevice.h deleted file mode 100644 index 69ad685c..00000000 --- a/src/AAL/AudioDevice.h +++ /dev/null @@ -1,387 +0,0 @@ -#pragma once - -#include "AudioCore.h" - -#if BE_PLATFORM_WINDOWS -#elif BE_PLATFORM_LINUX -#include -#endif - -namespace AAL -{ - /** - * \brief Interface for an audio device. Creates and manages an audio device, endpoint and buffer. - */ - class AudioDevice - { - public: - AudioDevice() = default; - ~AudioDevice() = default; - - enum class BufferSamplePlacement : GTSL::uint8 { BLOCKS, INTERLEAVED }; - - struct MixFormat - { - GTSL::uint8 NumberOfChannels; - GTSL::uint32 SamplesPerSecond; - GTSL::uint8 BitsPerSample; - BufferSamplePlacement bufferSamplePlacement; - - GTSL::uint8 GetBytesPerSample() const { return BitsPerSample / 8; } - - /** - * \brief Frame size, in bytes. The frame size is the minimum atomic unit of data for the format. - * Frane size is equal to the product of NumberChannels and BitsPerSample divided by 8 (bytes per sample). - * Software must process a multiple of BlockAlignment bytes of data at a time. Data written to and read from a device must always start at the beginning of a block. - * For example, it is illegal to start playback of PCM data in the middle of a sample (that is, on a non-block-aligned boundary). - */ - GTSL::uint16 GetFrameSize() const { return static_cast(NumberOfChannels) * GetBytesPerSample(); } - }; - - struct CreateInfo - { - }; - - /** - * \brief Initializes the audio device to start receiving audio. Must be called before any other function. - */ - [[nodiscard]] bool Initialize(const CreateInfo&) { -#if BE_PLATFORM_WINDOWS - if(CoInitializeEx(nullptr, 0) != S_OK) { return false; } - - if(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), reinterpret_cast(&enumerator)) != S_OK) { return false; } - - if(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &endPoint) != S_OK) { return false; } - - if(endPoint->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, reinterpret_cast(&audioClient)) != S_OK) { return false; } - - return true; -#elif BE_PLATFORM_LINUX - if(snd_pcm_open(&device, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) { return false; } //Open default device for playback - if(snd_pcm_hw_params_malloc(&hwParams) < 0) { return false; } // Allocate the hardware parameters object. - if(snd_pcm_hw_params_any(device, hwParams) < 0) { return false; } // Initialize hwParams with full configuration space - return true; -#endif - } - - /** - * \brief Return the optimal mix format supported by the audio device. Must be called after initialize. - * \return MixFormat supported by the audio device. - */ - [[nodiscard]] GTSL::Result GetMixFormat() const { -#if BE_PLATFORM_WINDOWS - WAVEFORMATEXTENSIBLE* waveformatex; - - if(audioClient->GetMixFormat(reinterpret_cast(&waveformatex)) != S_OK) { - return GTSL::Result(false); - } - - MixFormat mixFormat; - - GTSL_ASSERT(waveformatex->Format.wFormatTag == WAVE_FORMAT_PCM, "Format mismatch!"); - - mixFormat.NumberOfChannels = static_cast(waveformatex->Format.nChannels); - mixFormat.SamplesPerSecond = waveformatex->Format.nSamplesPerSec; - mixFormat.BitsPerSample = static_cast(waveformatex->Format.wBitsPerSample != 24 ? waveformatex->Format.wBitsPerSample : 32); // Most devices using WASAPI prefer 24 bits padded to 32 bits per sample. - - CoTaskMemFree(waveformatex); - - return GTSL::Result(GTSL::MoveRef(mixFormat), true); -#elif BE_PLATFORM_LINUX - if(snd_pcm_hw_params(device, hwParams) < 0) { return GTSL::Result(false); } - int bits = snd_pcm_hw_params_get_sbits(hwParams); - if(bits < 0) { return GTSL::Result(false); } - uint32 sampleRate = 0; - snd_pcm_hw_params_get_rate(hwParams, &sampleRate, nullptr); - uint32 channels = 0; - snd_pcm_hw_params_get_channels(hwParams, &channels); - return GTSL::Result(MixFormat{ channels, sampleRate, bits }, true); -#endif - } - - BufferSamplePlacement GetBufferSamplePlacement() const { -#if BE_PLATFORM_WINDOWS - return BufferSamplePlacement::BLOCKS; -#elif BE_PLATFORM_LINUX - snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED; - if(snd_pcm_hw_params_get_access(hwParams, &access) < 0) { return BufferSamplePlacement::BLOCKS; } - - BufferSamplePlacement bufferSamplePlacement = BufferSamplePlacement::BLOCKS; - - switch (access) { - case SND_PCM_ACCESS_RW_INTERLEAVED: bufferSamplePlacement = BufferSamplePlacement::INTERLEAVED; break; - case SND_PCM_ACCESS_RW_NONINTERLEAVED: bufferSamplePlacement = BufferSamplePlacement::BLOCKS; break; - default: break; - } - - return bufferSamplePlacement; -#endif - } - - /** - * \brief Queries the audio device for support of the specified format with the specified share mode. - * \param shareMode Shared mode to query support for. - * \param mixFormat Mix format to check support for. - * \return Wheter the format is supported(true) or not(false). - */ - [[nodiscard]] bool IsMixFormatSupported(StreamShareMode shareMode, MixFormat mixFormat) const { -#if BE_PLATFORM_WINDOWS - WAVEFORMATEX waveformatex; WAVEFORMATEXTENSIBLE* closestMatch; - - waveformatex.wFormatTag = WAVE_FORMAT_PCM; - waveformatex.cbSize = 0; //extra data size if using WAVEFORMATEXTENSIBLE, this parameter is ignored since format is PCM but for correctness we set it to 0 - waveformatex.nBlockAlign = mixFormat.GetFrameSize(); - waveformatex.nChannels = mixFormat.NumberOfChannels; - waveformatex.nSamplesPerSec = mixFormat.SamplesPerSecond; - waveformatex.wBitsPerSample = mixFormat.BitsPerSample; - waveformatex.nAvgBytesPerSec = waveformatex.nSamplesPerSec * waveformatex.nBlockAlign; - - bool result = false; - - switch (shareMode) - { - case StreamShareMode::SHARED: - result = audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &waveformatex, reinterpret_cast(&closestMatch)) == S_OK; - CoTaskMemFree(closestMatch); - break; - - case StreamShareMode::EXCLUSIVE: - result = audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &waveformatex, nullptr) == S_OK; - break; - } - - return result; -#elif BE_PLATFORM_LINUX - return true; -#endif - } - - /** - * \brief Creates the audio stream with the requested parameters. The user must make sure the utilized parameter combination is supported by querying the suport function. - * \param shareMode Share mode to initialize the audio stream with. - * \param mixFormat Mix format to initialize the audio stream with. - */ - bool CreateAudioStream(StreamShareMode shareMode, MixFormat mixFormat) { -#if BE_PLATFORM_WINDOWS - WAVEFORMATEXTENSIBLE pwfx{}; - pwfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - pwfx.Format.cbSize = 22; - pwfx.Format.nChannels = 2; - pwfx.Format.nSamplesPerSec = mixFormat.SamplesPerSecond; - pwfx.Format.wBitsPerSample = pwfx.Samples.wValidBitsPerSample = mixFormat.BitsPerSample; - mixFormat.BitsPerSample = static_cast(mixFormat.BitsPerSample != 24 ? mixFormat.BitsPerSample : 32); // Most devices using WASAPI prefer 24 bits padded to 32 bits per sample. - pwfx.Format.nBlockAlign = mixFormat.GetFrameSize(); - pwfx.SubFormat = GUID{ STATIC_KSDATAFORMAT_SUBTYPE_PCM }; - pwfx.Format.nAvgBytesPerSec = mixFormat.SamplesPerSecond * pwfx.Format.nBlockAlign; - - frameSize = pwfx.Format.nBlockAlign; - - _AUDCLNT_SHAREMODE win_share_mode{}; - switch (shareMode) { - case StreamShareMode::EXCLUSIVE: win_share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE; break; - case StreamShareMode::SHARED: win_share_mode = AUDCLNT_SHAREMODE_SHARED; break; - } - - if(audioClient->Initialize(win_share_mode, 0, 0, 0, reinterpret_cast(&pwfx), nullptr) != S_OK) { - return false; - } - - if(audioClient->GetBufferSize(&bufferFrameCount) != S_OK) { - return false; - } - - if(audioClient->GetService(__uuidof(IAudioRenderClient), reinterpret_cast(&renderClient)) != S_OK) { - return false; - } - - return true; -#elif BE_PLATFORM_LINUX - // Disable resampling - if(snd_pcm_hw_params_set_rate_resample(device, hwParams, 0) < 0) { return false; } - - snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED; - - switch (mixFormat.bufferSamplePlacement) { - case BufferSamplePlacement::INTERLEAVED: access = SND_PCM_ACCESS_MMAP_INTERLEAVED; break; - case BufferSamplePlacement::BLOCKS: access = SND_PCM_ACCESS_MMAP_NONINTERLEAVED; break; - default: break; - } - - if(snd_pcm_hw_params_set_access(device, hwParams, access) < 0) { return false; } - - snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; - - switch (mixFormat.BitsPerSample) { - case 8: format = SND_PCM_FORMAT_U8; break; - case 16: format = SND_PCM_FORMAT_S16_LE; break; - case 24: format = SND_PCM_FORMAT_S24_LE; break; - case 32: format = SND_PCM_FORMAT_S32_LE; break; - } - - if(snd_pcm_hw_params_set_format(device, hwParams, format) < 0) { return false; } // Set sample format - - if(snd_pcm_hw_params_set_channels(device, hwParams, mixFormat.NumberOfChannels) < 0) { return false; } // Set the number of channels - - uint32 exactRate = mixFormat.SamplesPerSecond; - if(snd_pcm_hw_params_set_rate_near(device, hwParams, &exactRate, nullptr) < 0) { return false; } // Set the sample rate to the nearest supported rate. - - if(snd_pcm_hw_params(device, hwParams) < 0) { return false; } // Write the parameters to the driver - - return true; -#endif - } - - /** - * \brief Starts the audio stream. No samples can be pushed if the stream is not started. - */ - [[nodiscard]] bool Start() const { -#if BE_PLATFORM_WINDOWS - if(audioClient->Start() != S_OK) { - return false; - } - - return true; -#elif BE_PLATFORM_LINUX - snd_pcm_prepare(device); - return true; -#endif - } - - /** - * \brief Sets the passed variable as the available size in the allocated buffer. - * Should be called to query the available size before filling the audio buffer size it may have some space still occupied since the audio driver may not have consumed it. - * \param availableBufferFrames Pointer to a variable to set as the available buffer size. - */ - bool GetAvailableBufferFrames(GTSL::uint32& availableBufferFrames) const { -#if BE_PLATFORM_WINDOWS - UINT32 numFramesAvailable = 0; - //For a shared-mode rendering stream, the padding value reported by GetCurrentPadding specifies the number of audio frames - //that are queued up to play in the endpoint buffer. Before writing to the endpoint buffer, the client can calculate the - //amount of available space in the buffer by subtracting the padding value from the buffer length. - if(audioClient->GetCurrentPadding(&numFramesAvailable) != S_OK) { - return false; - } - - availableBufferFrames = bufferFrameCount - numFramesAvailable; - - return true; -#elif BE_PLATFORM_LINUX - return true; -#endif - } - - /** - * \brief Sets the passed variable as the size of the allocated buffer. - * \param totalBufferFrames Pointer to to variable for storing the size of the allocated buffer. - */ - void GetBufferFrameCount(GTSL::uint32& totalBufferFrames) const { -#if BE_PLATFORM_WINDOWS - audioClient->GetBufferSize(&totalBufferFrames); -#elif BE_PLATFORM_LINUX - snd_pcm_uframes_t frames; - snd_pcm_hw_params_get_buffer_size(hwParams, &frames); - totalBufferFrames = static_cast(frames); -#endif - } - - /** - * \brief Invokes a function to push audio data for the amount of specified samples to the audio device buffer, making such data available for the next request from the driver to retrieve audio data. - * \param copyFunction Callable object taking a uint32 specifying the size in bytes to copy, and a void* to copy the data to. - * \param pushedSamples Number of audio frames to copy to the audio buffer. - */ - template - bool PushAudioData(F&& copyFunction, GTSL::uint32 pushedSamples) const - { -#if BE_PLATFORM_WINDOWS - auto getResult = getBuffer(pushedSamples); - if(!getResult) { return false; } - copyFunction(pushedSamples * frameSize, getResult.Get()); - auto releaseResult = releaseBuffer(pushedSamples); - if (!releaseResult) { return false; } - return true; -#elif BE_PLATFORM_LINUX - return true; -#endif - } - - /** - * \brief Stops the audio stream. No samples can be pushed if the stream is not started. Must be called before destroying the audio device, no other functions shall be called after this. - */ - [[nodiscard]] bool Stop() const { -#if BE_PLATFORM_WINDOWS - if(audioClient->Stop() != S_OK) { - return false; - } - - return true; -#elif BE_PLATFORM_LINUX - return true; -#endif - } - - /** - * \brief Destroys the audio stream. Must be called before destroying the audio device, no other functions shall be called after this. - */ - void Destroy() { -#if BE_PLATFORM_WINDOWS - renderClient->Release(); - audioClient->Release(); - endPoint->Release(); - enumerator->Release(); - - CoUninitialize(); -#elif BE_PLATFORM_LINUX - snd_pcm_hw_params_free(hwParams); - snd_pcm_close(device); -#endif - } - - static constexpr GTSL::uint8 LEFT_CHANNEL = 0, RIGHT_CHANNEL = 1; - - private: -#if BE_PLATFORM_WINDOWS - /** - * \brief The IMMDeviceEnumerator interface provides methods for enumerating multimedia device resources. - * In the current implementation of the MMDevice API, the only device resources that this interface can enumerate are audio endpoint devices. - * A client obtains a reference to an IMMDeviceEnumerator interface by calling the CoCreateInstance function, as described previously (see MMDevice API). - */ - IMMDeviceEnumerator* enumerator = nullptr; - - /** - * \brief The IMMDevice interface encapsulates the generic features of a multimedia device resource. - * In the current implementation of the MMDevice API, the only type of device resource that an IMMDevice interface can represent is an audio endpoint device. - */ - IMMDevice* endPoint = nullptr; - - /** - * \brief The IAudioClient interface enables a client to create and initialize an audio stream between an audio application and the audio engine - * (for a shared-mode stream) or the hardware buffer of an audio endpoint device (for an exclusive-mode stream). - */ - IAudioClient* audioClient = nullptr; - - /** - * \brief The IAudioRenderClient interface enables a client to write output data to a rendering endpoint buffer. - * The client obtains a reference to the IAudioRenderClient interface of a stream object by calling the IAudioClient::GetService method - * with parameter riid set to REFIID IID_IAudioRenderClient. - */ - IAudioRenderClient* renderClient = nullptr; - - GTSL::uint32 frameSize = 0; - - GTSL::uint32 bufferFrameCount = 0; - - [[nodiscard]] GTSL::Result getBuffer(GTSL::uint32 pushedSamples) const { - BYTE* bufferAddress = nullptr; - auto result = renderClient->GetBuffer(pushedSamples, &bufferAddress); - return GTSL::Result(GTSL::MoveRef(static_cast(bufferAddress)), result == S_OK); - } - - [[nodiscard]] bool releaseBuffer(GTSL::uint32 pushedSamples) const { - return renderClient->ReleaseBuffer(pushedSamples, 0) == S_OK; - } -#elif BE_PLATFORM_LINUX - snd_pcm_t* device = nullptr; - snd_pcm_hw_params_t* hwParams = nullptr; -#endif - }; -} \ No newline at end of file diff --git a/src/AAL/Platform/Windows/WindowsAudioDevice.h b/src/AAL/Platform/Windows/WindowsAudioDevice.h deleted file mode 100644 index fb60839f..00000000 --- a/src/AAL/Platform/Windows/WindowsAudioDevice.h +++ /dev/null @@ -1,265 +0,0 @@ -#pragma once - -#include "AAL/AudioDevice.h" - -#if BE_PLATFORM_WINDOWS -#include -#include - -#include "GTSL/Assert.h" -#include "GTSL/Result.h" - -namespace AAL -{ - class WindowsAudioDevice final : public AudioDevice - { - public: - WindowsAudioDevice() = default; - ~WindowsAudioDevice() = default; - - /** - * \brief Initializes the audio device to start receiving audio. Must be called before any other function. - */ - [[nodiscard]] bool Initialize(const CreateInfo&) { - if(CoInitializeEx(nullptr, 0) != S_OK) { - return false; - } - - if(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), reinterpret_cast(&enumerator)) != S_OK) { - return false; - } - - if(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &endPoint) != S_OK) { - return false; - } - - if(endPoint->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, reinterpret_cast(&audioClient)) != S_OK) { - return false; - } - - return true; - } - - /** - * \brief Return the optimal mix format supported by the audio device. Must be called after initialize. - * \return MixFormat supported by the audio device. - */ - [[nodiscard]] GTSL::Result GetMixFormat() const { - WAVEFORMATEXTENSIBLE* waveformatex; - - if(audioClient->GetMixFormat(reinterpret_cast(&waveformatex)) != S_OK) { - return GTSL::Result(false); - } - - MixFormat mixFormat; - - GTSL_ASSERT(waveformatex->Format.wFormatTag == WAVE_FORMAT_PCM, "Format mismatch!"); - - mixFormat.NumberOfChannels = static_cast(waveformatex->Format.nChannels); - mixFormat.SamplesPerSecond = waveformatex->Format.nSamplesPerSec; - mixFormat.BitsPerSample = static_cast(waveformatex->Format.wBitsPerSample != 24 ? waveformatex->Format.wBitsPerSample : 32); // Most devices using WASAPI prefer 24 bits padded to 32 bits per sample. - - CoTaskMemFree(waveformatex); - - return GTSL::Result(GTSL::MoveRef(mixFormat), true); - } - - BufferSamplePlacement GetBufferSamplePlacement() const { return BufferSamplePlacement::BLOCKS; } - - /** - * \brief Queries the audio device for support of the specified format with the specified share mode. - * \param shareMode Shared mode to query support for. - * \param mixFormat Mix format to check support for. - * \return Wheter the format is supported(true) or not(false). - */ - [[nodiscard]] bool IsMixFormatSupported(StreamShareMode shareMode, MixFormat mixFormat) const { - WAVEFORMATEX waveformatex; WAVEFORMATEXTENSIBLE* closestMatch; - - waveformatex.wFormatTag = WAVE_FORMAT_PCM; - waveformatex.cbSize = 0; //extra data size if using WAVEFORMATEXTENSIBLE, this parameter is ignored since format is PCM but for correctness we set it to 0 - waveformatex.nBlockAlign = mixFormat.GetFrameSize(); - waveformatex.nChannels = mixFormat.NumberOfChannels; - waveformatex.nSamplesPerSec = mixFormat.SamplesPerSecond; - waveformatex.wBitsPerSample = mixFormat.BitsPerSample; - waveformatex.nAvgBytesPerSec = waveformatex.nSamplesPerSec * waveformatex.nBlockAlign; - - bool result = false; - - switch (shareMode) - { - case StreamShareMode::SHARED: - result = audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &waveformatex, reinterpret_cast(&closestMatch)) == S_OK; - CoTaskMemFree(closestMatch); - break; - - case StreamShareMode::EXCLUSIVE: - result = audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &waveformatex, nullptr) == S_OK; - break; - } - - return result; - } - - /** - * \brief Creates the audio stream with the requested parameters. The user must make sure the utilized parameter combination is supported by querying the suport function. - * \param shareMode Share mode to initialize the audio stream with. - * \param mixFormat Mix format to initialize the audio stream with. - */ - bool CreateAudioStream(StreamShareMode shareMode, MixFormat mixFormat) { - WAVEFORMATEXTENSIBLE pwfx{}; - pwfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - pwfx.Format.cbSize = 22; - pwfx.Format.nChannels = 2; - pwfx.Format.nSamplesPerSec = mixFormat.SamplesPerSecond; - pwfx.Format.wBitsPerSample = pwfx.Samples.wValidBitsPerSample = mixFormat.BitsPerSample; - mixFormat.BitsPerSample = static_cast(mixFormat.BitsPerSample != 24 ? mixFormat.BitsPerSample : 32); // Most devices using WASAPI prefer 24 bits padded to 32 bits per sample. - pwfx.Format.nBlockAlign = mixFormat.GetFrameSize(); - pwfx.SubFormat = GUID{ STATIC_KSDATAFORMAT_SUBTYPE_PCM }; - pwfx.Format.nAvgBytesPerSec = mixFormat.SamplesPerSecond * pwfx.Format.nBlockAlign; - - frameSize = pwfx.Format.nBlockAlign; - - _AUDCLNT_SHAREMODE win_share_mode{}; - switch (shareMode) { - case StreamShareMode::EXCLUSIVE: win_share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE; break; - case StreamShareMode::SHARED: win_share_mode = AUDCLNT_SHAREMODE_SHARED; break; - } - - if(audioClient->Initialize(win_share_mode, 0, 0, 0, reinterpret_cast(&pwfx), nullptr) != S_OK) { - return false; - } - - if(audioClient->GetBufferSize(&bufferFrameCount) != S_OK) { - return false; - } - - if(audioClient->GetService(__uuidof(IAudioRenderClient), reinterpret_cast(&renderClient)) != S_OK) { - return false; - } - - return true; - } - - /** - * \brief Starts the audio stream. No samples can be pushed if the stream is not started. - */ - [[nodiscard]] bool Start() const { - if(audioClient->Start() != S_OK) { - return false; - } - - return true; - } - - - /** - * \brief Sets the passed variable as the available size in the allocated buffer. - * Should be called to query the available size before filling the audio buffer size it may have some space still occupied since the audio driver may not have consumed it. - * \param availableBufferFrames Pointer to a variable to set as the available buffer size. - */ - bool GetAvailableBufferFrames(GTSL::uint32& availableBufferFrames) const { - UINT32 numFramesAvailable = 0; - //For a shared-mode rendering stream, the padding value reported by GetCurrentPadding specifies the number of audio frames - //that are queued up to play in the endpoint buffer. Before writing to the endpoint buffer, the client can calculate the - //amount of available space in the buffer by subtracting the padding value from the buffer length. - if(audioClient->GetCurrentPadding(&numFramesAvailable) != S_OK) { - return false; - } - - availableBufferFrames = bufferFrameCount - numFramesAvailable; - - return true; - } - - /** - * \brief Sets the passed variable as the size of the allocated buffer. - * \param totalBufferFrames Pointer to to variable for storing the size of the allocated buffer. - */ - void GetBufferFrameCount(GTSL::uint32& totalBufferFrames) const { - audioClient->GetBufferSize(&totalBufferFrames); - } - - /** - * \brief Invokes a function to push audio data for the amount of specified samples to the audio device buffer, making such data available for the next request from the driver to retrieve audio data. - * \param copyFunction Callable object taking a uint32 specifying the size in bytes to copy, and a void* to copy the data to. - * \param pushedSamples Number of audio frames to copy to the audio buffer. - */ - template - bool PushAudioData(F&& copyFunction, GTSL::uint32 pushedSamples) const - { - auto getResult = getBuffer(pushedSamples); - if(!getResult) { return false; } - copyFunction(pushedSamples * frameSize, getResult.Get()); - auto releaseResult = releaseBuffer(pushedSamples); - if (!releaseResult) { return false; } - return true; - } - - /** - * \brief Stops the audio stream. No samples can be pushed if the stream is not started. Must be called before destroying the audio device, no other functions shall be called after this. - */ - [[nodiscard]] bool Stop() const { - if(audioClient->Stop() != S_OK) { - return false; - } - - return true; - } - - /** - * \brief Destroys all remaining audio device resources. - */ - void Destroy() { - renderClient->Release(); - audioClient->Release(); - endPoint->Release(); - enumerator->Release(); - - CoUninitialize(); - } - - static constexpr GTSL::uint8 LEFT_CHANNEL = 0, RIGHT_CHANNEL = 1; - - private: - /** - * \brief The IMMDeviceEnumerator interface provides methods for enumerating multimedia device resources. - * In the current implementation of the MMDevice API, the only device resources that this interface can enumerate are audio endpoint devices. - * A client obtains a reference to an IMMDeviceEnumerator interface by calling the CoCreateInstance function, as described previously (see MMDevice API). - */ - IMMDeviceEnumerator* enumerator = nullptr; - - /** - * \brief The IMMDevice interface encapsulates the generic features of a multimedia device resource. - * In the current implementation of the MMDevice API, the only type of device resource that an IMMDevice interface can represent is an audio endpoint device. - */ - IMMDevice* endPoint = nullptr; - - /** - * \brief The IAudioClient interface enables a client to create and initialize an audio stream between an audio application and the audio engine - * (for a shared-mode stream) or the hardware buffer of an audio endpoint device (for an exclusive-mode stream). - */ - IAudioClient* audioClient = nullptr; - - /** - * \brief The IAudioRenderClient interface enables a client to write output data to a rendering endpoint buffer. - * The client obtains a reference to the IAudioRenderClient interface of a stream object by calling the IAudioClient::GetService method - * with parameter riid set to REFIID IID_IAudioRenderClient. - */ - IAudioRenderClient* renderClient = nullptr; - - GTSL::uint32 frameSize = 0; - - GTSL::uint32 bufferFrameCount = 0; - - [[nodiscard]] GTSL::Result getBuffer(GTSL::uint32 pushedSamples) const { - BYTE* bufferAddress = nullptr; - auto result = renderClient->GetBuffer(pushedSamples, &bufferAddress); - return GTSL::Result(GTSL::MoveRef(static_cast(bufferAddress)), result == S_OK); - } - - [[nodiscard]] bool releaseBuffer(GTSL::uint32 pushedSamples) const { - return renderClient->ReleaseBuffer(pushedSamples, 0) == S_OK; - } - }; -} -#endif \ No newline at end of file diff --git a/src/ByteEngine.h b/src/ByteEngine.h deleted file mode 100644 index 46b57f1b..00000000 --- a/src/ByteEngine.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -//FOR USE BY GAME STUDIO APPLICATIONS - -//EntryPoint -#include "ByteEngine/Application/EntryPoint.h" diff --git a/src/ByteEngine/Animation/AnimationSystem.h b/src/ByteEngine/Animation/AnimationSystem.h deleted file mode 100644 index 0e1cda3c..00000000 --- a/src/ByteEngine/Animation/AnimationSystem.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include - -#include "ByteEngine/Game/System.hpp" -#include "ByteEngine/Handle.hpp" - -MAKE_HANDLE(uint32, Skeleton) - -class AnimationSystem : public System -{ -public: - void Initialize(const InitializeInfo& initializeInfo) override; - void Shutdown(const ShutdownInfo& shutdownInfo) override; - - SkeletonHandle CreateSkeleton() - { - auto skeletonIndex = skeletons.EmplaceBack(); - - return SkeletonHandle(skeletonIndex); - } - - void PlayAnimation(const SkeletonHandle skeletonHandle, Id animationName) - { - GTSL::Microseconds elapsedTime, deltaTime; - uint32 animationFrames, animationFPS; - GTSL::Microseconds frameLength(GTSL::Seconds(1)); frameLength /= GTSL::Microseconds(60); - - GTSL::Vector3 time[64]; - - elapsedTime += deltaTime; - - uint64 currentFrame = (elapsedTime / frameLength).GetCount(); - - if(currentFrame > animationFrames) { - elapsedTime -= GTSL::Microseconds(animationFrames) * frameLength; - currentFrame = (elapsedTime / frameLength).GetCount(); - } - - uint64 nextFrame = currentFrame % animationFrames; - float32 progressBetweenFrames = 0; - - auto newPos = GTSL::Math::Lerp(time[currentFrame], time[nextFrame], progressBetweenFrames); - } - -private: - GTSL::StaticVector skeletonsNames; - GTSL::StaticVector skeletons; - - GTSL::StaticVector animations; -}; diff --git a/src/ByteEngine/Animation/Skeletal Mesh.h b/src/ByteEngine/Animation/Skeletal Mesh.h deleted file mode 100644 index afbce340..00000000 --- a/src/ByteEngine/Animation/Skeletal Mesh.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - - -#include "ByteEngine/Application/AllocatorReferences.h" - -struct SkinnableVertex -{ - GTSL::Vector3 Position; - GTSL::Vector3 Normal; - uint16 BoneIDs[8]; - GTSL::Vector2 TextureCoordinates; -}; - -struct Joint -{ - GTSL::Id64 Name; - uint16 Parent; - GTSL::Matrix4 Offset; -}; - -class Skeleton -{ - GTSL::HashMap bones; - -public: -}; diff --git a/src/ByteEngine/Application/AllocatorReferences.cpp b/src/ByteEngine/Application/AllocatorReferences.cpp deleted file mode 100644 index bc9d2a0f..00000000 --- a/src/ByteEngine/Application/AllocatorReferences.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "AllocatorReferences.h" - -#include "Application.h" - -void BE::SystemAllocatorReference::Allocate(const uint64 size, const uint64 alignment, void** memory, uint64* allocatedSize) const { - (*allocatedSize) = size; - BE::Application::Get()->GetSystemAllocator()->Allocate(size, alignment, memory); -} - -void BE::SystemAllocatorReference::Deallocate(const uint64 size, const uint64 alignment, void* memory) const { - BE::Application::Get()->GetSystemAllocator()->Deallocate(size, alignment, memory); -} - -void BE::TransientAllocatorReference::Allocate(const uint64 size, const uint64 alignment, void** memory, uint64* allocatedSize) const { BE::Application::Get()->GetTransientAllocator()->Allocate(size, alignment, memory, allocatedSize, Name); } - -void BE::TransientAllocatorReference::Deallocate(const uint64 size, const uint64 alignment, void* memory) const { BE::Application::Get()->GetTransientAllocator()->Deallocate(size, alignment, memory, Name); } - -void BE::PersistentAllocatorReference::Allocate(const uint64 size, const uint64 alignment, void** memory, uint64* allocatedSize) const { Application::Get()->GetPersistantAllocator()->Allocate(size, alignment, memory, allocatedSize, Name); } - -void BE::PersistentAllocatorReference::Deallocate(const uint64 size, const uint64 alignment, void* memory) const { Application::Get()->GetPersistantAllocator()->Deallocate(size, alignment, memory, Name); } \ No newline at end of file diff --git a/src/ByteEngine/Application/AllocatorReferences.h b/src/ByteEngine/Application/AllocatorReferences.h deleted file mode 100644 index 4beb2222..00000000 --- a/src/ByteEngine/Application/AllocatorReferences.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" -#include -#include - -namespace BE -{ - class Application; - - struct BEAllocatorReference : GTSL::AllocatorReference - { - GTSL::ShortString<16> Name = u8"-"; - bool IsDebugAllocation = false; - - BEAllocatorReference() = default; - BEAllocatorReference(const BEAllocatorReference& allocatorReference) = default; - BEAllocatorReference(BEAllocatorReference&& allocatorReference) = default; - - BEAllocatorReference& operator=(const BEAllocatorReference& other) - { - Name = other.Name; IsDebugAllocation = other.IsDebugAllocation; return *this; - } - - explicit BEAllocatorReference(const GTSL::ShortString<16>& name, const bool isDebugAllocation = false) : Name(name), IsDebugAllocation(isDebugAllocation) {} - explicit BEAllocatorReference(const utf8* name, const bool isDebugAllocation = false) : Name(name), IsDebugAllocation(isDebugAllocation) {} - }; - - struct SystemAllocatorReference : BEAllocatorReference - { - void Allocate(uint64 size, uint64 alignment, void** memory, uint64* allocatedSize) const; - - void Deallocate(uint64 size, uint64 alignment, void* memory) const; - - SystemAllocatorReference() = default; - - SystemAllocatorReference(const utf8* name, const bool isDebugAllocation = false) : BEAllocatorReference(name, isDebugAllocation) - { - } - }; - - struct TransientAllocatorReference : BEAllocatorReference - { - void Allocate(uint64 size, uint64 alignment, void** memory, uint64* allocatedSize) const; - - void Deallocate(uint64 size, uint64 alignment, void* memory) const; - - TransientAllocatorReference() = delete; - - TransientAllocatorReference(const TransientAllocatorReference& reference) : BEAllocatorReference(reference.Name, reference.IsDebugAllocation) {} - TransientAllocatorReference(TransientAllocatorReference&& reference) = default; - - TransientAllocatorReference& operator=(const TransientAllocatorReference& allocatorReference) = default; - - TransientAllocatorReference(const GTSL::Range name, const bool isDebugAllocation = false) : BEAllocatorReference(name, isDebugAllocation) - { - } - }; - - struct PersistentAllocatorReference : BEAllocatorReference - { - void Allocate(uint64 size, uint64 alignment, void** memory, uint64* allocatedSize) const; - - void Deallocate(uint64 size, uint64 alignment, void* memory) const; - - PersistentAllocatorReference() = delete; - - PersistentAllocatorReference(const PersistentAllocatorReference& allocatorReference) : BEAllocatorReference(allocatorReference.Name, allocatorReference.IsDebugAllocation) - { - } - - PersistentAllocatorReference& operator=(const PersistentAllocatorReference&) = default; - - PersistentAllocatorReference(PersistentAllocatorReference&& persistentAllocatorReference) = default; - - explicit PersistentAllocatorReference(const GTSL::Range name, const bool isDebugAllocation = false) : BEAllocatorReference(name, isDebugAllocation) - { - } - }; - - using TAR = TransientAllocatorReference; - using PAR = PersistentAllocatorReference; -} diff --git a/src/ByteEngine/Application/Application.cpp b/src/ByteEngine/Application/Application.cpp deleted file mode 100644 index cb1619fa..00000000 --- a/src/ByteEngine/Application/Application.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include "ByteEngine/Application/Application.h" - -#include "ByteEngine/Application/InputManager.h" -#include "ByteEngine/Application/ThreadPool.h" -#include "ByteEngine/Application/Clock.h" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Debug/Logger.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -#if (_DEBUG) -void onAssert(const bool condition, const char* text, int line, const char* file, const char* function) -{ - //BE_BASIC_LOG_ERROR("GTSL ASSERT: ", text, ' ', "Line: ", line, ' ', "File: ", file, ' ', "Function: ", function); -} -#endif - -uint32 ShitTracker::shitCount = 0; - -namespace BE -{ - Application::Application(GTSL::StringView applicationName) : Object(applicationName) { - applicationInstance = this; - } - - Application::~Application() {} - - bool Application::base_initialize(GTSL::Range arguments) { - if (!checkPlatformSupport() ) { - Close(CloseMode::ERROR, GTSL::StaticString<128>(u8"No platform support.")); - return false; - } - - GTSL::Thread::SetThreadId(0); - - poolAllocator.initialize(); - stackAllocator.initialize(BE::SystemAllocatorReference(u8"StackAllocator", false)); - - //systemApplication.SetProcessPriority(GTSL::Application::Priority::HIGH); - - Logger::LoggerCreateInfo logger_create_info; - auto path = GetPathToApplication(); - logger_create_info.AbsolutePathToLogDirectory = path; - logger = GTSL::SmartPointer(BE::SystemAllocatorReference(u8"Logger", true), logger_create_info); - - if (!parseConfig()) { // TODO. create config file if it doesn't exist. - return false; - } - - //logger->SetTrace(GetBoolOption(u8"trace")); - - // inputManagerInstance = GTSL::SmartPointer(systemAllocatorReference); - -#if BE_PLATFORM_WINDOWS - // Set the process DPI awareness so windows' extents match the set resolution and are not scaled by Windows to match size based on DPI. - // We are basically saying that we are aware of DPI and we are handling the scaling ourselves. - SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); -#endif - - { - auto threadCount = 1u; - //auto threadCount = (uint32)GetUINTOption(u8"threadCount"); - threadCount = GTSL::Math::Limit(threadCount, static_cast(GTSL::Thread::ThreadCount() - 1/*main thread*/)); - threadCount = threadCount ? static_cast(threadCount) : GTSL::Thread::ThreadCount(); - threadPool = GTSL::SmartPointer(BE::SystemAllocatorReference(u8"ThreadPool"), threadCount); - } - - initialized = true; - - BE_LOG_SUCCESS(u8"Succesfully initialized Byte Engine module!"); - - if (arguments.ElementCount() > 0) { - GTSL::StaticString<2048> string(u8"Application started with parameters:\n\t"); - - string += GTSL::Join{ arguments, u8" " }; - - BE_LOG_MESSAGE(string); - } else { - BE_LOG_MESSAGE(u8"Application started with no parameters."); - } - - return true; - } - - bool Application::initialize() { - applicationManager = GTSL::SmartPointer(BE::SystemAllocatorReference(u8"ApplicationManager")); - - return true; - } - - void Application::shutdown() { - if(logger) { // If logger instance was successfully initialized report shutting down reason - if (closeMode != CloseMode::OK) { - if (closeMode == CloseMode::WARNING) { - BE_LOG_WARNING(u8"Shutting down application!\nReason: ", closeReason) - } - - BE_LOG_ERROR(u8"Shutting down application!\nReason: ", closeReason) - } - else { - BE_LOG_SUCCESS(u8"Shutting down application. No reported errors.") - } - } - - if (initialized) { - //must free manually or else these smart pointers get freed on destruction, which is after the allocators (which this classes depend on) are destroyed. - - applicationManager.TryFree(); - threadPool.TryFree(); - //inputManagerInstance.TryFree(); - logger.TryFree(); - stackAllocator.clear(); - poolAllocator.free(); - } - } - - //uint8 Application::GetNumberOfThreads() { return threadPool->GetNumberOfThreads() + 1/*main thread*/; } - uint8 Application::GetNumberOfThreads() { return 1/*main thread*/; } - - void Application::OnUpdate(const OnUpdateInfo& updateInfo) { - // inputManagerInstance->Update(); - // applicationManager->OnUpdate(this); - } - - void Application::run() { - //applicationManager->AddEvent(u8"Application", EventHandle(u8"OnPromptClose")); - - while (!flaggedForClose) { - //clockInstance.OnUpdate(); - - OnUpdateInfo update_info{}; - OnUpdate(update_info); - - //transientAllocator.LockedClear(); - - ++applicationTicks; - } - } - - void Application::PromptClose() { - //applicationManager->DispatchEvent(this, EventHandle(u8"OnPromptClose")); - } - - void Application::Close(const CloseMode closeMode, const GTSL::Range reason) - { - closeReason += reason; - flaggedForClose = true; - this->closeMode = closeMode; - } - - GTSL::StaticString<260> Application::GetPathToApplication() const { -#ifdef _WIN32 - char s[260]; - GetModuleFileNameA(GetModuleHandleA(nullptr), s, 260); - - GTSL::StaticString<260> ret(reinterpret_cast(s)); - ReplaceAll(ret, u8'\\', u8'/'); - RTrimLast(ret, u8'/'); - return ret; -#else - auto path = GTSL::Application::GetPathToExecutable(); - RTrimLast(path, u8'/'); - return path; -#endif - } - - bool Application::parseConfig() { - auto path = GetPathToApplication(); - path += u8"/settings.json"; - - GTSL::File settingsFile; - switch (settingsFile.Open(path, GTSL::File::READ, false)) { - case GTSL::File::OpenResult::ERROR: Close(CloseMode::ERROR, GTSL::StaticString<64>(u8"Config file not found.")); return false; - } - - //don't try parsing if file is empty - if(settingsFile.GetSize() == 0) { - Close(CloseMode::ERROR, GTSL::StaticString<64>(u8"Config file is empty.")); - return false; - } - - GTSL::Buffer fileBuffer(settingsFile, Object::GetTransientAllocator()); - - JSON = GTSL::MoveRef(GTSL::JSON(GTSL::StringView(fileBuffer), GTSL::DefaultAllocatorReference{})); - - return true; - } - - bool Application::checkPlatformSupport() { - GTSL::SystemInfo systemInfo = GTSL::System::GetSystemInfo(); - - bool avx2 = systemInfo.CPU.VectorInfo.HW_AVX2; - bool totalMemory = systemInfo.RAM.TotalPhysicalMemory.GetCount() >= GTSL::Byte(GTSL::GigaByte(12)).GetCount(); - //bool availableMemory = systemInfo.RAM.ProcessAvailableMemory >= GTSL::Byte(GTSL::GigaByte(2)); - bool availableMemory = true; - - return avx2 && totalMemory && availableMemory; - } -} diff --git a/src/ByteEngine/Application/Application.h b/src/ByteEngine/Application/Application.h deleted file mode 100644 index 507ef9cc..00000000 --- a/src/ByteEngine/Application/Application.h +++ /dev/null @@ -1,185 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -#include -#include -#include -#include - -#include "Clock.h" -#include "PoolAllocator.h" -#include "StackAllocator.h" -#include "SystemAllocator.h" -#include "ByteEngine/Id.h" -#include "ByteEngine/Resources/ResourceManager.h" -#include "GTSL/SmartPointer.hpp" - -class ApplicationManager; -class InputManager; -class ThreadPool; -class Clock; - -#undef ERROR - -#include - -class ShitTracker { -public: - ShitTracker() { - void* data = nullptr; - GTSL::Allocate(8ull, &data); - ++shitCount; - } - - ~ShitTracker() { - --shitCount; - } - - static uint32 shitCount; -}; - -namespace BE -{ - class Logger; - - class Application : public Object { - public: - explicit Application(GTSL::StringView applicationName); - Application(const Application&) = delete; // Explicitly delete copy constructor because we have a static pointer to this object. - Application(Application&&) = delete; // Explicitly delete move constructor because we have a static pointer to this object. - virtual ~Application(); - - [[nodiscard]] static const char* GetEngineName() { return "Byte Engine"; } - static const char* GetEngineVersion() { return "0.0.1"; } - - static Application* Get() { return applicationInstance; } - - bool base_initialize(GTSL::Range arguments); - - virtual bool initialize() = 0; - - void run(); - - enum class UpdateContext : uint8 { - NORMAL, BACKGROUND - }; - - struct OnUpdateInfo {}; - virtual void OnUpdate(const OnUpdateInfo& updateInfo); - - virtual void shutdown() = 0; - - uint8 GetNumberOfThreads(); - - virtual GTSL::ShortString<128> GetApplicationName() = 0; - - //Fires a Delegate to signal that the application has been requested to close. - void PromptClose(); - - enum class CloseMode : uint8 { - OK, WARNING, ERROR - }; - //Flags the application to close on the next update. - void Close(CloseMode closeMode, GTSL::Range reason); - - //Immediately closes the application and logs the reason - void Exit(const GTSL::Range reason) { - // GTSL::Lock lock(crashLogMutex); - - if(!crashLog) { - auto crashLogFileOpenResult = crashLog.Open(GTSL::ShortString<32>(u8"crash.log"), GTSL::File::WRITE, true); - } - - GTSL::Buffer> buffer; - GTSL::Insert(reason, buffer); - crashLog.Write(buffer); - - //todo: open dialog box? - } - - [[nodiscard]] GTSL::StaticString<260> GetPathToApplication() const; - - //[[nodiscard]] const Clock* GetClock() const { return &clockInstance; } - [[nodiscard]] const Clock* GetClock() const { return nullptr; } - //[[nodiscard]] InputManager* GetInputManager() const { return inputManagerInstance.GetData(); } - [[nodiscard]] InputManager* GetInputManager() const { return nullptr; } - [[nodiscard]] Logger* GetLogger() const { return logger; } - // [[nodiscard]] const GTSL::Application* GetSystemApplication() const { return &systemApplication; } - [[nodiscard]] const GTSL::Application* GetSystemApplication() const { return nullptr; } - [[nodiscard]] class ApplicationManager* GetGameInstance() const { return applicationManager; } - [[nodiscard]] class ApplicationManager* get_orchestrator() const { return applicationManager; } - - [[nodiscard]] uint64 GetApplicationTicks() const { return applicationTicks; } - - [[nodiscard]] ThreadPool* GetThreadPool() const { return threadPool; } - - [[nodiscard]] SystemAllocator* GetSystemAllocator() { return &systemAllocator; } - [[nodiscard]] PoolAllocator* GetPersistantAllocator() { return &poolAllocator; } - [[nodiscard]] StackAllocator* GetTransientAllocator() { return &stackAllocator; } - - bool GetBoolOption(const GTSL::StringView optionName) const { - return JSON[optionName].GetBool(); - } - - uint64 GetUINTOption(const GTSL::StringView optionName) const { - return JSON[optionName].GetUint(); - } - - GTSL::StringView GetStringOption(const GTSL::StringView optionName) const { - return JSON[optionName].GetStringView(); - } - - GTSL::Extent2D GetExtent2DOption(const GTSL::StringView optionName) const { - return { static_cast(JSON[optionName][0].GetUint()), static_cast(JSON[optionName][1].GetUint()) }; - } - - const auto& GetConfig() const { - return JSON; - } - - protected: - inline static Application* applicationInstance{ nullptr }; - - SystemAllocator systemAllocator; - - // GTSL::Application systemApplication; - - Clock clockInstance; - - GTSL::File crashLog; - - GTSL::SmartPointer logger; - - GTSL::SmartPointer applicationManager; - //ApplicationManager* applicationManager = nullptr; - - InputManager* inputManagerInstance = nullptr; - - PoolAllocator poolAllocator; - StackAllocator stackAllocator; - - bool initialized = false; - - GTSL::SmartPointer threadPool; - - bool flaggedForClose = false; - CloseMode closeMode{ CloseMode::OK }; - GTSL::StaticString<1024> closeReason; - - uint64 applicationTicks{ 0 }; - - GTSL::JSON JSON; - - bool parseConfig(); - /** - * \brief Checks if the platform (OS, CPU, RAM) satisfies certain requirements specified for the program. - * \return Whether the current platform supports the required features. - */ - bool checkPlatformSupport(); - private: - }; - - Application* CreateApplication(GTSL::AllocatorReference* allocatorReference); - void DestroyApplication(Application* application, GTSL::AllocatorReference* allocatorReference); -} \ No newline at end of file diff --git a/src/ByteEngine/Application/Clock.cpp b/src/ByteEngine/Application/Clock.cpp deleted file mode 100644 index d63ebaf3..00000000 --- a/src/ByteEngine/Application/Clock.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "Clock.h" - -#if BE_PLATFORM_WINDOWS -#include -#endif - -#include - -Clock::Clock() -{ -#if BE_PLATFORM_WINDOWS - LARGE_INTEGER WinProcessorFrequency; - LARGE_INTEGER WinProcessorTicks; - - QueryPerformanceFrequency(&WinProcessorFrequency); - QueryPerformanceCounter(&WinProcessorTicks); - - processorFrequency = WinProcessorFrequency.QuadPart; - startPerformanceCounterTicks = WinProcessorTicks.QuadPart; - performanceCounterTicks = WinProcessorTicks.QuadPart; -#endif -} - -Clock::~Clock() = default; - -void Clock::OnUpdate() { -#if BE_PLATFORM_WINDOWS - LARGE_INTEGER current_ticks; - QueryPerformanceCounter(¤t_ticks); - - //Check if delta_ticks exceeds 1 seconds. - //This is done to prevent possible problems caused by large time deltas, - //which could be caused by checking breakpoints during development - //or by occasional freezes during normal game-play. - - auto delta_microseconds = current_ticks.QuadPart - performanceCounterTicks; - delta_microseconds *= 1000000; delta_microseconds /= processorFrequency; - const auto delta_time = GTSL::Microseconds(delta_microseconds); - - if (delta_time > GTSL::Microseconds(GTSL::Seconds(1))) { - deltaTime = static_cast(GTSL::Milliseconds(16)); - } - else { - deltaTime = delta_time; - } - - elapsedTime += delta_time; - - //Set system ticks as this frame's ticks so in the next update we can work with it. - performanceCounterTicks = current_ticks.QuadPart; -#elif BE_PLATFORM_LINUX - timespec time; - clock_gettime(CLOCK_MONOTONIC, &time); - - auto absoluteNanoseconds = GTSL::Nanoseconds(time.tv_nsec); - const auto deltaTime = absoluteNanoseconds - elapsedTime; - - if(deltaTime > GTSL::Microseconds(GTSL::Seconds(1))) { - this->deltaTime = static_cast(GTSL::Milliseconds(16)); - } else { - this->deltaTime = deltaTime; - } - - elapsedTime += deltaTime; -#endif -} - - -#undef GetCurrentTime -GTSL::Microseconds Clock::GetCurrentMicroseconds() const { -#if BE_PLATFORM_WINDOWS - LARGE_INTEGER win_processor_ticks; QueryPerformanceCounter(&win_processor_ticks); return GTSL::Microseconds(win_processor_ticks.QuadPart * 1000000 / processorFrequency); -#elif BE_PLATFORM_LINUX - timespec time; clock_gettime(CLOCK_MONOTONIC, &time); return GTSL::Microseconds(GTSL::Nanoseconds(time.tv_nsec)); -#endif -} - -//UTILITY GETTERS - - -uint16 Clock::GetYear() -{ -#if BE_PLATFORM_WINDOWS - SYSTEMTIME WinTimeStructure; - GetLocalTime(&WinTimeStructure); - return WinTimeStructure.wYear; -#endif - - const time_t now = time(NULL); - struct tm here; - - localtime_r(&now, &here); - - return here.tm_year + 1900; -} - -Clock::Months Clock::GetMonth() -{ -#if BE_PLATFORM_WINDOWS - SYSTEMTIME WinTimeStructure; - GetLocalTime(&WinTimeStructure); - return static_cast(WinTimeStructure.wMonth); -#endif - - const time_t now = time(NULL); - struct tm here; - - localtime_r(&now, &here); - - return static_cast(here.tm_mon + 1); -} - -uint8 Clock::GetDayOfMonth() -{ -#if BE_PLATFORM_WINDOWS - SYSTEMTIME WinTimeStructure; - GetLocalTime(&WinTimeStructure); - return WinTimeStructure.wDay; -#endif - - const time_t now = time(NULL); - struct tm here; - - localtime_r(&now, &here); - - return here.tm_mday; -} - -Clock::Days Clock::GetDayOfWeek() -{ -#if BE_PLATFORM_WINDOWS - SYSTEMTIME WinTimeStructure; - GetLocalTime(&WinTimeStructure); - return (WinTimeStructure.wDayOfWeek == 0) ? Days::Sunday : static_cast(WinTimeStructure.wDayOfWeek); -#endif - - const time_t now = time(NULL); - struct tm here; - - localtime_r(&now, &here); - - return static_cast(here.tm_wday); -} - -Clock::Time Clock::GetTime() -{ -#if BE_PLATFORM_WINDOWS - SYSTEMTIME WinTimeStructure; - GetLocalTime(&WinTimeStructure); - return { static_cast(WinTimeStructure.wHour), static_cast(WinTimeStructure.wMinute), static_cast(WinTimeStructure.wSecond) }; -#endif - - const time_t now = time(NULL); - struct tm here; - - localtime_r(&now, &here); - - return { static_cast(here.tm_hour), static_cast(here.tm_min), static_cast(here.tm_sec) }; -} diff --git a/src/ByteEngine/Application/Clock.h b/src/ByteEngine/Application/Clock.h deleted file mode 100644 index b2c314a6..00000000 --- a/src/ByteEngine/Application/Clock.h +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" -#include "ByteEngine/Object.h" -#include - - -class Clock : public Object { -public: - Clock(); - ~Clock(); - - void OnUpdate(); - - //Used to specify time(Hour, Minute, Second). - struct Time { - uint8 Hour; - uint8 Minute; - uint8 Second; - }; - - //Used to specify days of the week, with Monday being 1 and Sunday being 7. - enum class Days : uint8 { - Monday = 1, - Tuesday, - Wednesday, - Thursday, - Friday, - Saturday, - Sunday, - }; - - //Used to specify months, with January being 1 and December being 12. - enum class Months : uint8 { - January = 1, - February, - March, - April, - May, - June, - July, - August, - September, - October, - November, - December, - }; - - //Returns the time elapsed since the last application update (tick). - [[nodiscard]] GTSL::Microseconds GetDeltaTime() const { return deltaTime; } - - //Returns the time the game has been running. - [[nodiscard]] GTSL::Microseconds GetElapsedTime() const { return elapsedTime; } - - [[nodiscard]] GTSL::Microseconds GetCurrentMicroseconds() const; - - //Returns the current local year of the computer. - static uint16 GetYear(); - - //Returns the current local month of the computer. - static Months GetMonth(); - - //Returns the current local day of the month of the computer. - static uint8 GetDayOfMonth(); - - //Returns the current local day of the week of the computer. - static Days GetDayOfWeek(); - - //Returns the current local time (Hour, Minute, Second) of the computer. - static Time GetTime(); - -private: -#if BE_PLATFORM_WINDOWS - uint64 startPerformanceCounterTicks = 0; - uint64 performanceCounterTicks = 0; - //Stores the frequency at which the processor operates. Used to calculate time differences between ticks. - uint64 processorFrequency = 0; -#endif - - GTSL::Microseconds deltaTime; - GTSL::Microseconds elapsedTime; -}; diff --git a/src/ByteEngine/Application/CommandMap.h b/src/ByteEngine/Application/CommandMap.h deleted file mode 100644 index f3257932..00000000 --- a/src/ByteEngine/Application/CommandMap.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "ByteEngine/Object.h" - -#include -#include -#include -#include - -class CommandMap : public Object -{ -public: - CommandMap() = default; - ~CommandMap() = default; - - void RegisterCommand(const char* name, const GTSL::Delegate& function) { commands.Emplace(GetPersistentAllocator(), GTSL::Id64(name), function); } - bool DoCommand(const GTSL::String& line) - { - const auto command_end = line.FindFirst(' '); - if(command_end == line.npos()) { return false; } - - const GTSL::Id64 command{ line.c_str() + command_end }; - const auto result = commands.Find(command); - if (result == commands.end()) { return false; } - //commands[command](GTSL::String(line.GetLength() - command_end, line, command_end)); - return true; - } - -private: - GTSL::HashMap> commands; -}; diff --git a/src/ByteEngine/Application/Console.h b/src/ByteEngine/Application/Console.h deleted file mode 100644 index 8d2505b9..00000000 --- a/src/ByteEngine/Application/Console.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -namespace GTSL { - class String; -} - -class Console -{ -public: - Console() = default; - virtual ~Console() = default; - - virtual void GetLine(GTSL::String& line) = 0; - virtual void PutLine(const GTSL::String& line) = 0; -}; diff --git a/src/ByteEngine/Application/EditorInterface.h b/src/ByteEngine/Application/EditorInterface.h deleted file mode 100644 index 3860ee5d..00000000 --- a/src/ByteEngine/Application/EditorInterface.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Game/System.hpp" - -class EditorInterface : public System { -public: - void Initialize(const InitializeInfo& initializeInfo) override { - socket.Open(EDITOR_ADDRESS, false); - } - - void t() { - GTSL::IPv4Endpoint sender; byte buffer[512]; - auto received = socket.Receive(&sender, GTSL::Range(512, buffer)); - if(sender != EDITOR_ADDRESS) {} - - //for every packet - // ++counter - // if counter != packet.index - // reject - - - ApplicationManager* gameInstance; - gameInstance->DispatchEvent("Editor Interface", ) - //push to command list - } - - void s() { - auto sendResult = socket.Send(EDITOR_ADDRESS, {}); - } - -private: - static constexpr auto EDITOR_ADDRESS = GTSL::IPv4Endpoint(127, 0, 0, 1, 436); - GTSL::UDPSocket socket; - uint16 counter = 0; -}; diff --git a/src/ByteEngine/Application/EntryPoint.h b/src/ByteEngine/Application/EntryPoint.h deleted file mode 100644 index 0da25f95..00000000 --- a/src/ByteEngine/Application/EntryPoint.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "Application.h" - -extern int CreateApplication(GTSL::Range arguments); //Is defined in another translation unit. -//extern int CreateApplication(); //Is defined in another translation unit. - -inline bool BasicCompatibilityTest() { - return sizeof(utf8) == 1 && sizeof(uint8) == 1 && sizeof(uint16) == 2 && sizeof(uint32) == 4 && sizeof(uint64) == 8; -} - -int main(int argc, char** argv) -{ - int exitCode = 0; - - if (!BasicCompatibilityTest()) { exitCode = -1; return exitCode; } - - GTSL::StringView arguments[32]; - - for (uint8 i = 0; i < argc; ++i) { - arguments[i] = GTSL::StringView((const utf8*)argv[i]); - } - - // When CreateApplication() is defined it must return a new object of it class, effectively letting us manage that instance from here. - exitCode = CreateApplication({ argc, arguments }); - - return exitCode; -} - -inline int do_default_flow(BE::Application* application) { - int exitCode = -1; - - if (application->base_initialize({})) //call BE::Application initialize, which does basic universal startup - { - if (application->initialize()) //call BE::Application virtual initialize which will call the chain of initialize's - { - //Call Run() on Application. There lies the actual application code, like the Engine SubSystems' initialization, the game loop, etc. - application->run(); - } - } - - application->shutdown(); - - return exitCode; //Return and exit. -} \ No newline at end of file diff --git a/src/ByteEngine/Application/Handle.hpp b/src/ByteEngine/Application/Handle.hpp deleted file mode 100644 index 6f70f09b..00000000 --- a/src/ByteEngine/Application/Handle.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/src/ByteEngine/Application/InputManager.cpp b/src/ByteEngine/Application/InputManager.cpp deleted file mode 100644 index 53827001..00000000 --- a/src/ByteEngine/Application/InputManager.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "InputManager.h" - -#include "Application.h" -#include "ByteEngine/Debug/Logger.h" - -InputManager::InputManager() : Object(u8"InputManager"), - inputEvents(64, GetPersistentAllocator()), - inputDevices(8, GetPersistentAllocator()), - inputSources(128, 0.2f, GetPersistentAllocator()), - inputSourceRecords(8, GetPersistentAllocator()), - inputLayers(4, { GetPersistentAllocator() }) -{ -} - -InputManager::~InputManager() -{ -} - -void InputManager::Update() -{ - GTSL::Microseconds current_time{ BE::Application::Get()->GetClock()->GetElapsedTime() }; - - auto* applicationManager = BE::Application::Get()->GetGameInstance(); - - updateInput(applicationManager, current_time); -} \ No newline at end of file diff --git a/src/ByteEngine/Application/InputManager.h b/src/ByteEngine/Application/InputManager.h deleted file mode 100644 index 4c9f39da..00000000 --- a/src/ByteEngine/Application/InputManager.h +++ /dev/null @@ -1,483 +0,0 @@ -#pragma once - -#include "ByteEngine/Object.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "ByteEngine/Id.h" - -#include "ByteEngine/Debug/Logger.h" -#include "ByteEngine/Game/ApplicationManager.h" - -namespace GTSL { - class Window; -} - -struct InputDeviceHandle { - uint32 DeviceHandle, DeviceIndex; -}; - -template -constexpr E GetType(); - -class InputManager : public Object -{ -public: - enum class Type { - NONE, BOOL, CHAR, LINEAR, VECTOR2D, VECTOR3D, COLOR, QUATERNION - }; - - union Datatypes { - Datatypes() : Color(0, 0, 0, 0) {} - Datatypes(bool b) : Action(b) {} - Datatypes(char32_t c) : Unicode(c) {} - Datatypes(float32 f) : Linear(f) {} - Datatypes(GTSL::Vector2 v) : Vector2D(v) {} - Datatypes(GTSL::Vector3 v) : Vector3D(v) {} - Datatypes(GTSL::RGBA r) : Color(r) {} - Datatypes(GTSL::Quaternion q) : Quaternion(q) {} - - GTSL::RGBA Color; - bool Action; char32_t Unicode; float32 Linear; - GTSL::Vector2 Vector2D; GTSL::Vector3 Vector3D; - GTSL::Quaternion Quaternion; - }; - - /** - * \brief Defines an input event which is a named event that is triggered when one of the InputSourceEvents that it is bound to occurs. - */ - template - struct InputEvent - { - using type = T; - InputDeviceHandle DeviceIndex; - GTSL::StaticString<64> InputSource; - GTSL::Microseconds LastEventTime; - T Value, LastValue; - - InputEvent(InputDeviceHandle device_handle, GTSL::StringView inputSource, GTSL::Microseconds lastEvent, T val, T lastVal) : DeviceIndex(device_handle), InputSource(inputSource), LastEventTime(lastEvent), Value(val), LastValue(lastVal) {} - }; - - MAKE_HANDLE(uint32, InputLayer) - - using ActionInputEvent = InputEvent; - using LinearInputEvent = InputEvent; - using CharacterInputEvent = InputEvent; - using Vector2DInputEvent = InputEvent; - using Vector3DInputEvent = InputEvent; - using QuaternionInputEvent = InputEvent; - - InputManager(); - ~InputManager(); - - InputLayerHandle RegisterInputLayer(const GTSL::StringView) { - uint32 index = inputLayers.GetLength(); - return InputLayerHandle(index); - } - - InputDeviceHandle RegisterInputDevice(GTSL::StringView inputDeviceName) { - auto index = inputDevices.GetLength(); - auto& inputDevice = inputDevices.EmplaceBack(); - inputDevice.Name = inputDeviceName; - auto deviceIndex = inputDevice.ActiveIndeces.GetLength(); - inputDevice.ActiveIndeces.EmplaceBack(0); - return InputDeviceHandle(index, deviceIndex); - } - - void UnregisterInputDevice(InputDeviceHandle inputDeviceHandle) { - if (inputDeviceHandle.DeviceHandle + 1u > inputDevices.GetLength()) { BE_LOG_WARNING(u8"Tried to unregister an input source but it wasn't registered."); return; } - inputDevices.Pop(inputDeviceHandle.DeviceHandle); - } - - void RegisterInputSource(InputDeviceHandle, GTSL::StringView inputSourceName, Type type) { - auto inputSource = inputSources.TryEmplace(inputSourceName); - - if (!inputSource.State()) { - BE_LOG_WARNING(u8"Tried to register input source ", GTSL::StringView(inputSourceName), u8" but it was already registered."); - return; - } - - inputSource.Get().SourceType = type; - //inputSource.Get().Pos = inputSourcesRecords.GetLength(); - - switch (type) { - case Type::NONE: { - break; - } - case Type::BOOL: { - //*inputSourcesRecords.AllocateStructure() = false; - break; - } - case Type::CHAR: { - //*inputSourcesRecords.AllocateStructure() = 0; - break; - } - case Type::LINEAR: { - //*inputSourcesRecords.AllocateStructure() = 0.0f; - break; - } - case Type::VECTOR2D: { - //inputSourcesRecords.AllocateStructure(); - break; - } - case Type::VECTOR3D: { - //inputSourcesRecords.AllocateStructure(); - break; - } - } - } - - void RegisterInputSources(InputDeviceHandle, GTSL::Range inputSourceNames, Type type) { - for (auto& e : inputSourceNames) { - auto inputSource = inputSources.TryEmplace(e); - - if (!inputSource.State()) { - BE_LOG_WARNING(u8"Tried to register input source ", GTSL::StringView(e), u8" but it was already registered."); - return; - } - - inputSource.Get().SourceType = type; - //inputSource.Get().Pos = inputSourcesRecords.GetLength(); - - //switch (type) { - //case InputSource::BOOL: { - // *inputSourcesRecords.AllocateStructure() = false; - //} - //case InputSource::Type::CHAR: { - // *inputSourcesRecords.AllocateStructure() = 0; - //} - //case InputSource::Type::LINEAR: { - // *inputSourcesRecords.AllocateStructure() = 0.0f; - //} - //case InputSource::Type::VECTOR2D: { - // inputSourcesRecords.AllocateStructure(); - //} - //case InputSource::Type::VECTOR3D: { - // inputSourcesRecords.AllocateStructure(); - //} - //} - } - } - - struct Action { - Action(const GTSL::StringView inputSource, const GTSL::StringView actionName) : InputSourceName(inputSource), ActionName(actionName), ActionType(Type::NONE) {} - - template - Action(const GTSL::StringView inputSource, const GTSL::StringView actionName, T val) : InputSourceName(inputSource), ActionName(actionName), Datatype(val), ActionType(GetType()) {} - - Id InputSourceName, ActionName; - Datatypes Datatype; - Type ActionType; - }; - - template - void SubscribeToInputEvent(GTSL::StringView eventName, GTSL::Range inputSourceNames, TaskHandle dynamicTaskHandle, bool p = false) { - auto inputEventIndex = inputEvents.GetLength(); - auto& inputEvent = inputEvents.EmplaceBack(); - - inputEvent.Handle = dynamicTaskHandle.Reference; - inputEvent.EventType = GetType(); - inputEvent.P = p; - - for (const auto& action : inputSourceNames) { - auto inputSource = inputSources.TryGet(GTSL::StringView(action.InputSourceName)); - - if (inputSource.State()) { - inputEvent.InputSources.Emplace(GTSL::StringView(action.InputSourceName)).TargetValue = action.Datatype; - - inputSource.Get().BoundInputEvents.EmplaceBack(inputEventIndex); - } else { - BE_LOG_WARNING(u8"Failed to register ", GTSL::StringView(action.ActionName), u8" action, input source ", GTSL::StringView(action.InputSourceName), u8" was not registered. Cannot create an action event which depends on a non existant input source, make sure the input source is registered before registering this input event"); - } - } - } - - template - void RecordInputSource(InputDeviceHandle deviceIndex, GTSL::StringView eventName, T newValue) - { - if (!inputSources.Find(eventName)) { BE_LOG_WARNING(u8"Tried to record ", GTSL::StringView(eventName), u8" which is not registered as an input source."); return; } - if (inputSources[eventName].SourceType != GetType()) { BE_LOG_WARNING(u8"Tried to record ", GTSL::StringView(eventName), u8" but the input source's type does not match the type of the data being supplied."); return; } - - inputSourceRecords.EmplaceBack(deviceIndex, eventName, newValue); - } - - ActionInputEvent::type GetActionInputSourceValue(InputDeviceHandle, GTSL::StringView eventName) const { - return inputSources[eventName].LastValue.Action; - } - - CharacterInputEvent::type GetCharacterInputSourceValue(InputDeviceHandle, GTSL::StringView eventName) const { - return inputSources[eventName].LastValue.Unicode; - } - - LinearInputEvent::type GetLinearInputSourceValue(InputDeviceHandle, GTSL::StringView eventName) const { - return inputSources[eventName].LastValue.Linear; - } - - Vector2DInputEvent::type GetVector2DInputSourceValue(InputDeviceHandle, GTSL::StringView eventName) const { - return inputSources[eventName].LastValue.Vector2D; - } - - void Update(); - - void SetInputDeviceParameter(InputDeviceHandle deviceHandle, GTSL::StringView parameterName, float32 value) { - inputDevices[deviceHandle.DeviceHandle].Parameters.At(parameterName).Linear = value; - } - - void SetInputDeviceParameter(InputDeviceHandle deviceHandle, GTSL::StringView parameterName, GTSL::RGBA value) { - inputDevices[deviceHandle.DeviceHandle].Parameters.At(parameterName).Color = value; - } - - [[nodiscard]] float32 GetInputDeviceParameter(InputDeviceHandle inputDeviceHandle, GTSL::StringView parameterName) const { - return inputDevices[inputDeviceHandle.DeviceHandle].Parameters.At(parameterName).Linear; - } - - void RegisterInputDeviceParameter(InputDeviceHandle inputDeviceHandle, GTSL::StringView parameterName) { - inputDevices[inputDeviceHandle.DeviceHandle].Parameters.Emplace(parameterName); - } - -protected: - struct InputSource { - GTSL::Microseconds LastTime; - Datatypes LastValue; - float32 Threshold = 0, DeadZone = 0.1f; - - Type SourceType; - - GTSL::StaticVector BoundInputEvents; - - InputSource() = default; - - template - InputSource(const T lstValue, const GTSL::Microseconds lstTime) : LastTime(lstTime), LastValue(lstValue) - { - } - }; - - struct InputEventData { - Type EventType; - uint32 Handle = ~0U; - - bool P = false; - - struct Action { - Datatypes TargetValue; - uint32_t StackEntry = ~0U; - }; - GTSL::StaticMap InputSources{ 4, 0.75f }; - - GTSL::StaticVector Stack; - }; - GTSL::Vector inputEvents; - - struct InputDevice { - GTSL::StaticString<64> Name; - GTSL::StaticVector ActiveIndeces; - GTSL::StaticMap Parameters; - }; - GTSL::Vector inputDevices; - GTSL::HashMap inputSources; - - /** - * \brief Defines an InputSourceRecord which is record of the value the physical input source(keyboard, mouse, VR controller, etc) it is associated to had when it was triggered. - * This can be a boolean value(on, off) triggered by a keyboard key, mouse click, etc; - * a linear value(X) triggered by a gamepad trigger, slider value, etc; - * a 3D value(X, Y, Z) triggered by a VR controller move, hand tracker move, etc; - * and a Quaternion value(X, Y, Z, Q)(rotation) triggered by a VR controller rotation change, phone orientation change, etc. - */ - struct InputSourceRecord { - InputDeviceHandle DeviceIndex; - - /** - * \brief Name of the input source which caused the input source event. - */ - GTSL::StaticString<64> InputSource; - - Datatypes NewValue; - - InputSourceRecord() = default; - - template - InputSourceRecord(InputDeviceHandle deviceIndex, const GTSL::StringView name, T newValue) : DeviceIndex(deviceIndex), InputSource(name), NewValue(newValue) - { - } - }; - - GTSL::Vector inputSourceRecords; - - InputLayerHandle activeInputLayer; - GTSL::SemiVector inputLayers; - - void updateInput(ApplicationManager* application_manager, GTSL::Microseconds time) { - for (const auto& record : inputSourceRecords) { - auto& inputSource = inputSources[GTSL::StringView(record.InputSource)]; - - for (const auto bie : inputSource.BoundInputEvents) { - auto& inputEventData = inputEvents[bie]; - - if (inputEventData.Handle != ~0U) { - switch (inputEventData.EventType) { - case Type::BOOL: { - bool newValue = false, oldValue = false; - - switch (inputSource.SourceType) { - case Type::NONE: break; - case Type::BOOL: { - newValue = record.NewValue.Action; - oldValue = inputSource.LastValue.Action; - break; - } - case Type::CHAR: break; - case Type::LINEAR: { - const bool wasPressed = inputSource.LastValue.Linear >= inputSource.Threshold; - - if (record.NewValue.Linear >= inputSource.Threshold) { //if is pressed - if (!wasPressed) { //and wasn't pressed - oldValue = false; - newValue = true; - } - } - else { //isn't pressed - if (wasPressed && record.NewValue.Linear <= inputSource.Threshold - 0.10f) { - oldValue = true; - newValue = false; - } - } - break; - } - case Type::VECTOR2D: break; - case Type::VECTOR3D: break; - case Type::COLOR: break; - case Type::QUATERNION: break; - } - - if (oldValue != newValue) { - if (inputEventData.P) { - application_manager->EnqueueScheduledTask(TaskHandle>(inputEventData.Handle), InputEvent(record.DeviceIndex, record.InputSource, inputSource.LastTime, newValue, oldValue)); - } else { - application_manager->EnqueueTask(TaskHandle>(inputEventData.Handle), InputEvent(record.DeviceIndex, record.InputSource, inputSource.LastTime, newValue, oldValue)); - } - } - - break; - } - case Type::CHAR: { - application_manager->EnqueueTask(TaskHandle>(inputEventData.Handle), InputEvent(record.DeviceIndex, record.InputSource, inputSource.LastTime, record.NewValue.Unicode, U'0')); - break; - } - case Type::LINEAR: { - float32 newVal = 0.0f, oldVal = 0.0f; - - bool update = false; - - switch (inputSource.SourceType) { - case Type::BOOL: { - auto& action = inputEventData.InputSources[record.InputSource]; - - if (record.NewValue.Action) { // If key was pressed - newVal = action.TargetValue.Linear; // Set new value as target value - - if(inputEventData.Stack) { - update = true; - } - - if (action.StackEntry == ~0U) { // If triggering source has no stack entry associated create one and bind it - action.StackEntry = inputEventData.Stack.GetLength(); - auto& stackEntry = inputEventData.Stack.EmplaceBack(); - stackEntry.Linear = newVal; - } - - } else { - if (action.StackEntry != ~0U) { - inputEventData.Stack.Pop(action.StackEntry); - - for(auto& e : inputEventData.InputSources) { - if(e.StackEntry > action.StackEntry and e.StackEntry != ~0U) { - --e.StackEntry; - } - } - - action.StackEntry = ~0U; - } - - if (inputEventData.Stack.GetLength()) { - newVal = inputEventData.Stack.back().Linear; - update = true; - } - } - break; - } - case Type::LINEAR: { - newVal = record.NewValue.Linear; - oldVal = inputSource.LastValue.Linear; - break; - } - } - - if (inputEventData.P) { - if (newVal != 0.0f) { - if (update) { - application_manager->RemoveScheduledTask(TaskHandle>(inputEventData.Handle)); - } - application_manager->EnqueueScheduledTask(TaskHandle>(inputEventData.Handle), InputEvent(record.DeviceIndex, record.InputSource, inputSource.LastTime, newVal, oldVal)); - } else { - application_manager->RemoveScheduledTask(TaskHandle>(inputEventData.Handle)); - } - } else { - application_manager->EnqueueTask(TaskHandle>(inputEventData.Handle), InputEvent(record.DeviceIndex, record.InputSource, inputSource.LastTime, newVal, oldVal)); - } - - break; - } - case Type::VECTOR2D: { - GTSL::Vector2 newValue, oldValue; - - switch (inputSource.SourceType) { - case Type::VECTOR2D: { - newValue = record.NewValue.Vector2D; - break; - } - } - - if (GTSL::Math::LengthGreater(newValue, GTSL::Vector2(inputSource.Threshold))) { - application_manager->EnqueueTask(TaskHandle>(inputEventData.Handle), InputEvent(record.DeviceIndex, record.InputSource, inputSource.LastTime, newValue, oldValue)); - } - break; - } - } - } - } - - inputSource.LastValue = record.NewValue; - inputSource.LastTime = time; - } - - inputSourceRecords.Resize(0); - } -}; - -template<> -constexpr InputManager::Type GetType() { return InputManager::Type::BOOL; } - -template<> -constexpr InputManager::Type GetType() { return InputManager::Type::CHAR; } - -template<> -constexpr InputManager::Type GetType() { return InputManager::Type::LINEAR; } - -template<> -constexpr InputManager::Type GetType() { return InputManager::Type::VECTOR2D; } - -template<> -constexpr InputManager::Type GetType() { return InputManager::Type::VECTOR3D; } - -template<> -constexpr InputManager::Type GetType() { return InputManager::Type::COLOR; } - -template<> -constexpr InputManager::Type GetType() { return InputManager::Type::QUATERNION; } \ No newline at end of file diff --git a/src/ByteEngine/Application/PoolAllocator.cpp b/src/ByteEngine/Application/PoolAllocator.cpp deleted file mode 100644 index f160d553..00000000 --- a/src/ByteEngine/Application/PoolAllocator.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include "PoolAllocator.h" - -#include - -#include -#include -#include -#include -#include - -#include "ByteEngine/Debug/Assert.h" - -PoolAllocator::PoolAllocator(BE::SystemAllocatorReference* allocatorReference) : systemAllocatorReference(allocatorReference) {} - -void PoolAllocator::Pool::initialize(const uint32 slotsCount, const uint32 slotsSize, uint64& allocatedSize, BE::SystemAllocatorReference* allocatorReference) -{ - SLOTS_SIZE = slotsSize; MAX_SLOTS_COUNT = GTSL::Math::RoundUpByPowerOf2(slotsCount, 8); - - uint64 pool_allocated_size{ 0 }; - - // Allocate memory for slots, this memory is where allocations will be placed - allocatorReference->Allocate(slotsDataAllocationSize(), slotsDataAllocationAlignment(), reinterpret_cast(&slotsData), &pool_allocated_size); - allocatedSize += pool_allocated_size; - - // Allocate memory to track free slots - allocatorReference->Allocate(GTSL::GetAllocationSize(MAX_SLOTS_COUNT), alignof(free_slots_type), reinterpret_cast(&freeSlots), &pool_allocated_size); - allocatedSize += pool_allocated_size; - - bitNums = MAX_SLOTS_COUNT / GTSL::Bits() + 1; - -#if BE_DEBUG - if constexpr (DEALLOC_COUNT) { - allocatorReference->Allocate(GTSL::GetAllocationSize(MAX_SLOTS_COUNT), alignof(free_slots_type), reinterpret_cast(&freeSlotsBitTrack2), &pool_allocated_size); - allocatedSize += pool_allocated_size; - - GTSL::InitializeBits(GTSL::Range(bitNums, freeSlotsBitTrack2)); - - allocatorReference->Allocate(MAX_SLOTS_COUNT * sizeof(uint8), alignof(uint8), reinterpret_cast(&allocCounter), &pool_allocated_size); - allocatedSize += pool_allocated_size; - - for (uint32 i = 0; i < MAX_SLOTS_COUNT; ++i) { - allocCounter[i] = 0; - } - } -#endif - - // Initialize free slots - GTSL::InitializeBits(GTSL::Range(bitNums, freeSlots)); - - if constexpr (MEMORY_PATTERN) { - for (uint32 i = 0; i < SLOTS_SIZE * MAX_SLOTS_COUNT; ++i) { - slotsData[i] = 0xCA; - } - } -} - -void PoolAllocator::initialize() { - BE_ASSERT(maximumPoolSize != 0 || minimumPoolSize != 0, "Minimum and maximum pool size must be set."); - BE_ASSERT(minimumPoolSize <= maximumPoolSize, "Minimum pool size must be smaller than maximum pool size."); - BE_ASSERT(GTSL::Math::IsPowerOfTwo(minimumPoolSize), "Minimum pool size must be a power of 2."); - BE_ASSERT(GTSL::Math::IsPowerOfTwo(maximumPoolSize), "Maximum pool size must be a power of 2."); - - uint64 allocator_allocated_size{ 0 }; // Accumulated size of all allocations of underlying pools - - minimumPoolSizeBits = GTSL::FindFirstSetBit(minimumPoolSize).Get(); - maximumPoolSizeBits = GTSL::FindFirstSetBit(maximumPoolSize).Get(); - - uint64 poolCount = maximumPoolSizeBits - minimumPoolSizeBits + 1; - - for(uint64 i = 0, poolSizeBits = minimumPoolSizeBits; i < poolCount; ++poolSizeBits, ++i) { - const auto slot_count = (poolCount - i) * 60; //pools with smaller slot sizes get more slots - const auto slot_size = 1 << poolSizeBits; // 2^poolSize, all pools have power of 2 slot sizes - - //auto& pool = pools.EmplaceBack(); - auto& pool = pools[i]; - pool.initialize(slot_count, slot_size, allocator_allocated_size, systemAllocatorReference); - } - - this->poolCount = poolCount; -} - -// ALLOCATE // - -void PoolAllocator::Allocate(const uint64 size, const uint64 alignment, void** memory, uint64* allocatedSize, GTSL::Range name) const -{ - // Find the smallest pool size that can fit the allocation - uint64 allocationMinSize = GTSL::NextPowerOfTwo(GTSL::Math::RoundUpByPowerOf2(size, alignment)); - allocationMinSize = GTSL::Math::Max(allocationMinSize, minimumPoolSize); // - - BE_ASSERT(allocationMinSize <= maximumPoolSize, "Allocation is too big!"); - BE_ASSERT((alignment & (alignment - 1)) == 0, "Alignment is not power of two!"); - - if constexpr (USE_MALLOC) { - *memory = malloc(size); - *allocatedSize = size; - } else { - auto set_bit = GTSL::FindFirstSetBit(allocationMinSize); - uint64 poolIndex = set_bit.Get() - minimumPoolSizeBits; - pools[poolIndex].allocate(size, alignment, memory, allocatedSize); - } - - if constexpr (DEALLOC_COUNT) { - //GTSL::Lock lock(debugLock); - //allocMap.emplace(*memory, allocationMinSize); - } -} - -void PoolAllocator::Pool::allocate(const uint64 size, const uint64 alignment, void** data, uint64* allocatedSize) const -{ - //GTSL::Lock lock(poolLock); - - auto slot = GTSL::OccupyFirstFreeSlot(GTSL::Range(bitNums, freeSlots)); - - byte* const slot_address = getSlotAddress(slot.Get()); - - if constexpr (MEMORY_PATTERN) { - bool isCorrect = true; - - for (uint32 i = 0; i < SLOTS_SIZE; ++i) { - if (slot_address[i] != 0xCA) { isCorrect = false; break; } - } - - BE_ASSERT(isCorrect, u8"Memory was written to after deallocation."); - } - -#if BE_DEBUG - if constexpr (DEALLOC_COUNT) { - auto slot2 = GTSL::OccupyFirstFreeSlot(GTSL::Range(bitNums, freeSlotsBitTrack2)); - BE_ASSERT(slot.Get() == slot2.Get(), u8""); - BE_ASSERT(allocCounter[slot.Get()] == 0, u8""); - ++allocCounter[slot.Get()]; - } -#endif - - BE_ASSERT(slot.State(), "No more free slots!") - - //*data = GTSL::AlignPointer(alignment, slot_address); - *data = slot_address; - *allocatedSize = (slot_address + SLOTS_SIZE) - static_cast(*data); - - BE_ASSERT(*data >= slotsData && *data <= slotsData + slotsDataAllocationSize(), "Allocation does not belong to pool!") -} - -// DEALLOCATE // - -void PoolAllocator::Deallocate(const uint64 size, const uint64 alignment, void* memory, GTSL::Range name) const -{ - uint64 allocationMinSize = GTSL::NextPowerOfTwo(size); - allocationMinSize = GTSL::Math::Max(allocationMinSize, minimumPoolSize); // - - BE_ASSERT(allocationMinSize <= maximumPoolSize, "Allocation is too big!"); - BE_ASSERT((alignment & (alignment - 1)) == 0, "Alignment is not power of two!"); - - if constexpr (USE_MALLOC) { - ::free(memory); - } else { - auto set_bit = GTSL::FindFirstSetBit(allocationMinSize); - uint64 poolIndex = set_bit.Get() - minimumPoolSizeBits; - pools[poolIndex].deallocate(size, alignment, memory, systemAllocatorReference); - } - - if constexpr (DEALLOC_COUNT) { - //GTSL::Lock lock(debugLock); - //BE_ASSERT(allocMap.at(memory) == allocationMinSize, u8""); - //allocMap.erase(memory); - } -} - -void PoolAllocator::Pool::deallocate(uint64 size, const uint64 alignment, void* memory, BE::SystemAllocatorReference* allocatorReference) const -{ - //GTSL::Lock lock(poolLock); - - BE_ASSERT(memory >= slotsData && memory <= slotsData + slotsDataAllocationSize(), "Allocation does not belong to pool!") - - const auto index = getSlotIndexFromPointer(memory); - - if constexpr (MEMORY_PATTERN) { - for (uint32 i = 0; i < SLOTS_SIZE; ++i) { - static_cast(memory)[i] = 0xCA; - } - } - -#if BE_DEBUG - if constexpr (DEALLOC_COUNT) { - GTSL::SetAsFree(GTSL::Range(bitNums, freeSlotsBitTrack2), index); - BE_ASSERT(allocCounter[index] == 1, u8""); - --allocCounter[index]; - } -#endif - - GTSL::SetAsFree(GTSL::Range(bitNums, freeSlots), index); -} - -// FREE // - -void PoolAllocator::free() { - uint64 freed_bytes{ 0 }; - - for (auto& pool : pools) { pool.free(freed_bytes, systemAllocatorReference); } -} - -void PoolAllocator::Pool::free(uint64& freedBytes, BE::SystemAllocatorReference* allocatorReference) { - if (slotsData) allocatorReference->Deallocate(slotsDataAllocationSize(), slotsDataAllocationAlignment(), slotsData); - if(freeSlots) allocatorReference->Deallocate(GTSL::GetAllocationSize(MAX_SLOTS_COUNT), alignof(free_slots_type), freeSlots); - -#if BE_DEBUG - if constexpr (DEALLOC_COUNT) { - allocatorReference->Deallocate(GTSL::GetAllocationSize(MAX_SLOTS_COUNT), alignof(free_slots_type), freeSlotsBitTrack2); - freedBytes += GTSL::GetAllocationSize(MAX_SLOTS_COUNT); - - allocatorReference->Deallocate(MAX_SLOTS_COUNT * sizeof(uint8), alignof(uint32), allocCounter); - freedBytes += MAX_SLOTS_COUNT * sizeof(uint8); - } -#endif -} \ No newline at end of file diff --git a/src/ByteEngine/Application/PoolAllocator.h b/src/ByteEngine/Application/PoolAllocator.h deleted file mode 100644 index 30305d64..00000000 --- a/src/ByteEngine/Application/PoolAllocator.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include - -#include "ByteEngine/Core.h" - -#include -#include -#include - -#include "ByteEngine/Game/System.hpp" - -class PoolAllocator { -public: - PoolAllocator() = default; - PoolAllocator(BE::SystemAllocatorReference* allocatorReference); - - ~PoolAllocator() = default; - - void initialize(); - - void Allocate(uint64 size, uint64 alignment, void** memory, uint64* allocatedSize, GTSL::Range name) const; - void Deallocate(uint64 size, uint64 alignment, void* memory, const GTSL::Range name) const; - - void free(); - - class Pool { - public: - Pool() = default; - - // Intialize pool with slotsCount slots of size slotsSize - void initialize(uint32 slotsCount, uint32 slotsSize, uint64& allocatedSize, BE::SystemAllocatorReference* allocatorReference); - - // Allocate memory from pool - void allocate(uint64 size, uint64 alignment, void** data, uint64* allocatedSize) const; - - // Deallocate memory from pool - void deallocate(uint64 size, uint64 alignment, void* memory, BE::SystemAllocatorReference* allocatorReference) const; - - // Free pool - void free(uint64& freedBytes, BE::SystemAllocatorReference* allocatorReference); - - private: - using free_slots_type = uint64; - - free_slots_type* freeSlots = nullptr; - -#if BE_DEBUG - free_slots_type* freeSlotsBitTrack2{ nullptr }; - uint8* allocCounter{ nullptr }; -#endif - - byte* slotsData = nullptr; - - uint32 SLOTS_SIZE = 0; - uint32 MAX_SLOTS_COUNT = 0; - - //mutable GTSL::Mutex poolLock; - - uint32 bitNums = 0; - - [[nodiscard]] byte* getSlotAddress(const uint32 slotIndex) const { return slotsData + (slotIndex * SLOTS_SIZE); } - uint32 getSlotIndexFromPointer(void* pointer) const { return static_cast((static_cast(pointer) - slotsData) / SLOTS_SIZE); } - - [[nodiscard]] uint64 slotsDataAllocationSize() const { return static_cast(MAX_SLOTS_COUNT) * SLOTS_SIZE; } - static uint64 slotsDataAllocationAlignment() { return alignof(uint64); } - }; - - static constexpr bool USE_MALLOC = false; - static constexpr bool MEMORY_PATTERN = false; - static constexpr bool DEALLOC_COUNT = false; - -private: - uint64 minimumPoolSize = 16ull; // Minumum default size of a pool, 16 bytes - uint64 maximumPoolSize = 1024ull * 1024ull * 4ull; // Maximum default size of a pool, 4 MB - - uint64 minimumPoolSizeBits = 0ull; - uint64 maximumPoolSizeBits = 0ull; - - //GTSL::StaticVector pools; - - uint32 poolCount = 0; - Pool pools[32]; - - BE::SystemAllocatorReference* systemAllocatorReference{ nullptr }; - - // mutable GTSL::Mutex debugLock; - - // mutable std::unordered_map allocMap; - - // [[nodiscard]] GTSL::Range pools() const { return GTSL::Range(poolCount, pools); } -}; diff --git a/src/ByteEngine/Application/ScriptingSystem.cpp b/src/ByteEngine/Application/ScriptingSystem.cpp deleted file mode 100644 index b991ed85..00000000 --- a/src/ByteEngine/Application/ScriptingSystem.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "ScriptingSystem.hpp" \ No newline at end of file diff --git a/src/ByteEngine/Application/ScriptingSystem.hpp b/src/ByteEngine/Application/ScriptingSystem.hpp deleted file mode 100644 index 128961dd..00000000 --- a/src/ByteEngine/Application/ScriptingSystem.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "ByteEngine/Object.h" -#include "ByteEngine/Game/System.hpp" -#include "GTSL/Vector.hpp" - -struct ScriptingSystem : public BE::System -{ - ScriptingSystem(const InitializeInfo& initialize_info) : System(initialize_info, u8"ScriptingEngine") { -#if BE_PLATFORM_WINDOWS - mono_set_dirs("C:/Program Files/Mono/lib", "C:/Program Files/Mono/etc"); -#endif - - domain = mono_jit_init_version("ByteEngine", "v4.0.30319"); - - if(!domain) { - BE_LOG_ERROR(u8"Failed to initialize scripting VM.") - return; - } - - MonoAssembly* assembly = mono_domain_assembly_open(domain, "ByteEngine.dll"); - if (!assembly) { - BE_LOG_ERROR(u8"Failed to open C# script module.") - return; - } - - image = mono_assembly_get_image(assembly); - - if(!image) { - BE_LOG_ERROR(u8"Failed to get image from assembly.") - return; - } - - InvokeStaticMethod(u8"BE.EntryPoint:Print()"); - } - - template - void BindNativeMethodToScriptMethod(const GTSL::StringView fully_qualified_name) { - mono_add_internal_call(reinterpret_cast(fully_qualified_name.GetData()), (void*)F); - } - - void AttachThread() { - auto* monoThread = mono_thread_attach(domain); - } - - void InvokeStaticMethod(const GTSL::StringView fully_qualified_name) { - MonoMethodDesc* monoMethodDesc = mono_method_desc_new(reinterpret_cast(fully_qualified_name.GetData()), false); - if (!monoMethodDesc) { - BE_LOG_ERROR(u8"Failed to invoke script method: ", fully_qualified_name) - return; - } - - MonoMethod* method = mono_method_desc_search_in_image(monoMethodDesc, image); - if (!method) { - BE_LOG_ERROR(u8"Failed to invoke script method: ", fully_qualified_name) - return; - } - - //run the method - MonoObject* returnMonoObject = mono_runtime_invoke(method, nullptr, nullptr, nullptr); - } - - ~ScriptingSystem() { - mono_jit_cleanup(domain); - //Note that for current versions of Mono, the mono runtime can�t be reloaded into the same process, so call mono_jit_cleanup() only if you�re never going to initialize it again. - } - - void InvokeMethod() { - const char8_t* className = u8"Dog"; - - MonoClass* monoClass = mono_class_from_name(image, "BE", reinterpret_cast(className)); - if (!monoClass) { - BE_LOG_ERROR(u8"Failed to find script class: ", className) - return; - } - - MonoObject* monoObject = mono_object_new(domain, monoClass); - if (!monoClass) { - return; - } - - // Call its default constructor - mono_runtime_object_init(monoObject); - - //Build a method description object - MonoObject* result; - const char* BarkMethodDescStr = "Dog:Bark(int)"; - MonoMethodDesc* BarkMethodDesc = mono_method_desc_new(BarkMethodDescStr, false); - if (!BarkMethodDesc) { - return; - } - - MonoMethod* method = mono_method_desc_search_in_image(BarkMethodDesc, image); - if (!method) { - return; - } - - //Set the arguments for the method - void* args[1]; - int barkTimes = 3; - args[0] = &barkTimes; - - //Run the method - mono_runtime_invoke(method, monoObject, args, nullptr); - } - - void SetInstanceVariableValue() { - const char8_t* fieldName = u8""; - // find the Id field in the Entity class - MonoClassField* idField = mono_class_get_field_from_name(monoClass, reinterpret_cast(fieldName)); - - int value = 42; - - // set the field's value - mono_field_set_value(monoObject, idField, &value); - - int result; - mono_field_get_value(monoObject, idField, &result); - } - -private: - MonoDomain* domain = nullptr; - MonoImage* image = nullptr; - MonoObject* monoObject = nullptr; - MonoClass* monoClass = nullptr; -}; \ No newline at end of file diff --git a/src/ByteEngine/Application/StackAllocator.cpp b/src/ByteEngine/Application/StackAllocator.cpp deleted file mode 100644 index e8c0ebc9..00000000 --- a/src/ByteEngine/Application/StackAllocator.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "StackAllocator.h" - -#include -#include "ByteEngine/Debug/Assert.h" - -void StackAllocator::Block::initialize(const uint64 minimumSize, BE::SystemAllocatorReference allocatorReference, uint64& allocatedSize) -{ - uint64 allocated_size{ 0 }; - - allocatorReference.Allocate(minimumSize, alignof(byte), reinterpret_cast(&start), &allocated_size); - - allocatedSize = allocated_size; - - at = start; - end = start + allocated_size; -} - -void StackAllocator::Block::deinitialize(BE::SystemAllocatorReference allocatorReference, uint64& deallocatedBytes) const -{ - allocatorReference.Deallocate(end - start, alignof(byte), start); - deallocatedBytes += end - start; -} - -void StackAllocator::Block::AllocateInBlock(const uint64 size, const uint64 alignment, void** data, uint64& allocatedSize) -{ - allocatedSize = GTSL::Math::RoundUpByPowerOf2(size, alignment); - *data = GTSL::AlignPointer(alignment, at); at += allocatedSize; -} - -bool StackAllocator::Block::TryAllocateInBlock(const uint64 size, const uint64 alignment, void** data, uint64& allocatedSize) -{ - allocatedSize = GTSL::Math::RoundUpByPowerOf2(size, alignment); - if (at + allocatedSize < end) - { - //*data = GTSL::AlignPointer(alignment, at); - *data = at; - at += allocatedSize; - return true; - } - return false; -} - -void StackAllocator::Block::clear() { at = start; } \ No newline at end of file diff --git a/src/ByteEngine/Application/StackAllocator.h b/src/ByteEngine/Application/StackAllocator.h deleted file mode 100644 index c43c1640..00000000 --- a/src/ByteEngine/Application/StackAllocator.h +++ /dev/null @@ -1,359 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -#include -#include -#include -#include -#include -#include -#include "AllocatorReferences.h" -#include "ByteEngine/Debug/Assert.h" -#include - -class StackAllocator -{ -public: - struct DebugData - { - explicit DebugData(BE::SystemAllocatorReference*) - { - } - - struct PerNameData - { - GTSL::ShortString<128> Name; - uint64 AllocationCount{ 0 }; - uint64 DeallocationCount{ 0 }; - uint64 BytesAllocated{ 0 }; - uint64 BytesDeallocated{ 0 }; - }; - - std::unordered_map PerNameAllocationsData; - - /** - * \brief Number of times it was tried to allocate on different blocks to no avail. - * To improve this number(lower it) try to make the blocks bigger. - * Don't make it so big that in the event that a new block has to be allocated it takes up too much space. - * Reset to 0 on every call to GetDebugInfo() - */ - uint64 BlockMisses{ 0 }; - - uint64 BytesAllocated{ 0 }; - uint64 TotalBytesAllocated{ 0 }; - - uint64 BytesDeallocated{ 0 }; - uint64 TotalBytesDeallocated{ 0 }; - - uint64 AllocatorAllocatedBytes{ 0 }; - uint64 TotalAllocatorAllocatedBytes{ 0 }; - - uint64 AllocatorDeallocatedBytes{ 0 }; - uint64 TotalAllocatorDeallocatedBytes{ 0 }; - - uint64 AllocationsCount{ 0 }; - uint64 TotalAllocationsCount{ 0 }; - - uint64 DeallocationsCount{ 0 }; - uint64 TotalDeallocationsCount{ 0 }; - - uint64 AllocatorAllocationsCount{ 0 }; - uint64 TotalAllocatorAllocationsCount{ 0 }; - - uint64 AllocatorDeallocationsCount{ 0 }; - uint64 TotalAllocatorDeallocationsCount{ 0 }; - - operator GTSL::StaticString<1024>() const - { -#define ADD_FIELD(string, var) string += reinterpret_cast(#var); (string) += u8": "; ToString(string, var); (string) += u8'\n'; - - GTSL::StaticString<1024> result; - ADD_FIELD(result, BytesAllocated) - ADD_FIELD(result, TotalBytesAllocated) - ADD_FIELD(result, TotalAllocatorAllocatedBytes) - ADD_FIELD(result, TotalAllocatorDeallocatedBytes) - -#undef ADD_FIELD - return result; - } - }; - - StackAllocator() = default; - - void initialize(BE::SystemAllocatorReference allocatorReference, const uint8 stackCount = 8, const uint8 defaultBlocksPerStackCount = 2, const uint64 blockSizes = 512) - { - this->blockSize = blockSizes; - //this->stacks = GTSL::Vector, BE::SystemAllocatorReference>(stackCount, allocatorReference); - // this->allocatorReference = allocatorReference; - this->MAX_STACKS = stackCount; - this->blocksPerStack = defaultBlocksPerStackCount; - - uint64 allocated_size = 0; - - for (uint8 stack = 0; stack < stackCount; ++stack) - { - //stacks.EmplaceBack(defaultBlocksPerStackCount, allocatorReference); - - for (uint32 block = 0; block < defaultBlocksPerStackCount; ++block) - { - //stacks[stack].EmplaceBack(); //construct a default block - - stacks[stack][block].initialize(blockSizes, allocatorReference, allocated_size); - -#if BE_DEBUG - //GTSL::Lock lock(debugDataMutex); - ++allocatorAllocationsCount; - ++totalAllocatorAllocationsCount; - allocatorAllocatedBytes += allocated_size; - totalAllocatorAllocatedBytes += allocated_size; -#endif - } - } - } - - ~StackAllocator() - { - - } - -#if BE_DEBUG - void GetDebugData(DebugData& debugData) - { - //GTSL::Lock lock(debugDataMutex); - - debugData.BlockMisses = blockMisses; - - debugData.PerNameAllocationsData = perNameData; - - debugData.AllocationsCount = allocationsCount; - debugData.TotalAllocationsCount = totalAllocationsCount; - - debugData.DeallocationsCount = deallocationsCount; - debugData.TotalDeallocationsCount = totalDeallocationsCount; - - debugData.BytesAllocated = bytesAllocated; - debugData.TotalBytesAllocated = totalBytesAllocated; - - debugData.BytesDeallocated = bytesDeallocated; - debugData.TotalBytesDeallocated = totalBytesDeallocated; - - debugData.AllocatorAllocationsCount = allocatorAllocationsCount; - debugData.TotalAllocatorAllocationsCount = totalAllocatorAllocationsCount; - - debugData.AllocatorDeallocationsCount = allocatorDeallocationsCount; - debugData.TotalAllocatorDeallocationsCount = totalAllocatorDeallocationsCount; - - debugData.AllocatorAllocatedBytes = allocatorAllocatedBytes; - debugData.TotalAllocatorAllocatedBytes = totalAllocatorAllocatedBytes; - - debugData.AllocatorDeallocatedBytes = allocatorDeallocatedBytes; - debugData.TotalAllocatorDeallocatedBytes = totalAllocatorDeallocatedBytes; - - for (auto& e : perNameData) { - e.second.DeallocationCount = 0; - e.second.AllocationCount = 0; - e.second.BytesAllocated = 0; - e.second.BytesDeallocated = 0; - } - - blockMisses = 0; - - bytesAllocated = 0; - bytesDeallocated = 0; - - allocationsCount = 0; - deallocationsCount = 0; - - allocatorAllocationsCount = 0; - allocatorDeallocationsCount = 0; - - allocatorAllocatedBytes = 0; - allocatorDeallocatedBytes = 0; - } -#endif - - void clear() { - for(uint32 s = 0; s < MAX_STACKS; ++s) { - for(uint32 b = 0; b < blocksPerStack; ++b) { - stacks[s][b].clear(); - } - } - } - - void Allocate(uint64 size, uint64 alignment, void** memory, uint64* allocatedSize, const GTSL::Range name) - { - const auto i{ stackIndex % MAX_STACKS }; ++stackIndex; - - BE_ASSERT((alignment & (alignment - 1)) == 0, "Alignment is not power of two!"); - BE_ASSERT(size <= blockSize, "Single allocation is larger than block sizes! An allocation larger than block size can't happen."); - - uint64 allocated_size{ 0 }; - -#if BE_DEBUG - { - //GTSL::Lock lock(debugDataMutex); - perNameData.try_emplace(GTSL::Id64(name)()).first->second.Name = name; - } -#endif - - //stacksMutexes[i].Lock(); - for (auto& block : stacks[i]) - { - if (block.TryAllocateInBlock(size, alignment, memory, allocated_size)) - { - //stacksMutexes[i].Unlock(); - *allocatedSize = allocated_size; - -#if BE_DEBUG - { - //GTSL::Lock lock(debugDataMutex); - perNameData[GTSL::Id64(name)()].BytesAllocated += allocated_size; - perNameData[GTSL::Id64(name)()].AllocationCount += 1; - bytesAllocated += allocated_size; - totalBytesAllocated += allocated_size; - ++allocationsCount; - ++totalAllocationsCount; - } -#endif - - return; - } - -#if BE_DEBUG - //debugDataMutex.Lock(); - ++blockMisses; - //debugDataMutex.Unlock(); -#endif - } - - - BE_ASSERT(false, "No block could allocate memory!"); - - // auto& lastBlock = stacks[i].EmplaceBack(); - // lastBlock.initialize(blockSize, allocatorReference, allocated_size); - // lastBlock.AllocateInBlock(size, alignment, memory, allocated_size); - //stacksMutexes[i].Unlock(); - - *allocatedSize = allocated_size; - -#if BE_DEBUG - { - //GTSL::Lock lock(debugDataMutex); - perNameData[GTSL::Id64(name)()].BytesAllocated += allocated_size; - perNameData[GTSL::Id64(name)()].AllocationCount += 1; - bytesAllocated += allocated_size; - totalBytesAllocated += allocated_size; - allocatorAllocatedBytes += allocated_size; - totalAllocatorAllocatedBytes += allocated_size; - ++allocatorAllocationsCount; - ++totalAllocatorAllocationsCount; - ++allocationsCount; - ++totalAllocationsCount; - } -#endif - } - - void Deallocate(uint64 size, uint64 alignment, void*, const GTSL::Range name) - { - BE_ASSERT((alignment & (alignment - 1)) == 0, "Alignment is not power of two!"); - BE_ASSERT(size <= blockSize, "Deallocation size is larger than block size! An allocation larger than block size can't happen. Trying to deallocate more bytes than allocated!"); - -#if BE_DEBUG - const auto bytes_deallocated{ GTSL::Math::RoundUpByPowerOf2(size, alignment) }; - - //GTSL::Lock lock(debugDataMutex); - perNameData[GTSL::Id64(name)()].BytesDeallocated += bytes_deallocated; - perNameData[GTSL::Id64(name)()].DeallocationCount += 1; - bytesDeallocated += bytes_deallocated; - totalBytesDeallocated += bytes_deallocated; - ++deallocationsCount; - ++totalDeallocationsCount; -#endif - } - - void Free() - { - uint64 freed_bytes{ 0 }; - - for (auto& stack : stacks) - { - for (auto& block : stack) - { - //block.deinitialize(allocatorReference, freed_bytes); -#if BE_DEBUG - ++allocatorDeallocationsCount; - ++totalAllocatorDeallocationsCount; -#endif - } - } - -#if BE_DEBUG - allocatorDeallocatedBytes += freed_bytes; - totalAllocatorDeallocatedBytes += freed_bytes; -#endif - } - - -protected: - struct Block - { - Block() = default; - - byte* start{ nullptr }; - byte* at{ nullptr }; - byte* end{ nullptr }; - - void initialize(uint64 minimumSize, BE::SystemAllocatorReference allocatorReference, uint64& allocatedSize); - - void deinitialize(BE::SystemAllocatorReference allocatorReference, uint64& deallocatedBytes) const; - - void AllocateInBlock(uint64 size, uint64 alignment, void** data, uint64& allocatedSize); - - bool TryAllocateInBlock(uint64 size, uint64 alignment, void** data, uint64& allocatedSize); - - void clear(); - - [[nodiscard]] uint64 GetBlockSize() const { return end - start; } - [[nodiscard]] uint64 GetRemainingSize() const { return end - at; } - }; - - uint64 blockSize{ 0 }; - std::atomic_uint32_t stackIndex = 0; - Block stacks[16][8]; - uint32 blocksPerStack = 0; - // GTSL::Mutex stacksMutexes[32]; - // BE::SystemAllocatorReference allocatorReference; - -#if BE_DEBUG - uint64 blockMisses{ 0 }; - std::unordered_map perNameData; - //GTSL::Mutex debugDataMutex; - - uint64 bytesAllocated{ 0 }; - uint64 bytesDeallocated{ 0 }; - - uint64 totalAllocatorAllocatedBytes{ 0 }; - uint64 totalAllocatorDeallocatedBytes{ 0 }; - - uint64 allocationsCount{ 0 }; - uint64 deallocationsCount{ 0 }; - - uint64 allocatorAllocationsCount{ 0 }; - uint64 allocatorDeallocationsCount{ 0 }; - - uint64 allocatorAllocatedBytes{ 0 }; - uint64 allocatorDeallocatedBytes{ 0 }; - - uint64 totalBytesAllocated{ 0 }; - uint64 totalBytesDeallocated{ 0 }; - - uint64 totalAllocationsCount{ 0 }; - uint64 totalDeallocationsCount{ 0 }; - - uint64 totalAllocatorAllocationsCount{ 0 }; - uint64 totalAllocatorDeallocationsCount{ 0 }; -#endif - - uint8 MAX_STACKS{ 8 }; -}; \ No newline at end of file diff --git a/src/ByteEngine/Application/SystemAllocator.cpp b/src/ByteEngine/Application/SystemAllocator.cpp deleted file mode 100644 index 1d45052e..00000000 --- a/src/ByteEngine/Application/SystemAllocator.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "SystemAllocator.h" - -#include -#include - -void SystemAllocator::Allocate(const uint64 size, const uint64 alignment, void** data) -{ - const uint64 allocated_size{ GTSL::Math::RoundUpByPowerOf2(size, alignment) }; - - //allocatorMutex.Lock(); - GTSL::Allocate(allocated_size, data); - //allocatorMutex.Unlock(); - - //*data = GTSL::AlignPointer(alignment, data); - - //BE_DEBUG_ONLY(GTSL::Lock lock(debugDataMutex)) - BE_DEBUG_ONLY(allocatedBytes += allocated_size) - BE_DEBUG_ONLY(totalAllocatedBytes += allocated_size) - BE_DEBUG_ONLY(++allocationCount) - BE_DEBUG_ONLY(++totalAllocationCount) -} - -void SystemAllocator::Deallocate(const uint64 size, const uint64 alignment, void* data) -{ - const uint64 allocation_size{GTSL::Math::RoundUpByPowerOf2(size, alignment)}; - - //byte* dealigned_pointer = static_cast(data) - (allocation_size - size); - byte* dealigned_pointer = static_cast(data); - - //allocatorMutex.Lock(); - GTSL::Deallocate(allocation_size, dealigned_pointer); - //allocatorMutex.Unlock(); - - //BE_DEBUG_ONLY(GTSL::Lock lock(debugDataMutex)) - BE_DEBUG_ONLY(deallocatedBytes += allocation_size) - BE_DEBUG_ONLY(totalDeallocatedBytes += allocation_size) - BE_DEBUG_ONLY(++deallocationCount) - BE_DEBUG_ONLY(++totalDeallocationCount) -} diff --git a/src/ByteEngine/Application/SystemAllocator.h b/src/ByteEngine/Application/SystemAllocator.h deleted file mode 100644 index 54636dce..00000000 --- a/src/ByteEngine/Application/SystemAllocator.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" -#include - -/** - * \brief Allocates memory directly from the OS. Useful for all other allocators. - */ -class SystemAllocator -{ -public: - struct DebugData - { - uint64 AllocatedBytes{ 0 }; - uint64 DeallocatedBytes{ 0 }; - uint64 TotalAllocatedBytes{ 0 }; - uint64 TotalDeallocatedBytes{ 0 }; - uint64 AllocationCount{ 0 }; - uint64 TotalAllocationCount{ 0 }; - uint64 DeallocationCount{ 0 }; - uint64 TotalDeallocationCount{ 0 }; - }; -protected: - // GTSL::Mutex allocatorMutex; - -#if BE_DEBUG - // GTSL::Mutex debugDataMutex; - uint64 allocatedBytes{ 0 }; - uint64 deallocatedBytes{ 0 }; - uint64 totalAllocatedBytes{ 0 }; - uint64 totalDeallocatedBytes{ 0 }; - uint64 allocationCount{ 0 }; - uint64 deallocationCount{ 0 }; - uint64 totalAllocationCount{ 0 }; - uint64 totalDeallocationCount{ 0 }; -#endif - -public: - SystemAllocator() = default; - -#if BE_DEBUG - void GetDebugData(DebugData& debugData) - { - // GTSL::Lock lock(debugDataMutex); - debugData.AllocationCount = allocationCount; - debugData.AllocatedBytes = allocatedBytes; - debugData.DeallocatedBytes = deallocatedBytes; - debugData.TotalAllocatedBytes = totalAllocatedBytes; - debugData.TotalDeallocatedBytes = totalDeallocatedBytes; - debugData.TotalAllocationCount = totalAllocationCount; - - allocationCount = 0; - allocatedBytes = 0; - deallocatedBytes = 0; - } -#endif - - void Allocate(const uint64 size, const uint64 alignment, void** data); - - void Deallocate(const uint64 size, const uint64 alignment, void* data); -}; diff --git a/src/ByteEngine/Application/Templates/GameApplication.cpp b/src/ByteEngine/Application/Templates/GameApplication.cpp deleted file mode 100644 index ef811384..00000000 --- a/src/ByteEngine/Application/Templates/GameApplication.cpp +++ /dev/null @@ -1,334 +0,0 @@ -#include "GameApplication.h" - -#include "ByteEngine/Application/InputManager.h" -#include "ByteEngine/Application/WindowSystem.hpp" -#include "ByteEngine/Debug/FunctionTimer.h" -#include "ByteEngine/Game/CameraSystem.h" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Physics/PhysicsWorld.h" -#include "ByteEngine/Game/WorldSystem.hpp" -#include "ByteEngine/Render/LightsRenderGroup.h" -#include "ByteEngine/Render/RenderOrchestrator.h" -#include "ByteEngine/Render/StaticMeshSystem.h" -#include "ByteEngine/Network/ConnectionHandler.hpp" -#include "ByteEngine/Application/ScriptingSystem.hpp" - -#include "ByteEngine/Render/RenderSystem.h" -#include "ByteEngine/Render/WorldRenderPipeline.hpp" -#include "ByteEngine/Render/UIManager.h" - -#include "ByteEngine/Resources/ShaderResourceManager.h" -#include "ByteEngine/Resources/PipelineCacheResourceManager.h" -#include "ByteEngine/Resources/StaticMeshResourceManager.h" -#include "ByteEngine/Resources/TextureResourceManager.h" -#include "ByteEngine/Resources/AudioResourceManager.h" -#include "ByteEngine/Resources/FontResourceManager.h" -#include "ByteEngine/Resources/CurvesResourceManager.hpp" - -#include "ByteEngine/Sound/AudioSystem.h" - -#include - -class RenderOrchestrator; - -bool GameApplication::initialize() -{ - if(!Application::initialize()) { return false; } - - SetupInputSources(); - - applicationManager->AddSystem(u8"StaticMeshResourceManager"); - applicationManager->AddSystem(u8"TextureResourceManager"); - applicationManager->AddSystem(u8"ShaderResourceManager"); - applicationManager->AddSystem(u8"AudioResourceManager"); - applicationManager->AddSystem(u8"PipelineCacheResourceManager"); - applicationManager->AddSystem(u8"FontResourceManager"); - - //FRAME START - applicationManager->AddStage(u8"FrameStart"); - - //GAMEPLAY CODE BEGINS - applicationManager->AddStage(u8"GameplayStart"); - //GAMEPLAY CODE ENDS - applicationManager->AddStage(u8"GameplayEnd"); - - applicationManager->AddStage(u8"PostGameplay"); - applicationManager->AddStage(u8"PreRenderSetup"); - - //RENDER CODE BEGINS - applicationManager->AddStage(u8"RenderSetup"); - //RENDER IS DISPATCHED - applicationManager->AddStage(u8"Render"); - - //FRAME ENDS - applicationManager->AddStage(u8"FrameEnd"); - - applicationManager->AddEvent(u8"Application", EventHandle(u8"OnFocusGain")); - applicationManager->AddEvent(u8"Application", EventHandle(u8"OnFocusLoss")); - applicationManager->AddEvent(u8"Application", EventHandle(u8"OnWindowResize")); - - auto* windowSystem = applicationManager->AddSystem(u8"WindowSystem"); - - { - bool fullscreen = GetBoolOption(u8"fullScreen"); - GTSL::Extent2D screenSize; - - if(fullscreen) { - screenSize = GTSL::Extent2D(1920, 1080); - } else { - screenSize = GetExtent2DOption(u8"resolution"); - } - - windowHandle = windowSystem->CreateWindow(u8"main", u8"Sandbox", screenSize); - } - - auto* renderSystem = applicationManager->AddSystem(u8"RenderSystem"); - auto* renderOrchestrator = applicationManager->AddSystem(u8"RenderOrchestrator"); - - applicationManager->AddSystem(u8"StaticMeshSystem"); - applicationManager->AddSystem(u8"WorldRendererPipeline"); - - applicationManager->AddSystem(u8"PhysicsWorld"); - applicationManager->AddSystem(u8"AudioSystem"); - - applicationManager->AddSystem(u8"CameraSystem"); - - applicationManager->AddSystem(u8"LightsRenderGroup"); - - windowSystemHandle = applicationManager->GetSystemReference(u8"WindowSystem"); - - windowSystem->keyboard = keyboard; windowSystem->mouse = mouse; - - auto* uiManager = applicationManager->AddSystem(u8"UIManager"); - - applicationManager->AddSystem(u8"UIRenderManager"); - - applicationManager->AddSystem(u8"WorldSystem"); - - applicationManager->AddSystem(u8"ScriptingSystem"); - - return true; -} - -void GameApplication::OnUpdate(const OnUpdateInfo& updateInfo) -{ - Application::OnUpdate(updateInfo); - - auto* windowSystem = applicationManager->GetSystem(windowSystemHandle); - - windowSystem->Update(); - - mouseCount = 0; - - auto gamePadUpdate = [&](GTSL::Gamepad::SourceNames source, GTSL::Gamepad::Side side, const void* value) { - switch (source) { - case GTSL::Gamepad::SourceNames::TRIGGER: { - const auto state = *static_cast(value); - - switch (side) { - case GTSL::Gamepad::Side::RIGHT: { - GetInputManager()->RecordInputSource(controller, u8"RightTrigger", state); - - break; - } - case GTSL::Gamepad::Side::LEFT: { - GetInputManager()->RecordInputSource(controller, u8"LeftTrigger", state); - - break; - } - default: break; - } - - break; - } - case GTSL::Gamepad::SourceNames::SHOULDER: { - auto state = *static_cast(value); - switch (side) { - case GTSL::Gamepad::Side::RIGHT: GetInputManager()->RecordInputSource(controller, u8"RightHatButton", state); break; - case GTSL::Gamepad::Side::LEFT: GetInputManager()->RecordInputSource(controller, u8"LeftHatButton", state); break; - } - break; - } - case GTSL::Gamepad::SourceNames::THUMB: { - auto state = *static_cast(value); - switch (side) { - case GTSL::Gamepad::Side::RIGHT: Get()->GetInputManager()->RecordInputSource(controller, u8"RightStick", state); break; - case GTSL::Gamepad::Side::LEFT: Get()->GetInputManager()->RecordInputSource(controller, u8"LeftStick", state); break; - } - - break; - } - case GTSL::Gamepad::SourceNames::MIDDLE_BUTTONS: { - auto state = *static_cast(value); - switch (side) { - case GTSL::Gamepad::Side::RIGHT: GetInputManager()->RecordInputSource(controller, u8"RightMenuButton", state); break; - case GTSL::Gamepad::Side::LEFT: GetInputManager()->RecordInputSource(controller, u8"LeftMenuButton", state); break; - } - break; - } - case GTSL::Gamepad::SourceNames::DPAD: { - auto state = *static_cast(value); - switch (side) { - case GTSL::Gamepad::Side::UP: GetInputManager()->RecordInputSource(controller, u8"TopDPadButton", state); break; - case GTSL::Gamepad::Side::RIGHT: GetInputManager()->RecordInputSource(controller, u8"RightDPadButton", state); break; - case GTSL::Gamepad::Side::DOWN: GetInputManager()->RecordInputSource(controller, u8"BottomDPadButton", state); break; - case GTSL::Gamepad::Side::LEFT: GetInputManager()->RecordInputSource(controller, u8"LeftDPadButton", state); break; - } - break; - } - case GTSL::Gamepad::SourceNames::FACE_BUTTONS: { - auto state = *static_cast(value); - switch (side) { - case GTSL::Gamepad::Side::UP: GetInputManager()->RecordInputSource(controller, u8"TopFrontButton", state); break; - case GTSL::Gamepad::Side::RIGHT: GetInputManager()->RecordInputSource(controller, u8"RightFrontButton", state); break; - case GTSL::Gamepad::Side::DOWN: GetInputManager()->RecordInputSource(controller, u8"BottomFrontButton", state); break; - case GTSL::Gamepad::Side::LEFT: GetInputManager()->RecordInputSource(controller, u8"LeftFrontButton", state); break; - } - - break; - } - case GTSL::Gamepad::SourceNames::THUMB_BUTTONS: { - auto state = *static_cast(value); - switch (side) { - case GTSL::Gamepad::Side::RIGHT: GetInputManager()->RecordInputSource(controller, u8"RightStickButton", state); break; - case GTSL::Gamepad::Side::LEFT: GetInputManager()->RecordInputSource(controller, u8"LeftStickButton", state); break; - } - break; - } - } - }; - - GTSL::Gamepad::Update(gamepad, gamePadUpdate, 0); - - { - auto lowEndVibration = inputManagerInstance->GetInputDeviceParameter(controller, u8"LowEndVibration"); - auto highEndVibration = inputManagerInstance->GetInputDeviceParameter(controller, u8"HighEndVibration"); - //gamepad.SetVibration(lowEndVibration, highEndVibration); - } -} - -void GameApplication::shutdown() -{ - Application::shutdown(); -} - -void GameApplication::SetupInputSources() { - RegisterMouse(); - RegisterKeyboard(); - RegisterControllers(); -} - -void GameApplication::RegisterMouse() { - mouse = inputManagerInstance->RegisterInputDevice(u8"Mouse"); - - inputManagerInstance->RegisterInputSource(mouse, u8"MouseMove", InputManager::Type::VECTOR2D); - inputManagerInstance->RegisterInputSource(mouse, u8"LeftMouseButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(mouse, u8"RightMouseButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(mouse, u8"MiddleMouseButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(mouse, u8"MouseWheel", InputManager::Type::LINEAR); -} - -void GameApplication::RegisterKeyboard() -{ - keyboard = inputManagerInstance->RegisterInputDevice(u8"Keyboard"); - - auto keys = GTSL::StaticVector, 128>{ u8"Q_Key", u8"W_Key", u8"E_Key", u8"R_Key", u8"T_Key", u8"Y_Key", u8"U_Key", u8"I_Key", u8"O_Key", u8"P_Key", - u8"A_Key", u8"S_Key", u8"D_Key", u8"F_Key", u8"G_Key", u8"H_Key", u8"J_Key", u8"K_Key", u8"L_Key", - u8"Z_Key", u8"X_Key", u8"C_Key", u8"V_Key", u8"B_Key", u8"N_Key", u8"M_Key", - u8"0_Key", u8"1_Key", u8"2_Key", u8"3_Key", u8"4_Key", u8"5_Key", u8"6_Key", u8"7_Key", u8"8_Key", u8"9_Key", - u8"Backspace_Key", u8"Enter_Key", u8"Supr_Key", u8"Tab_Key", u8"CapsLock_Key", u8"Esc_Key", u8"SpaceBar_Key", - u8"LeftShift_Key", u8"RightShift_Key", u8"LeftControl_Key", u8"RightControl_Key", u8"LeftAlt_Key", u8"RightAlt_Key", - u8"UpArrow_Key", u8"RightArrow_Key", u8"DownArrow_Key", u8"LeftArrow_Key", - u8"Numpad0_Key", u8"Numpad1_Key", u8"Numpad2_Key", u8"Numpad3_Key", u8"Numpad4_Key", u8"Numpad5_Key", u8"Numpad6_Key", u8"Numpad7_Key", u8"Numpad8_Key", u8"Numpad9_Key", - u8"F1_Key", u8"F2_Key", u8"F3_Key", u8"F4_Key", u8"F5_Key", u8"F6_Key", u8"F7_Key", u8"F8_Key", u8"F9_Key", u8"F10_Key", u8"F11_Key", u8"F12_Key" }; - - GTSL::StaticVector views; - - for(auto& e : keys) { - views.EmplaceBack(e); - } - - inputManagerInstance->RegisterInputSources(keyboard, views, InputManager::Type::BOOL); -} - -void GameApplication::RegisterControllers() -{ - controller = inputManagerInstance->RegisterInputDevice(u8"Controller"); - - inputManagerInstance->RegisterInputDeviceParameter(controller, u8"LowEndVibration"); - inputManagerInstance->RegisterInputDeviceParameter(controller, u8"HighEndVibration"); - - inputManagerInstance->RegisterInputSource(controller, u8"LeftStick", InputManager::Type::VECTOR2D); - inputManagerInstance->RegisterInputSource(controller, u8"RightStick", InputManager::Type::VECTOR2D); - - inputManagerInstance->RegisterInputSource(controller, u8"LeftTrigger", InputManager::Type::LINEAR); - inputManagerInstance->RegisterInputSource(controller, u8"RightTrigger", InputManager::Type::LINEAR); - - inputManagerInstance->RegisterInputSource(controller, u8"TopFrontButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"RightFrontButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"BottomFrontButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"LeftFrontButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"TopDPadButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"RightDPadButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"BottomDPadButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"LeftDPadButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"LeftStickButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"RightStickButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"LeftMenuButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"RightMenuButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"LeftHatButton", InputManager::Type::BOOL); - inputManagerInstance->RegisterInputSource(controller, u8"RightHatButton", InputManager::Type::BOOL); -} - -void GameApplication::keyboardEvent(const GTSL::Window::KeyboardKeys key, const bool state, bool isFirstkeyOfType) { - GTSL::StaticString<64> id; - - switch (key) { - case GTSL::Window::KeyboardKeys::Q: id = u8"Q_Key"; break; case GTSL::Window::KeyboardKeys::W: id = u8"W_Key"; break; - case GTSL::Window::KeyboardKeys::E: id = u8"E_Key"; break; case GTSL::Window::KeyboardKeys::R: id = u8"R_Key"; break; - case GTSL::Window::KeyboardKeys::T: id = u8"T_Key"; break; case GTSL::Window::KeyboardKeys::Y: id = u8"Y_Key"; break; - case GTSL::Window::KeyboardKeys::U: id = u8"U_Key"; break; case GTSL::Window::KeyboardKeys::I: id = u8"I_Key"; break; - case GTSL::Window::KeyboardKeys::O: id = u8"O_Key"; break; case GTSL::Window::KeyboardKeys::P: id = u8"P_Key"; break; - case GTSL::Window::KeyboardKeys::A: id = u8"A_Key"; break; case GTSL::Window::KeyboardKeys::S: id = u8"S_Key"; break; - case GTSL::Window::KeyboardKeys::D: id = u8"D_Key"; break; case GTSL::Window::KeyboardKeys::F: id = u8"F_Key"; break; - case GTSL::Window::KeyboardKeys::G: id = u8"G_Key"; break; case GTSL::Window::KeyboardKeys::H: id = u8"H_Key"; break; - case GTSL::Window::KeyboardKeys::J: id = u8"J_Key"; break; case GTSL::Window::KeyboardKeys::K: id = u8"K_Key"; break; - case GTSL::Window::KeyboardKeys::L: id = u8"L_Key"; break; case GTSL::Window::KeyboardKeys::Z: id = u8"Z_Key"; break; - case GTSL::Window::KeyboardKeys::X: id = u8"X_Key"; break; case GTSL::Window::KeyboardKeys::C: id = u8"C_Key"; break; - case GTSL::Window::KeyboardKeys::V: id = u8"V_Key"; break; case GTSL::Window::KeyboardKeys::B: id = u8"B_Key"; break; - case GTSL::Window::KeyboardKeys::N: id = u8"N_Key"; break; case GTSL::Window::KeyboardKeys::M: id = u8"M_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_0: id = u8"0_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_1: id = u8"1_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_2: id = u8"2_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_3: id = u8"3_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_4: id = u8"4_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_5: id = u8"5_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_6: id = u8"6_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_7: id = u8"7_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_8: id = u8"8_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_9: id = u8"9_Key"; break; - case GTSL::Window::KeyboardKeys::BACKSPACE: id = u8"Backspace_Key"; break; - case GTSL::Window::KeyboardKeys::ENTER: id = u8"Enter_Key"; break; - case GTSL::Window::KeyboardKeys::DELETE: id = u8"Supr_Key"; break; - case GTSL::Window::KeyboardKeys::TAB: id = u8"Tab_Key"; break; - case GTSL::Window::KeyboardKeys::CAPS_LOCK: id = u8"CapsLock_Key"; break; - case GTSL::Window::KeyboardKeys::ESCAPE: id = u8"Esc_Key"; break; - case GTSL::Window::KeyboardKeys::RIGHT_SHIFT: id = u8"RightShift_Key"; break; case GTSL::Window::KeyboardKeys::LEFT_SHIFT: id = u8"LeftShift_Key"; break; - case GTSL::Window::KeyboardKeys::RIGHT_CONTROL: id = u8"RightControl_Key"; break; case GTSL::Window::KeyboardKeys::LEFT_CONTROL: id = u8"LeftControl_Key"; break; - case GTSL::Window::KeyboardKeys::LEFT_ALT: id = u8"LeftAlt_Key"; break; case GTSL::Window::KeyboardKeys::RIGHT_ALT: id = u8"RightAlt_Key"; break; - case GTSL::Window::KeyboardKeys::UP: id = u8"Up_Key"; break; case GTSL::Window::KeyboardKeys::RIGHT: id = u8"Right_Key"; break; - case GTSL::Window::KeyboardKeys::DOWN: id = u8"Down_Key"; break; case GTSL::Window::KeyboardKeys::LEFT: id = u8"Left_Key"; break; - case GTSL::Window::KeyboardKeys::SPACE_BAR: id = u8"SpaceBar_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_0: id = u8"Numpad0_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_1: id = u8"Numpad1_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_2: id = u8"Numpad2_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_3: id = u8"Numpad3_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_4: id = u8"Numpad4_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_5: id = u8"Numpad5_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_6: id = u8"Numpad6_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_7: id = u8"Numpad7_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_8: id = u8"Numpad8_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_9: id = u8"Numpad9_Key"; break; - case GTSL::Window::KeyboardKeys::F1: id = u8"F1_Key"; break; case GTSL::Window::KeyboardKeys::F2: id = u8"F2_Key"; break; - case GTSL::Window::KeyboardKeys::F3: id = u8"F3_Key"; break; case GTSL::Window::KeyboardKeys::F4: id = u8"F4_Key"; break; - case GTSL::Window::KeyboardKeys::F5: id = u8"F5_Key"; break; case GTSL::Window::KeyboardKeys::F6: id = u8"F6_Key"; break; - case GTSL::Window::KeyboardKeys::F7: id = u8"F7_Key"; break; case GTSL::Window::KeyboardKeys::F8: id = u8"F8_Key"; break; - case GTSL::Window::KeyboardKeys::F9: id = u8"F9_Key"; break; case GTSL::Window::KeyboardKeys::F10: id = u8"F10_Key"; break; - case GTSL::Window::KeyboardKeys::F11: id = u8"F11_Key"; break; case GTSL::Window::KeyboardKeys::F12: id = u8"F12_Key"; break; - default: break; - } - - if (isFirstkeyOfType) { - GetInputManager()->RecordInputSource(keyboard, id, state); - } -} diff --git a/src/ByteEngine/Application/Templates/GameApplication.h b/src/ByteEngine/Application/Templates/GameApplication.h deleted file mode 100644 index a58cd347..00000000 --- a/src/ByteEngine/Application/Templates/GameApplication.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "ByteEngine/Application/Application.h" - -#include -#include - -#include "ByteEngine/Application/InputManager.h" -#include "ByteEngine/Application/WindowSystem.hpp" -#include "ByteEngine/Game/ApplicationManager.h" - -class GameApplication : public BE::Application { -public: - GameApplication(GTSL::ShortString<128> name) : Application(name) - { - } - - ~GameApplication() = default; - - bool initialize() override; - void OnUpdate(const OnUpdateInfo& updateInfo) override; - void shutdown() override; - - auto GetWindowHandle() const { return windowHandle; } - -protected: - GTSL::Gamepad gamepad; - InputDeviceHandle controller; - InputDeviceHandle keyboard; - InputDeviceHandle mouse; - - WindowSystem::WindowHandle windowHandle; - - SystemHandle windowSystemHandle; - - uint32 mouseCount = 0; - - void SetupInputSources(); - void RegisterMouse(); - void RegisterKeyboard(); - void RegisterControllers(); - - void keyboardEvent(const GTSL::Window::KeyboardKeys key, const bool state, bool isFirstkeyOfType); -}; diff --git a/src/ByteEngine/Application/ThreadPool.h b/src/ByteEngine/Application/ThreadPool.h deleted file mode 100644 index d8ca6393..00000000 --- a/src/ByteEngine/Application/ThreadPool.h +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" -#include "ByteEngine/Object.h" - -#include "ByteEngine/Debug/Logger.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -//https://github.com/mvorbrodt/blog - -class ThreadPool : public Object -{ - using TaskDelegate = GTSL::Delegate; - struct Task { - TaskDelegate Delegate; - byte* taskInfo; - - Task(const BE::PAR& a) {} - Task(TaskDelegate del, byte* task_info) : Delegate(del), taskInfo(task_info) {} - }; -public: - explicit ThreadPool(const uint8 tCount) : Object(u8"Thread Pool"), threadCount(tCount) - { - //lambda - auto workers_loop = [](ThreadPool* pool, const uint8 i) { - while (true) { - Task task(pool->GetPersistentAllocator()); - - for (auto n = 0; n < pool->threadCount * K; ++n) { - auto queueIndex = (i + n) % pool->threadCount; - - if (pool->queues[queueIndex].TryPop(task)) { - task.Delegate(pool, task.taskInfo); - pool->queues[queueIndex].Done(); - break; - } - } - - //if (!GTSL::Get(task) && !pool->queues[i].Pop(task)) { break; } - if (pool->queues[i].Pop(task)) { - task.Delegate(pool, task.taskInfo); - pool->queues[i].Done(); - } else { - break; - } - } - }; - - for (uint8 i = 0; i < threadCount; ++i) { - //Constructing threads with function and I parameter. i + 1 is because we leave id 0 to the main thread - threads.EmplaceBack(GetPersistentAllocator(), i + 1, GTSL::Delegate::Create(workers_loop), this, i); - threads[i].SetPriority(GTSL::Thread::Priority::HIGH); - } - } - - ThreadPool(const ThreadPool&) = delete; - - ~ThreadPool() { - for (uint32 i = 0; i < threadCount; ++i) { queues[i].End(); } - for (uint32 i = 0; i < threadCount; ++i) { threads[i].Join(GetPersistentAllocator()); } - } - - template - void EnqueueTask(const GTSL::Delegate& task, ARGS&&... args) { - const auto currentIndex = index++; - - TaskInfo* taskInfoAlloc = GTSL::New>(GetPersistentAllocator(), currentIndex, task, GTSL::ForwardRef(args)...); - - auto work = [](ThreadPool* threadPool, byte* voidTask) -> void { - TaskInfo* taskInfo = reinterpret_cast*>(voidTask); - - BE_ASSERT(taskInfo->TimesRun == 0, "") - - ++taskInfo->TimesRun; - - GTSL::Call(taskInfo->Delegate, GTSL::MoveRef(taskInfo->Arguments)); - - GTSL::Delete>(&taskInfo, threadPool->GetPersistentAllocator()); - }; - - for (auto n = 0; n < threadCount * K; ++n) { - //Try to Push work into queues, if success return else when Done looping place into some queue. - - if (queues[(currentIndex + n) % threadCount].TryPush(TaskDelegate::Create(work), reinterpret_cast(taskInfoAlloc))) { return; } - } - - queues[currentIndex % threadCount].Push(TaskDelegate::Create(work), reinterpret_cast(taskInfoAlloc)); - } - - uint8 GetNumberOfThreads() { return threadCount; } - -private: - const uint8 threadCount = 0; - GTSL::Atomic index{ 0 }, runTasks{ 0 }; - - std::array, 32> queues; - GTSL::StaticVector threads; - - template - struct TaskInfo - { - TaskInfo(uint32 i, const GTSL::Delegate& delegate, GTSL::Tuple&& args) : Delegate(delegate), Arguments(GTSL::MoveRef(args)), Index(i) - { - } - - TaskInfo(uint32 i, const GTSL::Delegate& delegate, ARGS&&... args) : Delegate(delegate), Arguments(GTSL::ForwardRef(args)...), Index(i) - { - } - - GTSL::Delegate Delegate; - GTSL::Tuple Arguments; - uint32 Index = 0; - uint32 TimesRun = 0; - }; - /** - * \brief Number of times to loop around the queues to find one that is free. - */ - inline static constexpr uint8 K{ 2 }; -}; \ No newline at end of file diff --git a/src/ByteEngine/Application/WindowSystem.hpp b/src/ByteEngine/Application/WindowSystem.hpp deleted file mode 100644 index 80f1a0d1..00000000 --- a/src/ByteEngine/Application/WindowSystem.hpp +++ /dev/null @@ -1,186 +0,0 @@ -#pragma once - -#include "Application.h" -#include "ByteEngine/Core.h" - -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Application/InputManager.h" - -class WindowSystem : public BE::System { -public: - WindowSystem(const InitializeInfo& initialize_info) : BE::System(initialize_info, u8"WindowSystem"), WindowTypeIndentifier(initialize_info.AppManager->RegisterType(this, u8"Window")), OnWindowResizeEventHandle(u8"OnWindowResize") { - } - - DECLARE_BE_TYPE(Window); - - DECLARE_BE_EVENT(OnWindowResize, WindowHandle, GTSL::Extent2D); - -#undef CreateWindow - - WindowHandle CreateWindow(const GTSL::StringView id_name, const GTSL::StringView display_name, const GTSL::Extent2D window_extent) { - uint32 index = windows.GetLength(); - auto& window = windows.EmplaceBack(); - -#if BE_PLATFORM_WINDOWS - GTSL::Window::API windowAPI = GTSL::Window::API::WIN32; -#elif BE_PLATFORM_LINUX - GTSL::Window::API windowAPI = GTSL::Window::API::XCB; -#endif - - window.window.BindToOS(id_name, display_name, windowAPI, window_extent, this, GTSL::Delegate::Create(this), nullptr); - - window.window.AddDevice(GTSL::Window::DeviceType::MOUSE); - window.window.AddDevice(GTSL::Window::DeviceType::GAMEPAD); - - window.window.SetWindowVisibility(true); - - return GetApplicationManager()->MakeHandle(WindowTypeIndentifier, index); - } - - GTSL::Vector2 GetWindowPosition(const WindowHandle window_handle) const { - return windows[window_handle()].position; - } - - GTSL::Extent2D GetWindowClientExtent(const WindowHandle window_handle) const { - return windows[window_handle()].window.GetFramebufferExtent(); - } - - - const GTSL::Window& GetWindow(const WindowHandle window_handle) const { - return windows[window_handle()].window; - } - - void Update() { - for(auto& window : windows) { - window.window.Update(this, GTSL::Delegate::Create(this)); - } - } - - InputDeviceHandle keyboard, mouse; -private: - struct WindowData { - GTSL::Window window; - GTSL::Vector2 position; - WindowHandle windowHandle; - }; - GTSL::StaticVector windows; - - void windowUpdateFunction(GTSL::Window* window, void* userData, GTSL::Window::WindowEvents event, void* eventData) { - auto* app = static_cast(userData); - - auto* inputManager = BE::Application::Get()->GetInputManager(); - - switch (event) { - case GTSL::Window::WindowEvents::FOCUS: { - auto* focusEventData = static_cast(eventData); - if(focusEventData->hasFocus) { - //app->GetApplicationManager()->DispatchEvent(u8"Application", EventHandle(u8"OnFocusGain"), GTSL::MoveRef(focusEventData->HadFocus)); - } else { - //app->GetApplicationManager()->DispatchEvent(u8"Application", EventHandle(u8"OnFocusLoss"), GTSL::MoveRef(focusEventData->HadFocus)); - } - break; - } - case GTSL::Window::WindowEvents::CLOSE: BE::Application::Get()->Close(BE::Application::CloseMode::OK, u8"User closed window."); break; - case GTSL::Window::WindowEvents::KEYBOARD_KEY: { - auto* keyboardEventData = static_cast(eventData); - - auto keyboardEvent = [&](const GTSL::Window::KeyboardKeys key, const bool state, bool isFirstkeyOfType) { - GTSL::StaticString<64> id; - - switch (key) { - case GTSL::Window::KeyboardKeys::Q: id = u8"Q_Key"; break; case GTSL::Window::KeyboardKeys::W: id = u8"W_Key"; break; - case GTSL::Window::KeyboardKeys::E: id = u8"E_Key"; break; case GTSL::Window::KeyboardKeys::R: id = u8"R_Key"; break; - case GTSL::Window::KeyboardKeys::T: id = u8"T_Key"; break; case GTSL::Window::KeyboardKeys::Y: id = u8"Y_Key"; break; - case GTSL::Window::KeyboardKeys::U: id = u8"U_Key"; break; case GTSL::Window::KeyboardKeys::I: id = u8"I_Key"; break; - case GTSL::Window::KeyboardKeys::O: id = u8"O_Key"; break; case GTSL::Window::KeyboardKeys::P: id = u8"P_Key"; break; - case GTSL::Window::KeyboardKeys::A: id = u8"A_Key"; break; case GTSL::Window::KeyboardKeys::S: id = u8"S_Key"; break; - case GTSL::Window::KeyboardKeys::D: id = u8"D_Key"; break; case GTSL::Window::KeyboardKeys::F: id = u8"F_Key"; break; - case GTSL::Window::KeyboardKeys::G: id = u8"G_Key"; break; case GTSL::Window::KeyboardKeys::H: id = u8"H_Key"; break; - case GTSL::Window::KeyboardKeys::J: id = u8"J_Key"; break; case GTSL::Window::KeyboardKeys::K: id = u8"K_Key"; break; - case GTSL::Window::KeyboardKeys::L: id = u8"L_Key"; break; case GTSL::Window::KeyboardKeys::Z: id = u8"Z_Key"; break; - case GTSL::Window::KeyboardKeys::X: id = u8"X_Key"; break; case GTSL::Window::KeyboardKeys::C: id = u8"C_Key"; break; - case GTSL::Window::KeyboardKeys::V: id = u8"V_Key"; break; case GTSL::Window::KeyboardKeys::B: id = u8"B_Key"; break; - case GTSL::Window::KeyboardKeys::N: id = u8"N_Key"; break; case GTSL::Window::KeyboardKeys::M: id = u8"M_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_0: id = u8"0_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_1: id = u8"1_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_2: id = u8"2_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_3: id = u8"3_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_4: id = u8"4_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_5: id = u8"5_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_6: id = u8"6_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_7: id = u8"7_Key"; break; - case GTSL::Window::KeyboardKeys::KEYBOARD_8: id = u8"8_Key"; break; case GTSL::Window::KeyboardKeys::KEYBOARD_9: id = u8"9_Key"; break; - case GTSL::Window::KeyboardKeys::BACKSPACE: id = u8"Backspace_Key"; break; - case GTSL::Window::KeyboardKeys::ENTER: id = u8"Enter_Key"; break; - case GTSL::Window::KeyboardKeys::DELETE: id = u8"Supr_Key"; break; - case GTSL::Window::KeyboardKeys::TAB: id = u8"Tab_Key"; break; - case GTSL::Window::KeyboardKeys::CAPS_LOCK: id = u8"CapsLock_Key"; break; - case GTSL::Window::KeyboardKeys::ESCAPE: id = u8"Esc_Key"; break; - case GTSL::Window::KeyboardKeys::RIGHT_SHIFT: id = u8"RightShift_Key"; break; case GTSL::Window::KeyboardKeys::LEFT_SHIFT: id = u8"LeftShift_Key"; break; - case GTSL::Window::KeyboardKeys::RIGHT_CONTROL: id = u8"RightControl_Key"; break; case GTSL::Window::KeyboardKeys::LEFT_CONTROL: id = u8"LeftControl_Key"; break; - case GTSL::Window::KeyboardKeys::LEFT_ALT: id = u8"LeftAlt_Key"; break; case GTSL::Window::KeyboardKeys::RIGHT_ALT: id = u8"RightAlt_Key"; break; - case GTSL::Window::KeyboardKeys::UP: id = u8"Up_Key"; break; case GTSL::Window::KeyboardKeys::RIGHT: id = u8"Right_Key"; break; - case GTSL::Window::KeyboardKeys::DOWN: id = u8"Down_Key"; break; case GTSL::Window::KeyboardKeys::LEFT: id = u8"Left_Key"; break; - case GTSL::Window::KeyboardKeys::SPACE_BAR: id = u8"SpaceBar_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_0: id = u8"Numpad0_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_1: id = u8"Numpad1_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_2: id = u8"Numpad2_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_3: id = u8"Numpad3_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_4: id = u8"Numpad4_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_5: id = u8"Numpad5_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_6: id = u8"Numpad6_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_7: id = u8"Numpad7_Key"; break; - case GTSL::Window::KeyboardKeys::NUMPAD_8: id = u8"Numpad8_Key"; break; case GTSL::Window::KeyboardKeys::NUMPAD_9: id = u8"Numpad9_Key"; break; - case GTSL::Window::KeyboardKeys::F1: id = u8"F1_Key"; break; case GTSL::Window::KeyboardKeys::F2: id = u8"F2_Key"; break; - case GTSL::Window::KeyboardKeys::F3: id = u8"F3_Key"; break; case GTSL::Window::KeyboardKeys::F4: id = u8"F4_Key"; break; - case GTSL::Window::KeyboardKeys::F5: id = u8"F5_Key"; break; case GTSL::Window::KeyboardKeys::F6: id = u8"F6_Key"; break; - case GTSL::Window::KeyboardKeys::F7: id = u8"F7_Key"; break; case GTSL::Window::KeyboardKeys::F8: id = u8"F8_Key"; break; - case GTSL::Window::KeyboardKeys::F9: id = u8"F9_Key"; break; case GTSL::Window::KeyboardKeys::F10: id = u8"F10_Key"; break; - case GTSL::Window::KeyboardKeys::F11: id = u8"F11_Key"; break; case GTSL::Window::KeyboardKeys::F12: id = u8"F12_Key"; break; - default: break; - } - - if (isFirstkeyOfType) { - inputManager->RecordInputSource(keyboard, id, state); - } - }; - - keyboardEvent(keyboardEventData->key, keyboardEventData->state, keyboardEventData->isFirstTime); - break; - } - case GTSL::Window::WindowEvents::CHAR: inputManager->RecordInputSource(app->keyboard, u8"Character", static_cast(*static_cast (eventData))); break; - case GTSL::Window::WindowEvents::SIZE: { - auto* sizingEventData = static_cast(eventData); - app->GetApplicationManager()->DispatchEvent(this, GetOnWindowResizeEventHandle(), GTSL::MoveRef(app->windows[0].windowHandle), GTSL::MoveRef(*sizingEventData)); - break; - } - case GTSL::Window::WindowEvents::MOVING: { - auto* moveData = static_cast(eventData); - - windows.front().position.X() = moveData->X; - windows.front().position.Y() = moveData->Y; - - break; - } - case GTSL::Window::WindowEvents::MOUSE_MOVE: { - auto* mouseMoveEventData = static_cast(eventData); - inputManager->RecordInputSource(app->mouse, u8"MouseMove", mouseMoveEventData->absolutePosition); - break; - } - case GTSL::Window::WindowEvents::MOUSE_WHEEL: { - auto* mouseWheelEventData = static_cast(eventData); - inputManager->RecordInputSource(app->mouse, u8"MouseWheel", *mouseWheelEventData); - break; - } - case GTSL::Window::WindowEvents::MOUSE_BUTTON: { - auto* mouseButtonEventData = static_cast(eventData); - - switch (mouseButtonEventData->button) { - case GTSL::Window::MouseButtons::LEFT_BUTTON: inputManager->RecordInputSource(app->mouse, u8"LeftMouseButton", mouseButtonEventData->state); break; - case GTSL::Window::MouseButtons::RIGHT_BUTTON: inputManager->RecordInputSource(app->mouse, u8"RightMouseButton", mouseButtonEventData->state); break; - case GTSL::Window::MouseButtons::MIDDLE_BUTTON: inputManager->RecordInputSource(app->mouse, u8"MiddleMouseButton", mouseButtonEventData->state); break; - default: break; - } - - break; - } - case GTSL::Window::WindowEvents::DEVICE_CHANGE: { - BE_LOG_MESSAGE(u8"Device changed!") - break; - } - default:; - } - } -}; \ No newline at end of file diff --git a/src/ByteEngine/Core.h b/src/ByteEngine/Core.h deleted file mode 100644 index 7bf717eb..00000000 --- a/src/ByteEngine/Core.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -// TYPEDEFS - -using byte = unsigned char; -using uint8 = unsigned char; -using int8 = char; -using uint16 = unsigned short; -using int16 = short; -using uint32 = unsigned int; -using int32 = int; -using uint64 = unsigned long long; -using int64 = long long; - -using utf8 = char8_t; - -using float32 = float; -using float64 = double; - -#if BE_DEBUG -#define BE_DEBUG_ONLY(...) __VA_ARGS__; -#else -#define BE_DEBUG_ONLY(...) -#endif \ No newline at end of file diff --git a/src/ByteEngine/Debug/Assert.h b/src/ByteEngine/Debug/Assert.h deleted file mode 100644 index 07e28921..00000000 --- a/src/ByteEngine/Debug/Assert.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "ByteEngine/Debug/Logger.h" - -#if BE_PLATFORM_WINDOWS -#define BE_DEBUG_BREAK __debugbreak() -#elif BE_PLATFORM_LINUX -#include -#define BE_DEBUG_BREAK raise(SIGTRAP) -#endif - -//Assert -#if BE_DEBUG -#define BE_ASSERT(func, text) if (!(func)) [[unlikely]] { BE_DEBUG_BREAK; } -#else -#define BE_ASSERT(func, text) -#endif \ No newline at end of file diff --git a/src/ByteEngine/Debug/FunctionTimer.cpp b/src/ByteEngine/Debug/FunctionTimer.cpp deleted file mode 100644 index 89011e10..00000000 --- a/src/ByteEngine/Debug/FunctionTimer.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "FunctionTimer.h" - -#include "Logger.h" -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Application/Clock.h" - -#undef GetCurrentTime - -FunctionTimer::FunctionTimer(const GTSL::StaticString<64>& name) : StartingTime(BE::Application::Get()->GetClock()->GetCurrentMicroseconds()), Name(name) -{ -} - -FunctionTimer::~FunctionTimer() -{ - //BE::Application::Get()->GetLogger()->logFunctionTimer(this, BE::Application::Get()->GetClock()->GetCurrentMicroseconds() - StartingTime); -} diff --git a/src/ByteEngine/Debug/FunctionTimer.h b/src/ByteEngine/Debug/FunctionTimer.h deleted file mode 100644 index 9e343643..00000000 --- a/src/ByteEngine/Debug/FunctionTimer.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include - -class FunctionTimer -{ -public: - FunctionTimer(const GTSL::StaticString<64>& name); - ~FunctionTimer(); - - GTSL::Microseconds StartingTime; - GTSL::StaticString<64> Name; -}; - -#ifdef BE_DEBUG -//Places a timer which automatically starts counting. Timer will stop and print results when it exits the scope it was created in. -#define PROFILE() FunctionTimer profiler(u8 ##__FUNCTION__) -#else -#define PROFILE -#endif diff --git a/src/ByteEngine/Debug/Logger.cpp b/src/ByteEngine/Debug/Logger.cpp deleted file mode 100644 index 349abe9e..00000000 --- a/src/ByteEngine/Debug/Logger.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "Logger.h" - -#include "ByteEngine/Application/Clock.h" -#include "ByteEngine/Debug/FunctionTimer.h" -#include "ByteEngine/Application/Application.h" - -#include - -using namespace BE; - -Logger::Logger(const LoggerCreateInfo& loggerCreateInfo) : Object(u8"Logger"), logFile()//, allowedLoggers(32, GetSyste()) -{ - uint64 allocated_size{ 0 }; - GetPersistentAllocator().Allocate(defaultBufferLength, 1, reinterpret_cast(&data), &allocated_size); - - { - GTSL::StaticString<260> path(loggerCreateInfo.AbsolutePathToLogDirectory); - path += u8"/log.txt"; - switch (logFile.Open(path, GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: break; - case GTSL::File::OpenResult::CREATED: break; - case GTSL::File::OpenResult::ERROR: break; - default:; - } - } - - logFile.Resize(0); - - GTSL::Console::SetConsoleInputModeAsUTF8(); -} - -void Logger::SetTrace(bool t) { - trace = t; - - if (trace) { - GTSL::StaticString<260> path(BE::Application::Get()->GetPathToApplication()); - path += u8"/trace.txt"; - switch (graphFile.Open(path, GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: break; - case GTSL::File::OpenResult::CREATED: break; - case GTSL::File::OpenResult::ERROR: break; - default:; - } - graphFile.Resize(0); - - { - GTSL::StaticString<512> string; - - string += u8"{\"otherData\": {},\"traceEvents\":[]}"; - - graphFile.Write(GTSL::Range(string.GetBytes(), reinterpret_cast(string.c_str()))); - } - } -} - -//TODO: if string is too big clamp to nearest CODEPOINT not Byte - -void Logger::log(const VerbosityLevel verbosityLevel, const GTSL::Range text) const -{ - const auto day_of_month = Clock::GetDayOfMonth(); const auto month = Clock::GetMonth(); const auto year = Clock::GetYear(); const auto time = Clock::GetTime(); - - GTSL::StaticString string; - - string += u8"["; - ToString(string, day_of_month); string += u8"/"; - ToString(string, static_cast(month)); string += u8"/"; - ToString(string, year); string += u8"]"; - - string += u8"["; - ToString(string, time.Hour); string += u8":"; - ToString(string, time.Minute); string += u8":"; - ToString(string, time.Second); string += u8"] "; - - auto clampedSize = GTSL::Math::Limit(text.GetBytes(), string.GetCapacity() - string.GetBytes() - 1); - string += GTSL::Range(clampedSize, clampedSize, text.GetData()); - - string += u8'\n'; - - if(verbosityLevel >= minLogLevel) { - SetTextColorOnLogLevel(verbosityLevel); - GTSL::Console::Print(string); - } - - logMutex.Lock(); - logFile.Write(GTSL::Range(string.GetBytes(), reinterpret_cast(string.c_str()))); - logMutex.Unlock(); -} - -void Logger::SetTextColorOnLogLevel(const VerbosityLevel level) const { - switch (level) { - case VerbosityLevel::MESSAGE: GTSL::Console::SetTextColor(GTSL::Console::TextColor::WHITE); break; - case VerbosityLevel::SUCCESS: GTSL::Console::SetTextColor(GTSL::Console::TextColor::GREEN); break; - case VerbosityLevel::WARNING: GTSL::Console::SetTextColor(GTSL::Console::TextColor::ORANGE); break; - case VerbosityLevel::FATAL: GTSL::Console::SetTextColor(GTSL::Console::TextColor::RED); break; - default: GTSL::Console::SetTextColor(GTSL::Console::TextColor::WHITE); break; - } -} - -Logger::~Logger() -{ -} \ No newline at end of file diff --git a/src/ByteEngine/Debug/Logger.h b/src/ByteEngine/Debug/Logger.h deleted file mode 100644 index ada27fdd..00000000 --- a/src/ByteEngine/Debug/Logger.h +++ /dev/null @@ -1,163 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "ByteEngine/Core.h" -#include -#include - -#include "ByteEngine/Id.h" -#include "ByteEngine/Object.h" - -class FunctionTimer; -class Object; - -#undef ERROR - -namespace BE -{ - constexpr const utf8* FIX_OR_CRASH_STRING = u8"Fix this issue as it will lead to a crash in release mode!"; - - /** - * \brief Self locking class that manages logging to console and to disk. - * All logs get dumped to disk, verbosity levels are only for console. - */ - class Logger : public Object - { - public: - enum class VerbosityLevel : uint8 { - MESSAGE = 1, SUCCESS = 2, WARNING = 4, FATAL = 8 - }; - private: - /** - * \brief Mutex for all log operations. - */ - mutable GTSL::Mutex logMutex; - mutable GTSL::Mutex traceMutex; - - /** - * \brief Minimum level for a log to go through to console, all logs get dumped to disk. - */ - mutable VerbosityLevel minLogLevel{ VerbosityLevel::MESSAGE }; - - /** - * \brief File handle to log file where all logs are dumped to. - */ - mutable GTSL::File logFile; - mutable GTSL::File graphFile; - mutable uint64 profileCount = 0; - - static constexpr uint16 maxLogLength{ 8192 }; - - static constexpr uint32 bytesToDumpOn{ 256 }; - - /** - * \brief Default amount of characters the buffer can hold at a moment. - */ - static constexpr uint32 defaultBufferLength{ bytesToDumpOn }; - - mutable std::atomic posInBuffer{ 0 }; - - //mutable GTSL::HashMap allowedLoggers; - - mutable utf8* data{ nullptr }; - - bool trace = false; - - mutable std::atomic counter{ 0 }; - - void SetTextColorOnLogLevel(VerbosityLevel level) const; - void log(VerbosityLevel verbosityLevel, const GTSL::Range text) const; - - public: - Logger() = default; - ~Logger(); - - struct LoggerCreateInfo { - GTSL::Range AbsolutePathToLogDirectory; - }; - explicit Logger(const LoggerCreateInfo& loggerCreateInfo); - - void SetTrace(bool t); - - template - void PrintObjectLog(const Object* obj, const VerbosityLevel level, ARGS... args) { - GTSL::StaticString text; - text += obj->GetName(); text += u8": "; - (ToString(text, GTSL::ForwardRef(args)), ...); - log(level, text); - } - - template - void PrintBasicLog(const VerbosityLevel level, ARGS&& ...args) { - GTSL::StaticString text; - //(ToString(text, GTSL::ForwardRef(args)), ...); - log(level, text); - } - - /** - * \brief Sets the minimum log verbosity, only affects logs to console. Value is inclusive. - * \param level Verbosity level. - */ - void SetMinLogLevel(const VerbosityLevel level) const { - logMutex.Lock(); - minLogLevel = level; - logMutex.Unlock(); - } - - void logFunction(const GTSL::StringView name, GTSL::Microseconds startTime, GTSL::Microseconds endTime, const GTSL::StringView args) { - if (!trace) { return; } - - GTSL::StaticString<1024> string; - - { - GTSL::Lock lock(traceMutex); - - if (profileCount++ > 0) - string += u8","; - - string += u8"{"; - string += u8"\"cat\":\"function\","; - string += u8"\"dur\":"; ToString(string, (endTime - startTime).GetCount()); string += u8","; - string += u8"\"name\":\""; string += name; string += u8"\","; - string += u8"\"ph\":\"X\","; - string += u8"\"pid\":0,"; - string += u8"\"tid\":"; ToString(string, getThread()); string += u8","; - string += u8"\"ts\":"; ToString(string, startTime.GetCount()); - if (args.GetBytes()) { - string += u8','; string += u8"\"args\":{ "; string += args; string += u8"}"; - } - string += u8"}]}"; - - graphFile.SetPointer(graphFile.GetSize() - 2); - graphFile.Write(GTSL::Range(string.GetBytes(), reinterpret_cast(string.c_str()))); - } - } - - void InstantEvent(GTSL::StringView name, uint64 time) { - if (!trace) { return; } - - GTSL::StaticString<1024> string; - - { - GTSL::Lock lock(traceMutex); - - if (profileCount++ > 0) - string += u8","; - - string += u8"{"; - string += u8"\"name\":\""; string += name; string += u8"\","; - string += u8"\"ph\":\"i\","; - string += u8"\"ts\":"; ToString(string, time); string += u8","; - string += u8"\"pid\":0,"; - string += u8"\"tid\":"; ToString(string, getThread()); string += u8","; - string += u8"\"s\":\"g\""; - string += u8"}"; - - graphFile.Write(GTSL::Range(string.GetBytes(), reinterpret_cast(string.c_str()))); - } - } - }; -} \ No newline at end of file diff --git a/src/ByteEngine/Game/ApplicationManager.cpp b/src/ByteEngine/Game/ApplicationManager.cpp deleted file mode 100644 index 388bb817..00000000 --- a/src/ByteEngine/Game/ApplicationManager.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include "ApplicationManager.h" - -#include "ByteEngine/Game/World.h" -#include "ByteEngine/Game/System.hpp" - -#include "ByteEngine/Debug/FunctionTimer.h" - -#include "ByteEngine/Application/ThreadPool.h" -#include "ByteEngine/Application/Application.h" - -#include - -ApplicationManager::ApplicationManager() : Object(u8"ApplicationManager"), worlds(4, GetPersistentAllocator()), systems(8, GetPersistentAllocator()), systemNames(16, GetPersistentAllocator()), -systemsMap(16, GetPersistentAllocator()), systemsIndirectionTable(64, GetPersistentAllocator()), events(32, GetPersistentAllocator()), tasks(128, GetPersistentAllocator()), functionToTaskMap(128, GetPersistentAllocator()), enqueuedTasks(128, GetPersistentAllocator()), tasksInFlight(0u), stagesNames(8, GetPersistentAllocator()), taskSorter(128, GetPersistentAllocator()), systemsData(16, GetPersistentAllocator()), liveInstances(256, GetPersistentAllocator()) -{ -} - -ApplicationManager::~ApplicationManager() { - { - //Call shutdown in reverse order since systems initialized last during application start - //may depend on those created before them also for shutdown - auto shutdownSystem = [&](GTSL::SmartPointer& system) -> void { - system.TryFree(); - }; - - GTSL::ReverseForEach(systems, shutdownSystem); - } - - World::DestroyInfo destroy_info; - destroy_info.GameInstance = this; - for (auto& world : worlds) { world->DestroyWorld(destroy_info); } -} - -void ApplicationManager::OnUpdate(BE::Application* application) { - struct DDD { - TypeErasedTaskHandle TaskHandle; - uint8 RunAttempts = 0; - }; - - using TaskStackType = GTSL::Vector; - - TaskStackType freeTaskStack(GetTransientAllocator()); - GTSL::StaticVector perStageTasks; // Holds all tasks which are to be executed - - GTSL::Vector executedTasks(GetTransientAllocator()); - - GTSL::Vector perStageCounter(32, GetTransientAllocator()); // Maintains the count of how many tasks were executed for each stage. It's used to know when an stage can advance. - - for(uint32 i = 0; i < stages; ++i) { // Loads all recurrent task onto the stack - perStageTasks.EmplaceBack(16, GetTransientAllocator()); - - for(uint32 j = 0; j < stages[i]; ++j) { - perStageTasks.back().EmplaceBack(stages[i][j]); - } - - perStageCounter.EmplaceBack(0); - } - - { - for (uint32 i = 0; i < enqueuedTasks; ++i) { - freeTaskStack.EmplaceBack(enqueuedTasks[i]); - } - - enqueuedTasks.Resize(0); // Clear enqueued tasks list after processing it - } - - // Stores tasks which were not dispatched during this cycle, so must be added back into the enqued tasks list for them to have another shot at running the next cycle. Note, that when loading the free tasks stack the en-queued tasks list is cleared completely. - GTSL::Vector nonDispatchedTasks(32, GetTransientAllocator()); - - // Mutex used to wait until resource availability changes. - GTSL::Mutex waitWhenNoChange; - - // Round robin counter to ensure all tasks run. - uint32 rr = 0; - - uint16 stageIndex = 0; - - bool debugTasks = BE::Application::Get()->GetBoolOption(u8"ApplicationManager.debugTasks"); - - auto tryDispatchTask = [&](TaskStackType& stack) -> bool { - const uint32 taskIndex = rr++ % stack.GetLength(); - auto& ddd = stack[taskIndex]; - auto taskHandle = ddd.TaskHandle; - auto& task = tasks[taskHandle()]; - - if(!task.Instances) { stack.Pop(taskIndex); return false; } //todo: instead cull queue and eliminate duplicate entries - - if (const auto result = taskSorter.CanRunTask(task.Access)) { - uint32 i = 0; - - while (i < task.Instances) { - auto& taskInstance = task.Instances[i]; - - if(taskInstance.Signals) { - auto& s = systemsData[taskInstance.SystemId]; - - uint8 val = 0; - - uint32 l = 0; - - { - GTSL::ReadLock lock(liveInstancesMutex); - auto& e = liveInstances[taskInstance.InstanceHandle.InstanceIndex]; - val = e.Counter; - l = e.SystemID; - l |= e.ComponentID << 16; - } - - auto& t = s.Types[l]; - - if (auto r = t.SetupSteps.LookFor([&](const SystemData::TypeData::DependencyData& d) { return taskHandle == d.TaskHandle; }); !r || val < r.Get()) { // If this task can, at this point, execute for this entity type - ++ddd.RunAttempts; - ++taskInstance.DispatchAttempts; - - if(taskInstance.DispatchAttempts > 3) { - if(debugTasks) { - BE_LOG_WARNING(u8"Failed to dispatch ", task.Name, u8", instance: ", taskInstance.TaskNumber, u8". Requires level: ", r.Get(), u8", but has: ", val); - BE_LOG_WARNING(u8"Task: ", tasks[t.SetupSteps[val].TaskHandle()].Name, u8" is required"); - } - } - - ++i; continue; - } - } - - if(task.Pre != 0xFFFFFFFF) { - if(!executedTasks.Find(TypeErasedTaskHandle(task.Pre))) { // If task which which we depend on executing hasn't yet executed, don't schedule instance. - ++ddd.RunAttempts; - ++taskInstance.DispatchAttempts; - - if(taskInstance.DispatchAttempts > 3) { - if(debugTasks) { - BE_LOG_WARNING(u8"Failed to dispatch ", task.Name, u8", instance: ", taskInstance.TaskNumber) - } - } - - ++i; continue; - } - } - - taskSorter.AddInstance(result.Get(), taskInstance.TaskInfo); // Append task instance to the task sorter's task dispatch packet - - if (!task.Scheduled) { - task.Instances.Pop(i); // Remove tasks instances which where successfully scheduled for execution. - } else { - ++i; - } - } - - if (!taskSorter.GetValidInstances(result.Get())) { - taskSorter.ReleaseResources(result.Get()); - if(ddd.RunAttempts > 3) { - if(debugTasks) { - BE_LOG_WARNING(u8"Task: ", task.Name, u8", has failed to run multiple times, removing from stack."); - } - - nonDispatchedTasks.EmplaceBack(taskHandle); - stack.Pop(taskIndex); // Remove task from the stack for this cycle, since multiple fails to run can stall the whole pipeline - } - return false; - } // Don't schedule dispatcher execution if no instance was up for execution - - application->GetThreadPool()->EnqueueTask(task.TaskDispatcher, this, GTSL::MoveRef(result.Get()), GTSL::MoveRef(taskHandle)); // Add task dispatcher to thread pool - - ++tasksInFlight; - resourcesUpdated.Add(); - - if(task.IsDependedOn) { - executedTasks.EmplaceBack(taskHandle); - } - - const uint16 targetStageIndex = task.EndStageIndex; - - if (targetStageIndex != 0xFFFF) { - semaphores[targetStageIndex].Add(); - ++perStageCounter[targetStageIndex]; - } - - stack.Pop(taskIndex); // If task was executed remove from stack. - - return true; - } - - if(ddd.RunAttempts > 3) { - BE_LOG_WARNING(u8"Task: ", task.Name, u8", has failed to run multiple times, removing from stack."); - nonDispatchedTasks.EmplaceBack(taskHandle); - stack.Pop(taskIndex); // Remove task from the stack for this cycle, since multiple fails to run can stall the whole pipeline - } - - return false; - }; - - while(freeTaskStack || stageIndex < perStageTasks.GetLength()) { // While there are elements to be processed - while (stageIndex < perStageTasks.GetLength() && perStageTasks[stageIndex]) { - semaphores[stageIndex].Wait(); - - if(!tryDispatchTask(perStageTasks[stageIndex])) { - break; - } - } - - if (stageIndex < perStageTasks.GetLength() && !perStageTasks[stageIndex]) { // If stage can be changed - ++stageIndex; - //getLogger()->InstantEvent(GTSL::StringView(stagesNames[stageIndex]), application->GetClock()->GetCurrentMicroseconds().GetCount()); //TODO: USE LOCK ON STAGE NAME - } - - while (freeTaskStack) { - if (!tryDispatchTask(freeTaskStack)) { - break; - } - } - - if (tasksInFlight) { // If there are task enqueued on the thread pool wait until a change in resource availability occurs to continue trying to dispatch tasks. Don't wait without checking if there are tasks left, because that will leave the thread waiting indefinitely since there are no tasks to signal the condition. - //resourcesUpdated.Wait(waitWhenNoChange); - resourcesUpdated.Wait(); - } - } - - for(auto e : nonDispatchedTasks) { - enqueuedTasks.EmplaceBack(e); - } - - ++frameNumber; -} - -void ApplicationManager::UnloadWorld(const WorldReference worldId) -{ - World::DestroyInfo destroy_info; - destroy_info.GameInstance = this; - worlds[worldId]->DestroyWorld(destroy_info); - worlds.Pop(worldId); -} - -BE::TypeIdentifier ApplicationManager::RegisterType(const BE::System* system, const GTSL::StringView type_name) { - uint16 id = system->systemId; - uint16 typeId = systemsData[id].TypeCount++; - - systemsData[id].Types.Emplace(BE::TypeIdentifier(id, typeId)(), GetPersistentAllocator()); - - return { id, typeId }; -} - -void ApplicationManager::RemoveTask(const Id taskName, const Id startOn) { - uint16 i = 0; - - if constexpr (BE_DEBUG) { - GTSL::ReadLock lock(stagesNamesMutex); - - if(!stagesNames.Find(startOn).State()) { - BE_LOG_ERROR(u8"Tried to remove task ", GTSL::StringView(taskName), u8" from stage ", GTSL::StringView(startOn), u8" which doesn't exist. Resolve this issue as it leads to undefined behavior in release builds!") - return; - } - - i = getStageIndex(startOn); - } - - { - GTSL::ReadLock lock(stagesNamesMutex); - i = getStageIndex(startOn); - } - - BE_LOG_MESSAGE(u8"Removed recurring task ", GTSL::StringView(taskName), u8" from stage ", GTSL::StringView(startOn)) -} - -void ApplicationManager::AddStage(GTSL::StringView stageName) -{ - auto hashedName = Id(stageName); - - if constexpr (BE_DEBUG) { - GTSL::WriteLock lock(stagesNamesMutex); - if (stagesNames.Find(hashedName).State()) { - BE_LOG_ERROR(u8"Tried to add stage ", stageName, u8" which already exists. Resolve this issue as it leads to undefined behavior in release builds!") - return; - } - } - - { - GTSL::WriteLock lock(stagesNamesMutex); - stagesNames.EmplaceBack(hashedName); - } - - stages.EmplaceBack(); -} - -void ApplicationManager::initWorld(const uint8 worldId) -{ - World::InitializeInfo initializeInfo; - initializeInfo.GameInstance = this; - worlds[worldId]->InitializeWorld(initializeInfo); -} \ No newline at end of file diff --git a/src/ByteEngine/Game/ApplicationManager.h b/src/ByteEngine/Game/ApplicationManager.h deleted file mode 100644 index c559a6dc..00000000 --- a/src/ByteEngine/Game/ApplicationManager.h +++ /dev/null @@ -1,966 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Tasks.h" -#include "ByteEngine/Id.h" - -#include "ByteEngine/Debug/Assert.h" - -#include "ByteEngine/Handle.hpp" -#include "ByteEngine/Debug/FunctionTimer.h" - -#include "ByteEngine/Application/Handle.hpp" - -#include "ByteEngine/Game/System.hpp" - -#include "ByteEngine/Application/Application.h" - -class World; -class ComponentCollection; - -namespace BE { - class Application; - class System; -} - -template -using Task = GTSL::Delegate; - -inline const char8_t* AccessTypeToString(const AccessType access) { - switch (static_cast(access)) { - case static_cast(AccessTypes::READ): return u8"READ"; - case static_cast(AccessTypes::READ_WRITE): return u8"READ_WRITE"; - } - - return u8"NULL"; -} - -template -struct TypedDependency { - TypedDependency(GTSL::StringView name) : Name(name) {} - TypedDependency(GTSL::StringView name, AccessType at) : Name(name), Access(at) {} - - using type = T; - Id Name; AccessType Access = AccessTypes::READ_WRITE; -}; - -template -struct DependencyBlock { - DependencyBlock(C... tds) : Names{ {}, tds.Name... }, AccessTypes{ {}, tds.Access... } {} - - Id Names[1 + sizeof...(C)]; - AccessType AccessTypes[1 + sizeof...(C)]; - uint64 Length = sizeof...(C); -}; - -template -struct Resources {}; - -template -struct TaskHandle { - TaskHandle() = default; - TaskHandle(uint32 reference) : Reference(reference) {} - - uint32 Reference = ~0U; - - operator bool() const { return Reference != ~0U; } - - uint32 operator()() const { return Reference; } -}; - -template -struct EventHandle { - EventHandle(const Id hashed_name) : Name(hashed_name) {} - EventHandle(const GTSL::StringView name) : Name(name) {} - Id Name; -}; - -MAKE_HANDLE(uint32, System) - -namespace BE { - struct TypeIdentifier { - TypeIdentifier() = delete; - TypeIdentifier(const uint16 sysid, const uint16 tid) : SystemId(sysid), TypeId(tid) {} - - bool operator==(const TypeIdentifier&) const = default; - - uint16 SystemId = 0xFFFF, TypeId = 0xFFFF; - - uint32 operator()() const { return (SystemId | TypeId << 16); } - }; - - template - struct fixed_string { - constexpr fixed_string(const char8_t (&s)[L + 1]) { - for(uint32 i = 0; i < L; ++i) { - _chars[i] = s[i]; - } - } - - const char8_t _chars[L+1] = {}; // +1 for null terminator - }; - - template - fixed_string(const char8_t (&arr)[N]) -> fixed_string; // Drop the null terminator - - struct BaseHandle { - protected: - friend ApplicationManager; - BaseHandle(uint32 a, uint32 handle) : InstanceIndex(a), EntityIndex(handle) {} - - uint32 InstanceIndex = 0xFFFFFFFF, EntityIndex = 0xFFFFFFFF; - - public: - BaseHandle() = default; - - uint32 operator()() const { return EntityIndex; } - - explicit operator uint64() const { return EntityIndex; } - explicit operator bool() const { return EntityIndex != 0xFFFFFFFF; } - }; - - template - struct Handle : public BaseHandle { - Handle() = default; - Handle(const Handle&) = default; - //Handle& operator=(const Handle& other) { - // Identifier.SystemId = other.Identifier.SystemId; - // Identifier.TypeId = other.Identifier.TypeId; - // EntityIndex = other.EntityIndex; - //} - private: - friend ApplicationManager; - Handle(uint32 a, uint32 handle) : BaseHandle(a, handle) {} - }; - //static_assert(sizeof(Handle ) <= 8); -} - -namespace GTSL { - template<> - struct Hash { - uint64 value = 0; - Hash(const BE::BaseHandle handle) : value(uint64(handle)) {} - operator uint64() const { return value; } - }; - - Hash(BE::BaseHandle) -> GTSL::Hash; -} - -#define LSTR(x) u8 ## x - -#define MAKE_BE_HANDLE(name)\ - using name##Handle = BE::Handle; - -#define BE_RESOURCES(...) __VA_ARGS__ -#define DECLARE_BE_TASK(name, res, ...) private: TaskHandle<__VA_ARGS__> name##TaskHandle; using name##Dependencies = DependencyBlock; public: auto Get##name##TaskHandle() const { return name##TaskHandle; } -#define DECLARE_BE_TYPE(name) MAKE_BE_HANDLE(name); private: BE::TypeIdentifier name##TypeIndentifier; public: BE::TypeIdentifier Get##name##TypeIdentifier() const { return name##TypeIndentifier; } -#define DECLARE_BE_EVENT(name, ...) private: EventHandle<__VA_ARGS__> name##EventHandle; public: static auto Get##name##EventHandle() { return EventHandle<__VA_ARGS__>(Id(LSTR(#name))); } - -template class> -struct is_instance : public std::false_type {}; - -template class U> -struct is_instance, U> : public std::true_type {}; - -class ApplicationManager : public Object { - MAKE_HANDLE(uint32, TypeErasedTask) - using TypeErasedHandleHandle = BE::BaseHandle; - using FunctionType = GTSL::Delegate; -public: - ApplicationManager(); - ~ApplicationManager(); - - void OnUpdate(BE::Application* application); - - using WorldReference = uint8; - - struct CreateNewWorldInfo {}; - template - WorldReference CreateNewWorld(const CreateNewWorldInfo& createNewWorldInfo) - { - auto index = worlds.GetLength(); - worlds.EmplaceBack(GetPersistentAllocator()); - initWorld(index); return index; - } - - void UnloadWorld(WorldReference worldId); - - template - void DestroyEntity(const T handle) { - auto& typeData = systemsData[handle.Identifier.SystemId].Types[handle.Identifier.TypeId]; - - auto& ent = typeData.Entities[handle.EntityIndex]; - - if (!(--ent.Uses)) { - if (typeData.DeletionTaskHandle) { //if we have a valid deletion handle - //EnqueueTask(TaskHandle(typeData.DeletionTaskHandle()), GTSL::MoveRef(handle)); - //enqueue and then call task - } - else { - BE_LOG_WARNING(u8"No deletion task available."); - } - } - } - - template - T* GetSystem(const GTSL::StringView systemName) { - GTSL::Lock lock(systemsMutex); - return static_cast(systemsMap.At(systemName)); - } - - template - T* GetSystem(const SystemHandle systemReference) { - GTSL::Lock lock(systemsMutex); - return static_cast(systems[systemReference()].GetData()); - } - - SystemHandle GetSystemReference(const GTSL::StringView systemName) { - GTSL::Lock lock(systemsMutex); - return SystemHandle(systemsIndirectionTable.At(systemName)); - } - - BE::TypeIdentifier RegisterType(const BE::System* system, const GTSL::StringView typeName); - - template - void BindDeletionTaskToType(const BE::TypeIdentifier handle, const TaskHandle deletion_task_handle) { - systemsData[handle.SystemId].Types[handle()].DeletionTaskHandle = TypeErasedTaskHandle(deletion_task_handle.Reference); - } - - void SpecifyTaskCoDependency(const TypeErasedTaskHandle a, const TypeErasedTaskHandle b) { - TaskData& taskA = tasks[a()]; - taskA.IsDependedOn = true; - TaskData& taskB = tasks[b()]; - taskB.Pre = a(); - } - - template - void AddTypeSetupDependency(BE::System* system_pointer, BE::TypeIdentifier type_identifier, TaskHandle dynamic_task_handle, bool is_required = true) { - auto& registeringSystem = systemsData[system_pointer->GetSystemId()]; - - if(type_identifier.SystemId != system_pointer->systemId) { // If type is not own, add to observed types - if(!registeringSystem.ObservedTypes.Find(type_identifier)) { - registeringSystem.ObservedTypes.EmplaceBack(type_identifier); - } - } - - auto& observedSystem = systemsData[type_identifier.SystemId]; - - if(!observedSystem.ObservingSystems.Find(SystemHandle(system_pointer->GetSystemId()))) { - observedSystem.ObservingSystems.EmplaceBack(SystemHandle(system_pointer->GetSystemId())); - } - - auto& type = registeringSystem.Types.TryEmplace(type_identifier(), GetPersistentAllocator()).Get(); - - if(type.SetupSteps) { - SpecifyTaskCoDependency(type.SetupSteps.back().TaskHandle, TypeErasedTaskHandle(dynamic_task_handle())); - } - - type.SetupSteps.EmplaceBack(TypeErasedTaskHandle(dynamic_task_handle()), is_required); - ++type.Target; - - TaskData& task = tasks[dynamic_task_handle()]; - task.AssociatedType = type_identifier; - } - - MAKE_HANDLE(uint32, Resource); - - ResourceHandle AddResource(BE::System* system_pointer, BE::TypeIdentifier type_identifier) { - auto& system = systemsData[system_pointer->GetSystemId()]; - auto& type = system.Types[type_identifier()]; - type.SetupSteps.EmplaceBack(TypeErasedTaskHandle(), true); - ++type.Target; - return ResourceHandle(0); - } - - template - static void task(ApplicationManager* gameInstance, const DispatchedTaskHandle dispatched_task_handle, TypeErasedTaskHandle task_handle) { - const TaskData& task = gameInstance->tasks[task_handle()]; - - auto instances = gameInstance->taskSorter.GetValidInstances(dispatched_task_handle); - - for (auto e : instances) { - DTI* info = static_cast(e); - - auto startTime = BE::Application::Get()->GetClock()->GetCurrentMicroseconds(); - - T* system = (T*)gameInstance->systems[info->SystemId].GetData(); - - if(info->Callee != system) { - BE_DEBUG_BREAK; - } - - call(TaskInfo(gameInstance), &task, info); - - GTSL::StaticString<512> args(u8"\"Start stage\":{ "); args += u8"\"Name\":\""; ToString(args, task.StartStage); args += u8"\", \"Index\":"; ToString(args, task.StartStageIndex); args += u8" },"; - args += u8"\"End stage\":{ "; args += u8"\"Name\":\""; ToString(args, task.EndStage); args += u8"\", \"Index\":"; ToString(args, task.EndStageIndex); args += u8" },"; - args += u8"\"Accesses\":[ "; - for (uint32 i = 0; i < task.Access; ++i) { - auto& [name, access] = task.Access[i]; - if(i) { args+=u8", "; } - args += u8"{ \"System\":\""; args += GTSL::StringView(gameInstance->systemNames[name]); args += u8"\", \"Access type\":\""; args += AccessTypeToString(access); args += u8"\" }"; - } - args += u8" ]"; - - BE::Application::Get()->GetLogger()->logFunction(task.Name, startTime, BE::Application::Get()->GetClock()->GetCurrentMicroseconds(), args); - - if (task.EndStageIndex != 0xFFFF) { gameInstance->semaphores[task.EndStageIndex].Post(); } - - if (info->Signals) { - GTSL::WriteLock lock(gameInstance->liveInstancesMutex); - ++gameInstance->liveInstances[info->InstanceHandle.InstanceIndex].Counter; - } - - ++info->D_CallCount; - - if (!task.Scheduled) { GTSL::Delete(&info, gameInstance->GetPersistentAllocator()); } // KEEP LAST AS THIS ERASES DATA - } - - --gameInstance->tasksInFlight; - //gameInstance->resourcesUpdated.NotifyAll(); - gameInstance->resourcesUpdated.Post(); - gameInstance->taskSorter.ReleaseResources(dispatched_task_handle); - } - - static constexpr uint32 MAX_SYSTEMS = 8u; - - /** - * \brief Registers a task with the application manager. - * \tparam T Callee type. - * \tparam ACC Typed dependencies types. - * \tparam FARGS Task function parameter types. - * \param caller Pointer to the system registering the function. - * \param taskName Task name. - * \param dependencies Dependencies list indicating which system will be accessed during this task and in what way(READ, READ_WRITE). - * \param delegate Pointer to the function which will be called. - * \param start_stage Stage at which the task can begin executing. Can be null to specify any moment in time is valid. - * \param end_stage Stage for which the task must be done executing. Can be null to specify any moment in time is valid. - * \return TaskHandle which identifies the task. - */ - template - [[nodiscard]] auto RegisterTask(T* caller, const GTSL::StringView taskName, DependencyBlock dependencies, void(T::* delegate)(TaskInfo, FARGS...), const GTSL::StringView start_stage = GTSL::StringView(), const GTSL::StringView end_stage = GTSL::StringView()) { - //const uint64 fPointer = *reinterpret_cast(&delegate); - - //if (const auto r = functionToTaskMap.TryGet(fPointer)) { - // return[&](void(T:: * d)(TaskInfo, typename ACC::type*..., ARGS...)) { return TaskHandle(r.Get()()); }(delegate); - //} - - GTSL::StaticVector accesses; - - dependencies.Names[0] = caller->instanceName; dependencies.AccessTypes[0] = AccessTypes::READ_WRITE; // Add a default access to the caller system since we also have to sync access to the caller and we don't expect the user to do so, access is assumed to be read_write - - //assertTask(taskName, {}, ) - - { - GTSL::ReadLock lock(stagesNamesMutex); - decomposeTaskDescriptor(dependencies.Length + 1, dependencies.Names, dependencies.AccessTypes, accesses); - } - - uint32 taskIndex = tasks.GetLength(); // Task index in tasks vector - - TaskData& task = tasks.EmplaceBack(); - - uint16 startStageIndex = 0xFFFF, endStageIndex = 0xFFFF; - - if (start_stage != GTSL::StringView()) { // Store start stage indices if a start stage is specified - startStageIndex = (uint32)stagesNames.Find(Id(start_stage)).Get(); - } - - if (end_stage != GTSL::StringView()) { // Store end stage indices if an end stage is specified - endStageIndex = (uint32)stagesNames.Find(Id(end_stage)).Get(); - } - - systemsData[caller->GetSystemId()].Tasks.EmplaceBack(taskIndex); // Add task handle to list of system owned tasks - - static_assert(sizeof...(ACC) <= MAX_SYSTEMS); - - return [&](void(T:: * d)(TaskInfo, typename ACC::type*..., ARGS...)) { - //static_assert((GTSL::IsSame, ARGS>() && ...), "Provided parameter types for task are not compatible with those required."); - - using TDI = TaskDispatchInfo; - - if constexpr (sizeof...(ARGS)) { - if constexpr (is_instance::type, BE::Handle>{}) { - task.Signals = true; - } - } - - { - //TODO: LOCKS!! - task.Name = GTSL::StringView(taskName); // Store task name, for debugging purposes - task.StartStageIndex = startStageIndex; // Store start stage index to correctly synchronize task execution, value may be 0xFFFF which indicates that there is no dependency on a stage. - task.StartStage = start_stage; // Store start stage name for debugging purposes - task.EndStageIndex = endStageIndex; // Store end stage index to correctly synchronize task execution, value may be 0xFFFF which indicates that there is no dependency on a stage. - task.EndStage = end_stage; // Store end stage name for debugging purposes - task.Callee = caller; // Store pointer to system instance which will be called when this task is executed - task.TaskDispatcher = FunctionType::Create<&ApplicationManager::task>(); // Store dispatcher, an application manager function which manages task state and calls the client delegate. - task.Access = accesses; // Store task accesses for synchronization and debugging purposes. - task.SetDelegate(d); // Set client function to be called - } - - return TaskHandle(taskIndex); - } (delegate); - } - - template - void SetTaskReceiveOnlyLast(const TaskHandle task_handle) { - TaskData& task = tasks[task_handle()]; - task.OnlyLast = true; - } - - /** - * \brief Schedules a task to run on a periodic basis. - * \tparam ARGS - */ - template - auto EnqueueScheduledTask(TaskHandle task_handle, ARGS&&... args) -> void { - using TDI = TaskDispatchInfo; - TaskData& task = tasks[task_handle()]; //TODO: locks - - if (stages[task.StartStageIndex].Find(TypeErasedTaskHandle(task_handle()))) { - BE_LOG_WARNING(u8"Task: ", task.Name, u8" is already scheduled"); return; - } - - task.Scheduled = true; - allocateTaskDispatchInfo(task, task.Access.front().First, TypeErasedHandleHandle(), GTSL::ForwardRef(args)...); - - stages[task.StartStageIndex].EmplaceBack(TypeErasedTaskHandle(task_handle())); - } - - template - void RemoveScheduledTask(TaskHandle task_handle) { - TaskData& task = tasks[task_handle()]; //TODO: locks - - if (!stages[task.StartStageIndex].Find(TypeErasedTaskHandle(task_handle()))) { - BE_LOG_WARNING(u8"Task: ", task.Name, u8" couldnt't be found"); return; - } - - task.Instances.PopBack(); - - stages[task.StartStageIndex].Pop(stages[task.StartStageIndex].Find(TypeErasedTaskHandle(task_handle())).Get()); - } - - template - static decltype(auto) get(Ts&&... ts) { - return std::get(std::forward_as_tuple(ts...)); - } - - BE::TypeIdentifier getTypeIdentifier(const TypeErasedHandleHandle type_erased_handle_handle) const { - GTSL::ReadLock mutex(liveInstancesMutex); - const auto& e = liveInstances[type_erased_handle_handle.InstanceIndex]; - return { e.SystemID, e.ComponentID }; - } - - template - void EnqueueTask(const TaskHandle task_handle, ARGS&&... args) { - if(!task_handle) { BE_LOG_ERROR(u8"Tried to dispatch task but handle was invalid."); return; } - - TaskData& task = tasks[task_handle()]; //TODO: locks - task.Scheduled = false; - - if constexpr (sizeof...(ARGS)) { - if(task.Signals) { - if constexpr (is_instance::type, BE::Handle>{}) { - auto& invokedSystem = systemsData[task.Access.front().First]; - - auto typedHandle = get<0>(args...); - - auto handle = makeTypeErasedHandle(typedHandle); - - if(invokedSystem.Types.Find(getTypeIdentifier(typedHandle)())) { // Check if entity identifier is associated with receiving task - } else { - } - - allocateTaskDispatchInfo(task, task.Access.front().First, handle, GTSL::ForwardRef(args)...); - } else { - allocateTaskDispatchInfo(task, task.Access.front().First, TypeErasedHandleHandle(), GTSL::ForwardRef(args)...); - } - } else { - allocateTaskDispatchInfo(task, task.Access.front().First, TypeErasedHandleHandle(), GTSL::ForwardRef(args)...); - } - } else { - allocateTaskDispatchInfo(task, task.Access.front().First, TypeErasedHandleHandle(), GTSL::ForwardRef(args)...); - } - - enqueuedTasks.EmplaceBack(TypeErasedTaskHandle(task_handle())); - } - - void RemoveTask(Id taskName, Id startOn); - - template - EventHandle RegisterEvent(const BE::System* caller, const GTSL::StringView event_name, bool priority = false) { - GTSL::WriteLock lock(eventsMutex); - if constexpr (BE_DEBUG) { if (events.Find(Id(event_name))) { BE_LOG_ERROR(u8"An event by the name ", event_name, u8" already exists, skipping adition. ", BE::FIX_OR_CRASH_STRING); return EventHandle(u8""); } } - Event& eventData = events.Emplace(Id(event_name), GetPersistentAllocator()); - - if (priority) { - eventData.priorityEntry = 0; - } - - return EventHandle(event_name); - } - - template - void AddEvent(const GTSL::StringView caller, const EventHandle eventHandle, bool priority = false) { - GTSL::WriteLock lock(eventsMutex); - if constexpr (BE_DEBUG) { if (events.Find(eventHandle.Name)) { BE_LOG_ERROR(u8"An event by the name ", GTSL::StringView(eventHandle.Name), u8" already exists, skipping adition. ", BE::FIX_OR_CRASH_STRING); return; } } - Event& eventData = events.Emplace(eventHandle.Name, GetPersistentAllocator()); - - if (priority) { - eventData.priorityEntry = 0; - } - } - - template - void SubscribeToEvent(const GTSL::StringView caller, const EventHandle eventHandle, TaskHandle taskHandle) { - GTSL::WriteLock lock(eventsMutex); - if constexpr (BE_DEBUG) { if (!events.Find(eventHandle.Name)) { BE_LOG_ERROR(u8"No event found by that name, skipping subscription. ", BE::FIX_OR_CRASH_STRING); return; } } - auto& vector = events.At(eventHandle.Name).Functions; - vector.EmplaceBack(taskHandle.Reference); - } - - template - void DispatchEvent(const BE::System*, const EventHandle eventHandle, ARGS&&... args) { - GTSL::ReadLock lock(eventsMutex); - if constexpr (BE_DEBUG) { if (!events.Find(eventHandle.Name)) { BE_LOG_ERROR(u8"No event found by that name, skipping dispatch. ", BE::FIX_OR_CRASH_STRING); return; } } - - Event& eventData = events.At(eventHandle.Name); - - if (eventData.priorityEntry != ~0U) { - EnqueueTask(TaskHandle(eventData.Functions[eventData.priorityEntry]()), GTSL::ForwardRef(args)...); - } - else { - auto& functionList = eventData.Functions; - for (auto e : functionList) { EnqueueTask(TaskHandle(e()), GTSL::ForwardRef(args)...); } - } - } - - void AddStage(GTSL::StringView stageName); - - template - T MakeHandle(BE::TypeIdentifier type_identifier, uint32 index) { - GTSL::WriteLock lock(liveInstancesMutex); - - auto instanceIndex = liveInstances.Emplace(type_identifier.SystemId, type_identifier.TypeId); - - auto& s = systemsData[type_identifier.SystemId]; - //s.Types[type_identifier()].Entities.EmplaceAt(instanceIndex, TypeErasedHandleHandle(index, instanceIndex)); - - { - for(auto osh : s.ObservingSystems) { - liveInstances.Emplace(type_identifier.SystemId, type_identifier.TypeId); - } - } - - return T(instanceIndex, index); - } - -private: - GTSL::Vector, BE::PersistentAllocatorReference> worlds; - - mutable GTSL::Mutex systemsMutex; - GTSL::FixedVector, BE::PersistentAllocatorReference> systems; - GTSL::FixedVector systemNames; - GTSL::HashMap systemsMap; - GTSL::HashMap systemsIndirectionTable; - - /** - * \brief Stores all data necessary to invoke a dispatch. - * Resource parameters are stored separately from data parameters because it simplifies accessing DispatchTaskInfo through type erased pointers since we don't need to know what resources the task requires only the data it uses. - * Such a use case can be seen with stored tasks, only StoreDynamicTask() can see the tasks full signature but can't allocate a DTI - * since every task needs it's own DTI instance which will be allocated when innvoking an stored dynamic task, but since AddStoredDynamicTask doesn't know the full - * signature it's easier to have DTIs use just the data parameters since that information is known thanks to the DynamicTaskHandle. - * \tparam ARGS Types of the non resource parameters for a task. - */ - template - struct TaskDispatchInfo { - TaskDispatchInfo() : Arguments{ 0 } {} - - template - TaskDispatchInfo(void(T::* function)(TaskInfo, FULL_ARGS...), uint32 sysCount) : ResourceCount(sysCount) { - static_assert(sizeof(decltype(function)) == 8); - WriteDelegate(function); - } - - template - TaskDispatchInfo(void(T::* function)(TaskInfo, FULL_ARGS...), uint32 sysCount, ARGS&&... args) requires (static_cast(sizeof...(ARGS))) : ResourceCount(sysCount) { - static_assert(sizeof(decltype(function)) == 8); - WriteDelegate(function); - UpdateArguments(GTSL::ForwardRef(args)...); - } - - TaskDispatchInfo(const TaskDispatchInfo&) = delete; - TaskDispatchInfo(TaskDispatchInfo&&) = delete; - - ~TaskDispatchInfo() { - [&] (GTSL::Indices) { - (GTSL::Destroy::type>(*GetPointer()), ...); - } (GTSL::BuildIndices{}); - -#if BE_DEBUG - Callee = nullptr; -#endif - } - - void* Callee; - uint32 ResourceCount = 0; - uint16 SystemId; - - // Index of the entity to signal as being updated by the task. - bool Signals = false; - byte Arguments[sizeof(BE::System*) * MAX_SYSTEMS + GTSL::PackSize()]; - - uint32 D_CallCount = 0; - - TypeErasedHandleHandle InstanceHandle; - - void SetResource(const uint64 pos, BE::System* pointer) { *reinterpret_cast(Arguments + pos * 8) = pointer; } - - template - T* GetResource() { return *reinterpret_cast(Arguments + POS * 8); } - - template - auto GetPointer() { return reinterpret_cast::type*>(Arguments + ResourceCount * 8 + GTSL::PackSizeAt()); } - - template - auto& GetArgument() { return *GetPointer(); } - - void UpdateArguments(ARGS&&... args) { - [&] (GTSL::Indices) { - (::new(GetPointer()) ARGS(GTSL::ForwardRef(args)), ...); - } (GTSL::BuildIndices{}); - } - }; - - mutable GTSL::ReadWriteMutex eventsMutex; - - struct Event { - Event(const BE::PAR& allocator) : Functions(allocator) {} - - uint32 priorityEntry = ~0U; - GTSL::Vector Functions; - }; - GTSL::HashMap events; - - GTSL::Atomic taskCounter{ 0u }; - - // TASKS - mutable GTSL::ReadWriteMutex tasksMutex; - struct TaskData { - //TaskData() : TargetType(0xFFFF, 0xFFFF) {} - TaskData() {} - - /** - * \brief Hold a function pointer to a dispatcher function with the signature of the task. - */ - FunctionType TaskDispatcher; - - static constexpr size_t TASK_POINTER_BUFFER_SIZE = 16ull; - - GTSL::StaticVector Access; - void* Callee; - byte TaskFunction[TASK_POINTER_BUFFER_SIZE]; - - uint16 StartStageIndex = 0xFFFF, EndStageIndex = 0xFFFF; - -#if BE_DEBUG - GTSL::StaticString<64> Name, StartStage, EndStage; -#endif - - //Task that has to be called before this - uint32 Pre = 0xFFFFFFFF; - - bool IsDependedOn = false; - - bool Scheduled = false; - bool Signals = false; - - TypeErasedTaskHandle Next; - BE::TypeIdentifier AssociatedType{ 0xFFFF, 0xFFFF }; - - struct InstanceData { - uint32 TaskNumber = 0; - - // System index which the entity to update corresponds to. - uint16 SystemId; - - // Index of the entity to signal as being updated by the task. - TypeErasedHandleHandle InstanceHandle; - void* TaskInfo; - - bool Signals = false; - - uint16 DispatchAttempts = 0; - }; - GTSL::StaticVector Instances; - - bool OnlyLast = false; - - template - void SetDelegate(F delegate) { - static_assert(sizeof(F) <= TASK_POINTER_BUFFER_SIZE, "Delegate size is bigger than buffer available."); - auto* d = reinterpret_cast(&delegate); - for (uint64 i = 0; i < sizeof(F); ++i) { - TaskFunction[i] = d[i]; - } - } - - template - auto GetDelegate() const { - union F { - void(T::* Delegate)(TaskInfo, ARGS...); - }; - - return reinterpret_cast(TaskFunction)->Delegate; - } - }; - GTSL::Vector tasks; - - GTSL::HashMap functionToTaskMap; - - GTSL::StaticVector, 16> stages; - - GTSL::Vector enqueuedTasks; - - template - static void call(TaskInfo task_info, const TaskData* task_data, TaskDispatchInfo* dispatch_task_info) { - [&] (GTSL::Indices, GTSL::Indices) { - (static_cast(dispatch_task_info->Callee)->*(task_data->template GetDelegate()))(task_info, dispatch_task_info->template GetResource()..., GTSL::MoveRef(dispatch_task_info->template GetArgument())...); - } (GTSL::BuildIndices{}, GTSL::BuildIndices{}); - } - - // TASKS - - GTSL::Semaphore resourcesUpdated; - GTSL::Atomic tasksInFlight; - - mutable GTSL::ReadWriteMutex stagesNamesMutex; - GTSL::Vector stagesNames; - - TaskSorter taskSorter; - - GTSL::Semaphore semaphores[64]; - - uint32 scalingFactor = 16; - - uint64 frameNumber = 0; - - uint16 getStageIndex(const Id stageName) const { - auto findRes = GTSL::Find(stagesNames, [&](const Id& goal_name) { return goal_name == stageName; }); - BE_ASSERT(findRes, "No stage found with that name!"); - return static_cast(findRes.Get() - stagesNames.begin()); - } - - template - void decomposeTaskDescriptor(uint64 len, const Id* names, const AccessType* accessTypes, U& access) { - for (uint16 i = 0; i < len; ++i) { //for each dependency - access.EmplaceBack(getSystemIndex(names[i]), accessTypes[i]); - } - } - - [[nodiscard]] bool assertTask(const Id taskName, const Id startGoal, const Id endGoal, const uint64 len, const Id* names, const AccessType* access) const { - { - GTSL::ReadLock lock(stagesNamesMutex); - - if (!stagesNames.Find(startGoal).State()) { - BE_LOG_ERROR(u8"Tried to add task ", GTSL::StringView(taskName), u8" to stage ", GTSL::StringView(startGoal), u8" which doesn't exist. Resolve this issue as it leads to undefined behavior in release builds!") - return true; - } - - //assert done for exists - if (!stagesNames.Find(endGoal).State()) { - BE_LOG_ERROR(u8"Tried to add task ", GTSL::StringView(taskName), u8" ending on stage ", GTSL::StringView(endGoal), u8" which doesn't exist. Resolve this issue as it leads to undefined behavior in release builds!") - return true; - } - } - - //{ - // GTSL::ReadLock lock(recurringTasksMutex); - // - // if (recurringTasksPerStage[getStageIndex(startGoal)].DoesTaskExist(taskName)) { - // BE_LOG_ERROR(u8"Tried to add task ", GTSL::StringView(taskName), u8" which already exists to stage ", GTSL::StringView(startGoal), u8". Resolve this issue as it leads to undefined behavior in release builds!") - // return true; - // } - //} - - { - GTSL::Lock lock(systemsMutex); - - for (auto i = 0ull; i < len; ++i) { - if (!doesSystemExist(names[i])) { - BE_LOG_ERROR(u8"Tried to add task ", GTSL::StringView(taskName), u8" to stage ", GTSL::StringView(startGoal), u8" with a dependency on ", GTSL::StringView(names[i]), u8" which doesn't exist. Resolve this issue as it leads to undefined behavior in release builds!") - return true; - } - } - } - - return false; - } - - template - auto allocateTaskDispatchInfo(TaskData& task, uint16 task_owner_system_id, TypeErasedHandleHandle instance_handle, ARGS&&... args) { - TaskDispatchInfo* dispatchTaskInfo = GTSL::New>(GetPersistentAllocator()); - - dispatchTaskInfo->ResourceCount = task.Access.GetLength() - 1; - dispatchTaskInfo->UpdateArguments(GTSL::ForwardRef(args)...); - - for (uint32 i = 1; i < task.Access; ++i) { // Skip first resource because it's the system being called for which we don't send a pointer for - dispatchTaskInfo->SetResource(i - 1, systems[task.Access[i].First]); - } - - dispatchTaskInfo->Callee = task.Callee; - - const bool signals = task.Signals; - - const uint32 taskNumber = taskCounter++; - - auto h = instance_handle.InstanceIndex; - - if(task.OnlyLast) { - //TODO: match system index, and everything - auto taskForSameInstanceExists = task.Instances.LookFor([&](const TaskData::InstanceData& instance_data){ return instance_data.InstanceHandle.InstanceIndex == h; }); - if(taskForSameInstanceExists) { - TaskData::InstanceData& instance = task.Instances[taskForSameInstanceExists.Get()]; - GTSL::Delete(reinterpret_cast**>(&instance.TaskInfo), GetPersistentAllocator()); // Free overwritten task data - instance.TaskInfo = dispatchTaskInfo; - instance.TaskNumber = taskNumber; - } else { - if(task_owner_system_id == 0xFFFF) { - task.Instances.EmplaceBack(taskNumber, task_owner_system_id, instance_handle, dispatchTaskInfo, signals); - } else { - task.Instances.EmplaceBack(taskNumber, task_owner_system_id, instance_handle, dispatchTaskInfo, signals); - } - } - } else { - if(task_owner_system_id == 0xFFFF) { - task.Instances.EmplaceBack(taskNumber, task_owner_system_id, instance_handle, dispatchTaskInfo, signals); - } else { - task.Instances.EmplaceBack(taskNumber, task_owner_system_id, instance_handle, dispatchTaskInfo, signals); - } - } - - dispatchTaskInfo->SystemId = task_owner_system_id; dispatchTaskInfo->Signals = signals; - dispatchTaskInfo->InstanceHandle = instance_handle; - - return dispatchTaskInfo; - } - - void initWorld(uint8 worldId); - - uint32 getSystemIndex(Id systemName) { - return systemsIndirectionTable[GTSL::StringView(systemName)]; - } - - bool doesSystemExist(const Id systemName) const { - return systemsIndirectionTable.Find(GTSL::StringView(systemName)); - } - - //struct EntityClassData { - // - //}; - //GTSL::Vector entityClasses; - - struct SystemData { - SystemData(const BE::PAR& allocator) : Types(allocator) {} - - struct TypeData { - uint32 Target = 0; - TypeErasedTaskHandle DeletionTaskHandle; - - struct DependencyData { - DependencyData(TypeErasedTaskHandle task_handle, bool is_required) : TaskHandle(task_handle), IsReq(is_required) {} - - TypeErasedTaskHandle TaskHandle; - bool IsReq = true; - }; - GTSL::StaticVector SetupSteps; - //GTSL::FixedVector Entities; - - TypeData(const BE::PAR& allocator) {} - }; - GTSL::HashMap Types; - - GTSL::StaticVector ObservedTypes; - GTSL::StaticVector ObservingSystems; - - GTSL::StaticVector Tasks; - - uint32 TypeCount = 0; // Owned types count - - Id Name; - }; - GTSL::Vector systemsData; - - mutable GTSL::ReadWriteMutex liveInstancesMutex; - - struct InstanceData { - uint16 SystemID, ComponentID; - uint32 Counter = 0; - }; - GTSL::FixedVector liveInstances; - - template - static TypeErasedHandleHandle makeTypeErasedHandle(const BE::Handle a) { - return TypeErasedHandleHandle(a.InstanceIndex, a.EntityIndex); - } - -public: - /** - * \brief Create a system instance. - * \tparam T Class of system. - * \param systemName Identifying name for the system instance. - * \return A pointer to the created system. - */ - template - T* AddSystem(const GTSL::StringView systemName) { - if constexpr (BE_DEBUG) { - if (doesSystemExist(Id(systemName))) { - BE_LOG_ERROR(u8"System by that name already exists! Returning existing instance.", BE::FIX_OR_CRASH_STRING); - return reinterpret_cast(systemsMap.At(systemName)); - } - } - - T* systemPointer = nullptr; uint16 systemIndex = 0xFFFF; - - { - BE::System::InitializeInfo initializeInfo; - initializeInfo.AppManager = this; - initializeInfo.ScalingFactor = scalingFactor; - initializeInfo.InstanceName = Id(systemName); - - { - GTSL::Lock lock(systemsMutex); - - systemIndex = systemNames.Emplace(systemName); - initializeInfo.SystemId = systemIndex; - systemsIndirectionTable.Emplace(systemName, systemIndex); - auto& systemData = systemsData.EmplaceBack(GetPersistentAllocator()); - systemData.Name = Id(systemName); - } - - auto systemAllocation = GTSL::SmartPointer(GetPersistentAllocator(), initializeInfo); - systemPointer = systemAllocation.GetData(); - - { - GTSL::Lock lock(systemsMutex); - - systems.EmplaceAt(systemIndex, GTSL::MoveRef(systemAllocation)); - taskSorter.AddSystem(Id(systemName)); - systemsMap.Emplace(systemName, systemPointer); - } - } - - systemPointer->systemId = systemIndex; - systemPointer->instanceName = Id(systemName); - - return systemPointer; - } -}; diff --git a/src/ByteEngine/Game/CameraSystem.h b/src/ByteEngine/Game/CameraSystem.h deleted file mode 100644 index d1421560..00000000 --- a/src/ByteEngine/Game/CameraSystem.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" -#include "ByteEngine/Handle.hpp" -#include "ByteEngine/Game/System.hpp" - -#include -#include -#include - - -class CameraSystem : public BE::System -{ -public: - CameraSystem(const InitializeInfo& initializeInfo) : System(initializeInfo, u8"CameraSystem"), positionMatrices(4, GetPersistentAllocator()), rotationMatrices(4, GetPersistentAllocator()), fovs(4, GetPersistentAllocator()) - {} - - MAKE_HANDLE(uint32, Camera); - - CameraHandle AddCamera(const GTSL::Vector3 pos) - { - rotationMatrices.EmplaceBack(); - fovs.EmplaceBack(45.0f); - auto index = positionMatrices.GetLength(); - positionMatrices.EmplaceBack(pos); - return CameraHandle(index); - } - - void RemoveCamera(const CameraHandle reference) - { - positionMatrices.Pop(reference()); - rotationMatrices.Pop(reference()); - fovs.Pop(reference()); - } - - void SetCameraRotation(const CameraHandle reference, const GTSL::Quaternion quaternion) { - rotationMatrices[reference()] = GTSL::Matrix4(quaternion); - } - - void SetCameraRotation(const CameraHandle reference, const GTSL::Matrix4 matrix4) { - rotationMatrices[reference()] = matrix4; - } - - GTSL::Matrix4 GetCameraTransform() const { - return rotationMatrices[0] * positionMatrices[0]; - } - - void SetCameraPosition(const CameraHandle reference, const GTSL::Vector3 pos) { - GTSL::Math::SetTranslation(positionMatrices[reference()], pos); - } - - void AddCameraPosition(const CameraHandle reference, GTSL::Vector3 pos) { - GTSL::Math::Translate(positionMatrices[reference()], pos); - } - - void AddCameraRotation(const CameraHandle reference, const GTSL::Quaternion quaternion) - { - rotationMatrices[reference()] *= GTSL::Matrix4(quaternion); - } - - void AddCameraRotation(const CameraHandle reference, const GTSL::Matrix4 matrix4) - { - rotationMatrices[reference()] *= matrix4; - } - - [[nodiscard]] GTSL::Range GetFieldOfViews() const { return fovs; } - void SetFieldOfView(const CameraHandle componentReference, const float32 fov) { fovs[componentReference()] = fov; } - float32 GetFieldOfView(const CameraHandle componentReference) const { return fovs[componentReference()]; } - GTSL::Vector3 GetCameraPosition(CameraHandle cameraHandle) const { return GTSL::Math::GetTranslation(positionMatrices[cameraHandle()]); } - //GTSL::Quaternion GetCameraOrientation(CameraHandle cameraHandle) const { return rotationMatrices[cameraHandle()]; } - -private: - GTSL::Vector positionMatrices; - GTSL::Vector rotationMatrices; - GTSL::Vector fovs; -}; diff --git a/src/ByteEngine/Game/System.hpp b/src/ByteEngine/Game/System.hpp deleted file mode 100644 index d2394e92..00000000 --- a/src/ByteEngine/Game/System.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include "ByteEngine/Object.h" - -#include "ByteEngine/Debug/Assert.h" - -namespace GTSL { - template - class Vector; -} - -template -using Vector = GTSL::Vector; - -class ApplicationManager; - -namespace BE { - /** - * \brief Systems persist across levels and can process world components regardless of the current level. - * Used to instantiate render engines, sound engines, physics engines, AI systems, etc. - */ - class System : public Object { - public: - struct InitializeInfo { - ApplicationManager* AppManager = nullptr; - /** - * \brief Rough estimate for number of components present during average run of the application. - * Can be used for initialization of data structures to allocate "enough" space during start as to avoid as many re-allocations further down the line. - */ - uint32 ScalingFactor = 0; - uint16 SystemId; - Id InstanceName; - }; - System(const InitializeInfo& initializeInfo, const utf8* name) : Object(name), systemId(initializeInfo.SystemId), instanceName(initializeInfo.InstanceName), application_manager_(initializeInfo.AppManager) - { - } - - //struct ShutdownInfo - //{ - // class ApplicationManager* ApplicationManager = nullptr; - //}; - //void Shutdown(const ShutdownInfo& shutdownInfo); - - [[nodiscard]] uint16 GetSystemId() const { return systemId; } - - protected: - - ApplicationManager* GetApplicationManager() const { return application_manager_; } - - private: - friend ApplicationManager; - - uint16 systemId; - Id instanceName; - - ApplicationManager* application_manager_ = nullptr; - }; -} \ No newline at end of file diff --git a/src/ByteEngine/Game/Tasks.h b/src/ByteEngine/Game/Tasks.h deleted file mode 100644 index 319bfcb2..00000000 --- a/src/ByteEngine/Game/Tasks.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -#include -#include -#include -#include - -#include "ByteEngine/Id.h" -#include "ByteEngine/Debug/Assert.h" - -#include "ByteEngine/Handle.hpp" - -class ApplicationManager; -using AccessType = GTSL::Flags; -using TaskAccess = GTSL::Pair; - -namespace AccessTypes { - static constexpr AccessType READ(1), READ_WRITE(4); -} - -struct TaskInfo { - TaskInfo(ApplicationManager* application_manager) : AppManager(application_manager) {} - - class ApplicationManager* AppManager = nullptr; - uint8 InvocationID = 0; -}; - -struct TaskDependency -{ - TaskDependency() = default; - TaskDependency(const GTSL::StringView object, const AccessType access) : AccessedObject(object), Access(access) {} - TaskDependency(const Id object, const AccessType access) : AccessedObject(object), Access(access) {} - - Id AccessedObject; - AccessType Access; -}; - -MAKE_HANDLE(uint32, DispatchedTask); - -template -struct TaskSorter { - explicit TaskSorter(const uint32 num, const ALLOCATOR& allocator) : - currentObjectAccessState(num, allocator), currentObjectAccessCount(num, allocator), - ongoingTasksAccesses(num, allocator), instances(num, allocator) - { - } - - GTSL::Result CanRunTask(const GTSL::Range accesses) { - const auto elementCount = accesses.ElementCount(); - - uint32 res = 0; - - { - GTSL::WriteLock lock(mutex); - - for (uint32 i = 0; i < elementCount; ++i) { - if (currentObjectAccessState[accesses[i].First] == AccessTypes::READ_WRITE) { return GTSL::Result(false); } - if (currentObjectAccessState[accesses[i].First] == AccessTypes::READ && accesses[i].Second == AccessTypes::READ_WRITE) { return GTSL::Result(false); } - } - - for (uint32 i = 0; i < elementCount; ++i) { - currentObjectAccessState[accesses[i].First] = accesses[i].Second; - ++currentObjectAccessCount[accesses[i].First]; - } - - auto insPos = instances.Emplace(); - - res = ongoingTasksAccesses.Emplace(accesses); - - BE_ASSERT(insPos == res, u8""); - } - - return GTSL::Result(DispatchedTaskHandle(res), true); - } - - void ReleaseResources(const DispatchedTaskHandle taskIndex) { - GTSL::WriteLock lock(mutex); - - const auto count = ongoingTasksAccesses[taskIndex()].GetLength(); - auto& accesses = ongoingTasksAccesses[taskIndex()]; - - for (uint32 i = 0; i < count; ++i) { - BE_ASSERT(currentObjectAccessCount[accesses[i].First] != 0, "Oops :/"); - if (--currentObjectAccessCount[accesses[i].First] == 0) { //if object is no longer accessed - currentObjectAccessState[accesses[i].First] = AccessType(); - } - } - - ongoingTasksAccesses.Pop(taskIndex()); - instances.Pop(taskIndex()); - } - - void AddSystem(Id objectName) { - auto lock = GTSL::WriteLock(mutex); - currentObjectAccessState.Emplace(0); - currentObjectAccessCount.Emplace(0); - } - - void AddInstance(const DispatchedTaskHandle dispatched_task_handle, void* instance) { - instances[dispatched_task_handle()].EmplaceBack(instance); - } - - auto GetValidInstances(DispatchedTaskHandle dispatched_task_handle) { - return instances[dispatched_task_handle()]; - } - -private: - GTSL::FixedVector currentObjectAccessState; - GTSL::FixedVector currentObjectAccessCount; - - GTSL::FixedVector, ALLOCATOR> ongoingTasksAccesses; - - GTSL::FixedVector, ALLOCATOR> instances; - - GTSL::ReadWriteMutex mutex; -}; \ No newline at end of file diff --git a/src/ByteEngine/Game/World.cpp b/src/ByteEngine/Game/World.cpp deleted file mode 100644 index c306467b..00000000 --- a/src/ByteEngine/Game/World.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "World.h" - -#include "GTSL/JSON.hpp" - -World::World() : Object(u8"World") -{ -} - -void World::InitializeWorld(const InitializeInfo& initializeInfo) -{ -} - -void World::DestroyWorld(const DestroyInfo& destroyInfo) -{ -} - -void World::Pause() -{ - worldTimeMultiplier = 0; -} diff --git a/src/ByteEngine/Game/World.h b/src/ByteEngine/Game/World.h deleted file mode 100644 index a90a0e94..00000000 --- a/src/ByteEngine/Game/World.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "ByteEngine/Object.h" - -class World : public Object -{ -public: - World(); - ~World() = default; - - struct InitializeInfo - { - class ApplicationManager* GameInstance{ nullptr }; - }; - virtual void InitializeWorld(const InitializeInfo& initializeInfo); - - struct DestroyInfo - { - class ApplicationManager* GameInstance{ nullptr }; - }; - virtual void DestroyWorld(const DestroyInfo& destroyInfo); - - virtual void Pause(); - - void SetWorldTimeMultiplier(const float multiplier) { worldTimeMultiplier = multiplier; } - -protected: - float worldTimeMultiplier = 1; - -}; diff --git a/src/ByteEngine/Game/WorldSystem.hpp b/src/ByteEngine/Game/WorldSystem.hpp deleted file mode 100644 index 67976036..00000000 --- a/src/ByteEngine/Game/WorldSystem.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include "ByteEngine/Game/System.hpp" - -#include - -#include "ByteEngine/Render/LightsRenderGroup.h" - -class WorldSystem : public BE::System { - static void SetPosition(const GTSL::JSON& json, auto system, auto handle) { - auto jsonPosition = json[u8"pos"]; - auto pos = GTSL::Vector3(jsonPosition[0].GetFloat(), jsonPosition[1].GetFloat(), jsonPosition[2].GetFloat()); - system->SetPosition(handle, pos); - } - - static void SetRotation(const GTSL::JSON& json, auto system, auto handle) { - auto jsonRotation = json[u8"rot"]; - if(!jsonRotation) { return; } - auto rot = GTSL::Rotator(GTSL::Math::DegreesToRadians(jsonRotation[0].GetFloat()), GTSL::Math::DegreesToRadians(jsonRotation[1].GetFloat()), GTSL::Math::DegreesToRadians(jsonRotation[2].GetFloat())); - system->SetRotation(handle, GTSL::Quaternion(rot)); - } - - static void SetColor(const GTSL::JSON& json, auto system, auto handle) { - auto jsonColor = json[u8"color"]; - auto color = GTSL::RGBA(jsonColor[0].GetFloat(), jsonColor[1].GetFloat(), jsonColor[2].GetFloat(), jsonColor[3].GetFloat()); - system->SetColor(handle, GTSL::RGB(color.R(), color.G(), color.B())); - } -public: - WorldSystem(const InitializeInfo& initialize_info) : System(initialize_info, u8"WorldSystem") { - GTSL::File file(ResourceManager::GetUserResourcePath(u8"level.json")); - - GTSL::StaticBuffer<8192> fileBuffer(file); - - auto json = GTSL::JSON(GTSL::StringView(fileBuffer), GetTransientAllocator()); - - auto worldName = json[u8"name"].GetStringView(); - - auto* staticMeshSystem = GetApplicationManager()->GetSystem(u8"StaticMeshSystem"); - auto lightsSystem = GetApplicationManager()->GetSystem(u8"LightsRenderGroup"); - - for(auto e : json[u8"elements"]) { - if(auto m = e[u8"type"]; m.GetStringView() == u8"Mesh") { - auto componentName = e[u8"name"]; - auto resourceName = e[u8"mesh"]; - - auto staticMeshHandle = staticMeshSystem->AddStaticMesh(resourceName); - - SetPosition(e, staticMeshSystem, staticMeshHandle); - SetRotation(e, staticMeshSystem, staticMeshHandle); - } - - if(auto m = e[u8"type"]; m.GetStringView() == u8"Light") { - auto componentName = e[u8"name"]; - - auto lightHandle = lightsSystem->CreatePointLight(); - - SetPosition(e, lightsSystem, lightHandle); - SetColor(e, lightsSystem, lightHandle); - } - } - } -}; diff --git a/src/ByteEngine/Graph.hpp b/src/ByteEngine/Graph.hpp deleted file mode 100644 index da36da56..00000000 --- a/src/ByteEngine/Graph.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -template -struct Graph { -private: - - struct Internal { - Internal(T d) : data(d) {} - - ~Internal() { - for(uint32 i = 0; i < downstreamCount; ++i) { - downstream[i] = nullptr; - } - - downstreamCount = 0u; - upstreamCount = 0u; - } - - T data; - Internal* downstream[64] = { nullptr }; - Internal* upstream[64] = { nullptr }; - uint32 downstreamCount = 0, upstreamCount = 0; - }* internal = nullptr; - - bool shared = false; - -public: - explicit Graph(T d) : internal(new Internal(d)) {} - - Graph(Internal* internal) : internal(internal), shared(true) {} - - Graph(Graph&& other) noexcept : internal(other.internal) { - other.internal = nullptr; - } - - Graph(const Graph& other) : internal(new Internal(other.GetData())) { - internal->downstreamCount = other.internal->downstreamCount; - internal->upstreamCount = other.internal->upstreamCount; - - for(uint32 i = 0; i < internal->downstreamCount; ++i) { - internal->downstream[i] = other.internal->downstream[i]; - } - - for(uint32 i = 0; i < internal->upstreamCount; ++i) { - internal->upstream[i] = other.internal->upstream[i]; - } - } - - ~Graph() { - if(internal && !shared) { delete internal; } - internal = nullptr; - } - - void Connect(Graph& other) { - for(uint32 i = 0; i < other.internal->upstreamCount; ++i) { - if(other.internal->upstream[i] == other.internal) { - BE_DEBUG_BREAK; - } - } - - internal->downstream[internal->downstreamCount++] = other.internal; - other.internal->upstream[other.internal->upstreamCount++] = internal; - } - - auto GetParents() const { - GTSL::StaticVector children; - - for(uint32 i = 0; i < internal->upstreamCount; ++i) { - children.EmplaceBack(internal->upstream[i]); - } - - return children; - } - - auto GetChildren() const { - GTSL::StaticVector children; - - for(uint32 i = 0; i < internal->downstreamCount; ++i) { - children.EmplaceBack(internal->downstream[i]); - } - - return children; - } - - T& GetData() { return internal->data; } - const T& GetData() const { return internal->data; } -}; \ No newline at end of file diff --git a/src/ByteEngine/Handle.hpp b/src/ByteEngine/Handle.hpp deleted file mode 100644 index 5d5b8463..00000000 --- a/src/ByteEngine/Handle.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include - -#include "ByteEngine/Core.h" - -template -class Handle -{ -public: - Handle() = default; - ~Handle() = default; - - explicit Handle(C value) noexcept : handle(value) {} - - explicit operator C() const { return handle; } - - C operator()() const { return handle; } - - bool operator==(const Handle& other) const { return handle == other.handle; } - bool operator!=(const Handle& other) const { return handle != other.handle; } -private: - C handle; - - friend Handle; -}; - -template -class Handle -{ -public: - Handle() = default; - ~Handle() = default; - - explicit Handle(C value) noexcept : handle(value) {} - - explicit operator C() const { return handle; } - - C operator()() const { return handle; } - - bool operator==(const Handle & other) const { return handle == other.handle; } - bool operator!=(const Handle & other) const { return handle != other.handle; } - - explicit operator bool() const { return handle != static_cast(~0); } -private: - C handle = static_cast(~0); -}; - -#define MAKE_HANDLE(type, name) using name##Handle = Handle; \ No newline at end of file diff --git a/src/ByteEngine/Id.h b/src/ByteEngine/Id.h deleted file mode 100644 index fb3061aa..00000000 --- a/src/ByteEngine/Id.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "Core.h" -#include -#include - -class Id -{ -public: - Id() = default; - - template - constexpr explicit Id(char8_t const (&s)[N]) : hashedName(s) {} - - constexpr explicit Id(const utf8* name) noexcept : hashedName(name), stringName(name) {} - constexpr explicit Id(const GTSL::Range name) noexcept : hashedName(name), stringName(name) {} - Id(const GTSL::Id64 name) noexcept : hashedName(name) {} - //explicit Id(const uint64 value) noexcept : hashedName(value) {} - - //[[nodiscard]] const utf8* GetString() const { return GTSL::Range(stringName).begin(); } - [[nodiscard]] constexpr GTSL::Id64 GetHash() const { return hashedName; } - - explicit operator GTSL::Id64() const { return hashedName; } - //explicit operator const utf8* () const { return GTSL::Range(stringName).(); } - explicit operator GTSL::Range() const { return stringName; } - explicit operator bool() const { return hashedName.GetID(); } - - Id& operator=(const utf8* name) { hashedName = name; stringName = GTSL::Range(name); return *this; } - Id& operator=(const GTSL::Id64 other) { hashedName = other; return *this; } - - bool operator==(const Id other) const { return hashedName == other.hashedName; } - //bool operator==(const GTSL::Id64 other) const { return hashedName == other; } - - uint64 operator()() const { return hashedName.GetID(); } - explicit operator uint64() const { return hashedName(); } -private: - GTSL::Id64 hashedName; - GTSL::ShortString<64> stringName; -}; - -namespace GTSL { - template<> - struct Hash { - uint64 value = 0; - constexpr Hash(const Id& id) : value(id.GetHash()) {} - constexpr operator uint64() const { return value; } - }; - - Hash(Id) -> Hash; -} \ No newline at end of file diff --git a/src/ByteEngine/Light.cpp b/src/ByteEngine/Light.cpp deleted file mode 100644 index ab1870b4..00000000 --- a/src/ByteEngine/Light.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "Light.h" - -/* -void Light::SetColor(const uint16 ColorTemperature) -{ - //CODE BY TANNER HELLAND - //http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ - - const uint16 Temperature_ = ColorTemperature / 100; - - //----------RED---------- - if (Temperature_ <= 66) - { - Color.R = 255; - } - else - { - Color.R = Temperature_ - 60; - Color.R = 329.698727446 * (Color.R ^ -0.1332047592); - - if (Color.R < 0) - { - Color.R = 0; - } - if (Color.R > 255) - { - Color.R = 255; - } - } - //----------RED---------- - - //----------GREEN---------- - if (Temperature_ <= 66) - { - Color.G = Temperature_; - Color.G = 99.4708025861 * Ln(Color.G) - 161.1195681661; - if (Color.G < 0) - { - Color.G = 0; - } - if (Color.G > 255) - { - Color.G = 255; - } - } - else - { - Color.G = Temperature_ - 60; - Color.G = 288.1221695283 * (Color.G ^ -0.0755148492); - - if (Color.G < 0) - { - Color.G = 0; - } - if (Color.G > 255) - { - Color.G = 255; - } - } - //----------GREEN---------- - - //----------BLUE---------- - if (Temperature_ >= 66) - { - Color.B = 255; - } - else - { - if (Temperature_ <= 19) - { - Color.B = 0; - } - else - { - Color.B = Temperature_ - 10; - Color.B = 138.5177312231 * Ln(Color.B) - 305.0447927307; - - if (Color.B < 0) - { - Color.B = 0; - } - if (Color.B > 255) - { - Color.B = 255; - } - } - } - //----------BLUE---------- -} -*/ diff --git a/src/ByteEngine/Light.h b/src/ByteEngine/Light.h deleted file mode 100644 index 39222e7a..00000000 --- a/src/ByteEngine/Light.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "Core.h" - -#include - -class Light -{ -public: - Light() = default; - ~Light() = default; - - //Returns the value of lumens for this light. - [[nodiscard]] float GetLumens() const { return Lumens; } - //Returns the color for this light. - //[[nodiscard]] GTSL::RGB GetRGB() const { return Color; } - - //Sets Lumens as NewLumens. - void SetLumens(const float NewLumens) { Lumens = NewLumens; } - //Sets Color as NewColor. - //void SetColor(const GTSL::RGB& NewColor) { Color = NewColor; } - //Sets Color from a color temperature. - void SetColor(const uint16 ColorTemperature); - -protected: - //Determines the intensity of the light in lumens. - float Lumens = 1000.0f; - //GTSL::RGB Color{ 0.0f, 0.0f, 0.0f }; -}; diff --git a/src/ByteEngine/MetaStruct.hpp b/src/ByteEngine/MetaStruct.hpp deleted file mode 100644 index cd05ae9e..00000000 --- a/src/ByteEngine/MetaStruct.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -template -struct fixed_string { - constexpr fixed_string(const char(&foo)[N + 1]) { - std::copy_n(foo, N + 1, data); - } - - auto operator<=>(const fixed_string&) const = default; - char data[N + 1] = {}; -}; - -template -fixed_string(const char(&str)[N])->fixed_string; - -template -struct tag_and_value { - T value; -}; - -template -struct arg_type { - template - constexpr auto operator=(T t) const { - return tag_and_value{ std::move(t) }; - } -}; - -template -inline constexpr auto arg = arg_type{}; - -template -struct member { - //template - //constexpr member(tag_and_value tv) : value(std::move(tv.value)) {} - - constexpr static auto tag() { return TAG; } - - using element_type = T; -}; - -template -struct meta_struct : MEMBERS... {}; \ No newline at end of file diff --git a/src/ByteEngine/Network/ConnectionHandler.hpp b/src/ByteEngine/Network/ConnectionHandler.hpp deleted file mode 100644 index a09f7f42..00000000 --- a/src/ByteEngine/Network/ConnectionHandler.hpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "ByteEngine/Game/System.hpp" -#include - -class ConnectionHandler : public BE::System { -public: - ConnectionHandler(const InitializeInfo& initializeInfo) : System(initializeInfo, u8"ConnectionHandler"), clients(16, GetPersistentAllocator()) - { - source.Address[0] = 127; - source.Address[1] = 0; - source.Address[2] = 0; - source.Address[3] = 1; - source.Port = 25565; - - socket.Open(source, false); - } - - void poll() - { - GTSL::IPv4Endpoint sender; - - socket.Receive(&sender, {}); - } - - enum class ConnectionAttemptCodes { - OK, NO_MORE_SLOTS, ALREADY_EXISTS - }; - - MAKE_HANDLE(uint32, Connection); - - GTSL::Result OpenConnection(GTSL::StringView connection_name, const GTSL::IPv4Endpoint endpoint) { - if (clients.GetLength() == maxClients) { return { ConnectionHandle(), ConnectionAttemptCodes::NO_MORE_SLOTS }; } //if we already exhausted our client capacity, fail connection - - auto adressLookup = lookupClientBasedOnAddress(endpoint); - if (adressLookup) { return { ConnectionHandle(), ConnectionAttemptCodes::ALREADY_EXISTS }; } //if connection with address exists, reject - - //todo: check salt - - auto clientIndex = clients.GetLength(); - - auto& client = clients.EmplaceBack(GetPersistentAllocator()); - - client.Name = connection_name; - client.Salt = randomNumberGenerator(); - client.ConnectionState = ClientData::ConnectionStates::CONNECTING; - - return { ConnectionHandle(clientIndex), ConnectionAttemptCodes::OK }; - } - -private: - static constexpr uint32 BUFFER_CAPACITY = 1024u, ACK_DEPTH = 32u; - - GTSL::Math::RandomSeed randomNumberGenerator; - - struct Header { - /** - * \brief Increments with each packet sent, used to check ordering. Wraps around when overflowed. - */ - uint16 Sequence; - - /** - * \brief Stores the most recent packet sequence number received. - */ - uint16 LastSequenceNumberReceived; - - /** - * \brief Signals whether each one of the last 32 consecutive packets where received. - */ - GTSL::Bitfield AckBits; - }; - - GTSL::Socket socket; - - GTSL::IPv4Endpoint source; - - //server - uint32 maxClients = 0; - -#undef NULL - - struct ClientData { - ClientData(const BE::PAR& allocator) : Name(allocator) {} - - GTSL::String Name; - uint64 Salt = 0; - GTSL::IPv4Endpoint Address; - enum class ConnectionStates { NULL, CONNECTING, OK, LOST } ConnectionState; - }; - Vector clients; - - /** - * \brief Looks for a connected client matching the address provided. - * \param address Address to lookup - * \return Result, number is client index, state is whether it was found - */ - GTSL::Result lookupClientBasedOnAddress(const GTSL::IPv4Endpoint address) { - if(auto r = GTSL::Find(clients, [address](const ClientData& client_data) { return client_data.Address.Address == address.Address && client_data.Address.Port == address.Port; })) { - return { static_cast(clients.end() - r.Get()), true }; - } - - return { 0, false }; - } - //server - - //client - uint32 sentSequenceBuffer[BUFFER_CAPACITY]{ ~0u }; - - struct PacketData { - bool Acknowledged = false; - GTSL::Microseconds SendTime; - }; - PacketData sentPacketBuffer[BUFFER_CAPACITY]; - - PacketData* insertPacketData(uint16 sequence) { - const uint32 index = sequence % BUFFER_CAPACITY; - sentSequenceBuffer[index] = sequence; - return &sentPacketBuffer[index]; - } - PacketData* getPacketData(const uint16 sequence) { - const uint16 index = sequence % BUFFER_CAPACITY; - - if(sentSequenceBuffer[index] == sequence) { - return &sentPacketBuffer[index]; - } - - return nullptr; - } - - uint16 sendPacketSequenceNumber = 0; - uint16 receivedPacketSequenceNumber = 0; - //client - - static bool sequence_greater_than(uint16_t s1, uint16_t s2) { - return ((s1 > s2) && (s1 - s2 <= 32768)) || ((s1 < s2) && (s2 - s1 > 32768)); - } - - //Unfortunately, on the receive side packets arrive out of order and some are lost. - //Under ridiculously high packet loss (99%) I’ve seen old sequence buffer entries stick around from before the previous sequence number wrap at 65535 and break my ack logic - //(leading to false acks and broken reliability where the sender thinks the other side has received something they haven’t…). - //The solution to this problem is to walk between the previous highest insert sequence and the new insert sequence(if it is more recent) - //and clear those entries in the sequence buffer to 0xFFFFFFFF. - //Now in the common case, insert is very close to constant time, but worst case is linear where n is the number of sequence entries between the previous highest insert sequence and the current insert sequence. - - void processPacket() { - Header header; - - if(sequence_greater_than(header.Sequence, receivedPacketSequenceNumber)) { - //for(uint32 i = receivedPacketSequenceNumber; i < header.Sequence - 1; ++i) { //clear every slot in between - // sentSequenceBuffer[i] = ~0u; - //} - - receivedPacketSequenceNumber = header.Sequence; - - sentSequenceBuffer[header.Sequence] = receivedPacketSequenceNumber; - - for(uint32 i = 0, j = header.LastSequenceNumberReceived; i < ACK_DEPTH; ++i, ++j) { - bool val; - - header.AckBits.Get(ACK_DEPTH - 1 - i, val); - - if(val) { - sentPacketBuffer[j % BUFFER_CAPACITY].Acknowledged = true; - } - } - } - } - - void sendPacket() { - Header header; - header.Sequence = sendPacketSequenceNumber; - header.LastSequenceNumberReceived = receivedPacketSequenceNumber; - - for(uint32 i = 0; i < ACK_DEPTH; ++i) { - auto& packet = sentPacketBuffer[(receivedPacketSequenceNumber - i) % BUFFER_CAPACITY]; - header.AckBits.Set(ACK_DEPTH - 1 - i, packet.Acknowledged); - } - - ++sendPacketSequenceNumber; - } -}; \ No newline at end of file diff --git a/src/ByteEngine/Object.cpp b/src/ByteEngine/Object.cpp deleted file mode 100644 index 344b1f1b..00000000 --- a/src/ByteEngine/Object.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "ByteEngine/Object.h" - -#include - - -#include "ByteEngine/Application/Application.h" - -BE::Logger* Object::getLogger() const { return BE::Application::Get()->GetLogger(); } - -uint8 Object::getThread() const { return GTSL::Thread::ThisTreadID(); } diff --git a/src/ByteEngine/Object.h b/src/ByteEngine/Object.h deleted file mode 100644 index ef8e0f1e..00000000 --- a/src/ByteEngine/Object.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include -#include - -#include "Application/AllocatorReferences.h" - -namespace BE { - class Logger; -} - -/** - * \brief Base class for most non-data only classes in the engine. - */ -class Object { -public: - Object() = default; - - // Object(const utf8* objectName = u8"Object") : objectName(objectName) {} - - Object(const GTSL::StringView name) : objectName(name) {} - - ~Object() = default; - - [[nodiscard]] auto& GetName() const { return objectName; } - - [[nodiscard]] BE::PersistentAllocatorReference GetPersistentAllocator() const { - return BE::PersistentAllocatorReference(GetName()); - } - - [[nodiscard]] BE::TransientAllocatorReference GetTransientAllocator() const { - return BE::TransientAllocatorReference(GetName()); - } - -protected: - [[nodiscard]] BE::Logger* getLogger() const; - uint8 getThread() const; - -private: - GTSL::ShortString<128> objectName = u8"Object"; -}; - -#ifdef BE_DEBUG -#define BE_LOG_SUCCESS(...) this->getLogger()->PrintObjectLog(this, BE::Logger::VerbosityLevel::SUCCESS, __VA_ARGS__); -#define BE_LOG_MESSAGE(...) this->getLogger()->PrintObjectLog(this, BE::Logger::VerbosityLevel::MESSAGE, __VA_ARGS__); -#define BE_LOG_WARNING(...) this->getLogger()->PrintObjectLog(this, BE::Logger::VerbosityLevel::WARNING, __VA_ARGS__); -#define BE_LOG_ERROR(...) this->getLogger()->PrintObjectLog(this, BE::Logger::VerbosityLevel::FATAL, __VA_ARGS__); -#define BE_LOG_LEVEL(Level) this->getLogger()->SetMinLogLevel(Level); - -//#define BE_BASIC_LOG_SUCCESS(...) BE::Application::Get()->GetLogger()->PrintBasicLog(BE::Logger::VerbosityLevel::SUCCESS, __VA_ARGS__); -//#define BE_BASIC_LOG_MESSAGE(...) BE::Application::Get()->GetLogger()->PrintBasicLog(BE::Logger::VerbosityLevel::MESSAGE, __VA_ARGS__); -//#define BE_BASIC_LOG_WARNING(...) BE::Application::Get()->GetLogger()->PrintBasicLog(BE::Logger::VerbosityLevel::WARNING, __VA_ARGS__); -//#define BE_BASIC_LOG_ERROR(...) BE::Application::Get()->GetLogger()->PrintBasicLog(BE::Logger::VerbosityLevel::FATAL, __VA_ARGS__); -#else -#define BE_LOG_SUCCESS(Text, ...) -#define BE_LOG_MESSAGE(Text, ...) -#define BE_LOG_WARNING(Text, ...) -#define BE_LOG_ERROR(Text, ...) -#define BE_LOG_LEVEL(_Level) -#define BE_BASIC_LOG_SUCCESS(Text, ...) -#define BE_BASIC_LOG_MESSAGE(Text, ...) -#define BE_BASIC_LOG_WARNING(Text, ...) -#define BE_BASIC_LOG_ERROR(Text, ...) -#endif \ No newline at end of file diff --git a/src/ByteEngine/Physics/ForceGenerator.h b/src/ByteEngine/Physics/ForceGenerator.h deleted file mode 100644 index c66b19f1..00000000 --- a/src/ByteEngine/Physics/ForceGenerator.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -struct ForceInstructions -{ -}; - -class ForceGenerator -{ - /** - * \brief Determines the intensity at which this magnet force generator pushes or pulls objects. When positive it will repel objects, when positive it will attract them. - */ - float intensity = 0; - -public: - virtual const char* GetForceType() = 0; - virtual ForceInstructions GetForceInstructions(); - - auto& GetIntensity() { return intensity; } -}; diff --git a/src/ByteEngine/Physics/ForceGenerators.h b/src/ByteEngine/Physics/ForceGenerators.h deleted file mode 100644 index 90e20f89..00000000 --- a/src/ByteEngine/Physics/ForceGenerators.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "ForceGenerator.h" - -#include - -#include "Utility/Shapes/SphereWithFallof.h" -#include "Utility/Shapes/BoxWithFalloff.h" -#include "Utility/Shapes/ConeWithFalloff.h" - -class ExplosionGenerator : public ForceGenerator -{ - SphereWithFalloff effectVolume = 0; - -public: - const char* GetForceType() override { return "Explosion"; } -}; - -class BuoyancyGenerator : public ForceGenerator -{ - /** - * \brief Fluid weight(KG) per cubic meter. E.I: water is 1000kg. - */ - float fluidWeight = 1000; - - Box effectVolume; -public: - const char* GetForceType() override { return "Buoyancy"; } -}; - -class MagnetGenerator : public ForceGenerator -{ - SphereWithFalloff effectVolume; - -public: - const char* GetForceType() override { return "Magnet"; } -}; - -class WindGenerator : public ForceGenerator -{ - GTSL::Vector3 windDirection; - BoxWithFalloff effectVolume; - -public: - const char* GetForceType() override { return "Wind"; } -}; - -class DirectionalWindGenerator : public ForceGenerator -{ - GTSL::Quaternion windOrientation; - ConeWithFalloff windDirection; - -public: - const char* GetForceType() override { return "Directional Wind"; } -}; diff --git a/src/ByteEngine/Physics/HitResult.h b/src/ByteEngine/Physics/HitResult.h deleted file mode 100644 index e439f052..00000000 --- a/src/ByteEngine/Physics/HitResult.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -struct HitResult { - /** - * \brief Defines whether there was hit or not.\n - * true = there was a collision.\n - * false = there was no collision. - */ - bool WasHit = false; - - /** - * \brief Defines the position (in world space) of the hit. - */ - GTSL::Vector3 Position; - - GTSL::Vector3 PointOnA; - - GTSL::Vector3 PointOnB; - - /** - * \brief Defines the normal (in world space) of the hit. - */ - GTSL::Vector3 Normal; - - /** - * \brief Defines the penetration distance of the two colliding bodies. This is along the HitNormal. - */ - float32 T = 0; -}; diff --git a/src/ByteEngine/Physics/PhysicsWorld.cpp b/src/ByteEngine/Physics/PhysicsWorld.cpp deleted file mode 100644 index 7c9d1d84..00000000 --- a/src/ByteEngine/Physics/PhysicsWorld.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "PhysicsWorld.h" - - -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Resources/StaticMeshResourceManager.h" - -PhysicsWorld::PhysicsWorld(const InitializeInfo& initialize_info) : System(initialize_info, u8"PhysicsWorld"), physicsObjects(32, GetPersistentAllocator()), PhysicsObjectTypeIndentifier(initialize_info.AppManager->RegisterType(this, u8"PhysicsObject")) -{ - //initialize_info.ApplicationManager->AddTask(this, u8"onUpdate", &PhysicsWorld::onUpdate, DependencyBlock(TypedDependency(u8"StaticMeshRenderGroup")), u8"GameplayStart", u8"GameplayEnd"); - - //onStaticMeshInfoLoadedHandle = initialize_info.ApplicationManager-> - // (this, u8"onStaticMeshInfoLoad", DependencyBlock(TypedDependency(u8"StaticMeshResourceManager", AccessTypes::READ)), &PhysicsWorld::onStaticMeshInfoLoaded); - //onStaticMeshLoadedHandle = initialize_info.ApplicationManager->RegisterTask(this, u8"onStaticMeshLoad", DependencyBlock(TypedDependency(u8"StaticMeshResourceManager", AccessTypes::READ)), &PhysicsWorld::onStaticMeshLoaded); - - boundlessForces.EmplaceBack(0, -10, 0, 0); -} - -PhysicsWorld::PhysicsObjectHandle PhysicsWorld::AddPhysicsObject(StaticMeshSystem::StaticMeshHandle static_mesh_handle) -{ - auto objectIndex = physicsObjects.Emplace(GetPersistentAllocator()); - physicsObjects[objectIndex].Handle = static_mesh_handle; - - auto* staticMeshResourceManager = GetApplicationManager()->GetSystem(u8"StaticMeshResourceManager"); - auto* staticMeshSystem = GetApplicationManager()->GetSystem(u8"StaticMeshSystem"); - - staticMeshResourceManager->LoadStaticMeshInfo(GetApplicationManager(), staticMeshSystem->GetMeshName(static_mesh_handle), onStaticMeshInfoLoadedHandle, GTSL::MoveRef(objectIndex)); - - return GetApplicationManager()->MakeHandle(PhysicsObjectTypeIndentifier, objectIndex); -} - -void PhysicsWorld::onUpdate(TaskInfo taskInfo, StaticMeshSystem* static_mesh_render_group) -{ - auto deltaMicroseconds = BE::Application::Get()->GetClock()->GetDeltaTime(); - - auto deltaSeconds = deltaMicroseconds.As(); - - GTSL::Vector4 accumulatedUnboundedForces; - for (auto f : boundlessForces) { accumulatedUnboundedForces += f; } - - //for(auto& a : physicsObjects) { - // for(auto& b : physicsObjects) { - // if (auto hit = intersect(a, b); hit.WasHit) { - // const auto totalInverseMass = a.inverseMass + b.inverseMass; - // const auto totalElasticity = a.restitutionFactor * b.restitutionFactor; - // - // const auto vAB = a.velocity - b.velocity; - // const auto impulseJ = -(1.0f + totalElasticity) * GTSL::Math::DotProduct(vAB, hit.Normal) / totalInverseMass; - // const auto vecImpulse = hit.Normal * impulseJ; - // - // applyImpulseLinear(&a, vecImpulse); - // applyImpulseLinear(&b, -vecImpulse); - // - // const auto tA = a.inverseMass / totalInverseMass; - // const auto tB = b.inverseMass / totalInverseMass; - // - // const auto ds = hit.PointOnB - hit.PointOnA; - // a.position += ds * tA; - // b.position -= ds * tB; - // } - // } - //} - - for (auto i : loaded) { - auto& e = physicsObjects[i]; - - //semi implicit euler - e.velocity += accumulatedUnboundedForces * deltaSeconds; - e.position += e.velocity * deltaSeconds; - //semi implicit euler - - static_mesh_render_group->SetPosition(e.Handle, GTSL::Vector3(e.position)); - } -} - -void PhysicsWorld::onStaticMeshInfoLoaded(TaskInfo taskInfo, StaticMeshResourceManager* staticMeshResourceManager, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo, uint32 buffer) -{ - auto& mesh = physicsObjects[buffer]; - - mesh.aabb = staticMeshInfo.BoundingBox; - mesh.radius = staticMeshInfo.BoundingRadius; - - physicsObjects[buffer].Buffer.Allocate(staticMeshInfo.GetVertexSize() * staticMeshInfo.GetVertexCount() + staticMeshInfo.GetIndexSize() * staticMeshInfo.GetIndexCount() + 32, 16); - - //staticMeshResourceManager->LoadStaticMesh(taskInfo.ApplicationManager, staticMeshInfo, 2, GTSL::Range(physicsObjects[buffer].Buffer.GetCapacity(), physicsObjects[buffer].Buffer.GetData()), onStaticMeshLoadedHandle, GTSL::MoveRef(buffer)); -} - -void PhysicsWorld::onStaticMeshLoaded(TaskInfo taskInfo, StaticMeshResourceManager* staticMeshResourceManager, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo, uint32 index) -{ - loaded.EmplaceBack(index); -} diff --git a/src/ByteEngine/Physics/PhysicsWorld.h b/src/ByteEngine/Physics/PhysicsWorld.h deleted file mode 100644 index 80bbeb08..00000000 --- a/src/ByteEngine/Physics/PhysicsWorld.h +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "HitResult.h" -#include "ByteEngine/Game/System.hpp" -#include "ByteEngine/Handle.hpp" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Render/StaticMeshSystem.h" -#include "ByteEngine/Resources/StaticMeshResourceManager.h" - -class StaticMeshResourceManager; - -class PhysicsWorld : public BE::System { -public: - DECLARE_BE_TYPE(PhysicsObject) - - PhysicsWorld(const InitializeInfo& initialize_info); - - PhysicsObjectHandle AddPhysicsObject(StaticMeshSystem::StaticMeshHandle); - - GTSL::Vector4 GetPosition(const PhysicsObjectHandle physics_object_handle) const { return physicsObjects[physics_object_handle()].position; } - - void SetMass(const PhysicsObjectHandle physics_object_handle, float32 massKg) { physicsObjects[physics_object_handle()].inverseMass = 1.f / massKg; } - - void SetDampFactor(const float32 newDampFactor) { dampFactor = newDampFactor; } - - [[nodiscard]] auto GetAirDensity() const { return dampFactor; } - - HitResult TraceRay(const GTSL::Vector3 start, const GTSL::Vector3 end); - -private: - /** - * \brief Specifies how much speed the to remove from entities.\n - * Default value is 0.0001. - */ - float32 dampFactor = 0.001f; - - /** - * \brief Defines the number of substeps used for simulation. Default is 1, which mean only one iteration will run each frame. - */ - uint16 simSubSteps = 1; - - void doBroadPhase(); - void doNarrowPhase(); - void solveDynamicObjects(double _UpdateTime); - - void insertObject() { - GTSL::Vector3 aabb, pos; - - GTSL::Bitfield<3> bitfield; - - bitfield[0] = pos.X() > 0.0f; bitfield[1] = pos.Y() > 0.0f; bitfield[2] = pos.Z() > 0.0f; - } - - void onUpdate(TaskInfo taskInfo, StaticMeshSystem* static_mesh_system); - - void onStaticMeshInfoLoaded(TaskInfo taskInfo, StaticMeshResourceManager* staticMeshResourceManager, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo, uint32); - void onStaticMeshLoaded(TaskInfo taskInfo, StaticMeshResourceManager* staticMeshResourceManager, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo, uint32); - - struct PhysicsObject { - GTSL::Vector4 velocity, angularVelocity, acceleration, position, centerOfMass; - GTSL::Quaternion orientation; - - //kg - float32 mass = 1.0f, inverseMass = 1.0f; - float32 restitutionFactor = 0.5f; - - //shape - float32 radius = 1.0f; - - StaticMeshSystem::StaticMeshHandle Handle; - GTSL::Vector3 aabb; - - PhysicsObject(const BE::PAR& allocator) : Buffer(allocator) {} - - GTSL::Buffer Buffer; - }; - GTSL::FixedVector physicsObjects; - - GTSL::StaticVector boundlessForces; - - GTSL::StaticVector loaded; - - TaskHandle onStaticMeshInfoLoadedHandle; - TaskHandle onStaticMeshLoadedHandle; - - void applyImpulseLinear(PhysicsObject* a, const GTSL::Vector4 impulse) { - a->velocity += impulse * a->inverseMass; - } - - void applyImpulseAngular(PhysicsObject* a, const GTSL::Vector4 impulse) { - a->angularVelocity += getInverseWorldSpaceInertiaTensor(*a) * impulse; - - constexpr auto MAX_ANGULAR_SPEED = 30.f; - - if(GTSL::Math::LengthSquared(a->angularVelocity) > MAX_ANGULAR_SPEED * MAX_ANGULAR_SPEED) { - GTSL::Math::Normalize(a->angularVelocity); - a->angularVelocity *= MAX_ANGULAR_SPEED; - } - } - - HitResult intersect(PhysicsObject& a, PhysicsObject& b) { - auto ab = b.position - a.position; - auto abRadius = a.radius + b.radius; - - HitResult hit; - hit.WasHit = GTSL::Math::LengthSquared(ab) <= abRadius * abRadius; - //hit.Normal = GTSL::Math::Normalized(ab); - //hit.Position = a.position + hit.Normal * a.radius; - - return hit; - } - - GTSL::Matrix4 getInertiaTensor(const PhysicsObject& a) { - return GTSL::Matrix4{ 2 * a.radius * a.radius / 5.f }; - } - - GTSL::Matrix4 getInverseWorldSpaceInertiaTensor(const PhysicsObject& a) { - auto inertiaTensor = getInertiaTensor(a); - auto inverted = GTSL::Math::Inverse(inertiaTensor) * a.inverseMass; - auto orientation = GTSL::Matrix4(a.orientation); - //inverted = orientation * inverted * orientation.Transpose(); - return inverted; - } -}; diff --git a/src/ByteEngine/Physics/Queries.h b/src/ByteEngine/Physics/Queries.h deleted file mode 100644 index 4cd9f0fc..00000000 --- a/src/ByteEngine/Physics/Queries.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "ByteEngine/Core.h" -#include "ByteEngine/Application/AllocatorReferences.h" - -class Obj -{ -public: - GTSL::Vector3 GetPosition() { return GTSL::Vector3(); } - - GTSL::Vector3 GetSupportPointInDirection(const GTSL::Vector3& direction) { - return GTSL::Vector3(); - } -}; \ No newline at end of file diff --git a/src/ByteEngine/Physics/RigidBody.h b/src/ByteEngine/Physics/RigidBody.h deleted file mode 100644 index 25459190..00000000 --- a/src/ByteEngine/Physics/RigidBody.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -class RigidBody -{ - /** - * \brief Specifies the inverse mass of this body. - */ - float inverseBodyMass = 1; - -public: - void SetMass(const float mass) { inverseBodyMass = 1 / mass; } -}; diff --git a/src/ByteEngine/PlayableAsset.h b/src/ByteEngine/PlayableAsset.h deleted file mode 100644 index f7a649cc..00000000 --- a/src/ByteEngine/PlayableAsset.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "Core.h" -#include - -class PlayableAsset -{ -public: - - void Update(const GTSL::Microseconds deltaTime) { elapsedTime += deltaTime; } - - [[nodiscard]] GTSL::Microseconds GetCurrentFrame() const { return elapsedTime; } - [[nodiscard]] uint32 GetTotalFrameCount() const { return totalFrames; } - -private: - GTSL::Microseconds elapsedTime; - const uint64 totalFrames = 0; - -}; diff --git a/src/ByteEngine/Render/Culling.h b/src/ByteEngine/Render/Culling.h deleted file mode 100644 index 8047ebe7..00000000 --- a/src/ByteEngine/Render/Culling.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "ByteEngine/Core.h" -#include - -struct vec4; - -//GTSL::Vector3 ttt(const float32 near, const float32 far, const float32 fov, GTSL::Extent2D size, const GTSL::Matrix4& a) { -// GTSL::Vector3 farPoint(0, 0, far); -// -// auto xSize = far * GTSL::Math::Tangent(fov / 2); -// -// a * farPoint; -// -// GTSL::Vector3 halfSize(); -//} - -inline float32 projectSphere(GTSL::Vector3 cameraPosition, GTSL::Vector3 spherePosition, const float32 radius) { - return GTSL::Math::Tangent(radius * radius / GTSL::Math::DistanceSquared(spherePosition, cameraPosition)); -} - -inline void projectSpheres(const GTSL::Vector3 cameraPosition, GTSL::MultiRange spherePositions, auto& results) { - using float8x = GTSL::SIMD; - - float8x cameraX(cameraPosition[0]), cameraY(cameraPosition[1]), cameraZ(cameraPosition[2]); - - for(uint32 i = 0; i < spherePositions.GetLength(); i += 8) { - float8x sphereX(spherePositions.GetPointer<0>(i)), sphereY(spherePositions.GetPointer<1>(i)), sphereZ(spherePositions.GetPointer<2>(i)), sphereRadiuses(spherePositions.GetPointer<3>(i)); - - float8x distanceX = cameraX - sphereX, distanceY = cameraY - sphereY, distanceZ = cameraZ - sphereZ; - float8x distanceSquared = distanceX * distanceX + distanceY * distanceY + distanceZ * distanceZ; - - auto result = (sphereRadiuses * sphereRadiuses) / distanceSquared; - //auto result = GTSL::Math::Tangent((sphereRadiuses * sphereRadiuses) / distanceSquared); - - float32 res[8]; - result.CopyTo(res); - - for (auto j = 0; j < 8; ++j) { results.EmplaceBack(res[j]); } - } -} - -inline float32 test(const GTSL::Vector3 cameraPosition, const GTSL::Vector3 spherePosition, const float32 radius, const float32 fov) -{ - auto size = projectSphere(cameraPosition, spherePosition, radius); - return GTSL::Math::MapToRangeZeroToOne(fov, 180.f, 1.0f); -} - -inline uint8 SelectLOD(const float32 percentage, const uint8 minLOD, const uint8 maxLOD) { - return static_cast(GTSL::Math::MapToRange(percentage, 0, 1, minLOD, maxLOD)); -} - - -using AABB2 = GTSL::Vector2; -using AABB = GTSL::Vector3; - -inline void ScreenCull(const GTSL::Range aabbs) { - GTSL::StaticVector front; front.EmplaceBack(); - - for(uint32 i = 0; i < aabbs.ElementCount(); ++i) { - - } -} \ No newline at end of file diff --git a/src/ByteEngine/Render/LightsRenderGroup.h b/src/ByteEngine/Render/LightsRenderGroup.h deleted file mode 100644 index 0ada1e30..00000000 --- a/src/ByteEngine/Render/LightsRenderGroup.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include "ByteEngine/Game/System.hpp" -#include "ByteEngine/Handle.hpp" - -#include -#include -#include - -class LightsRenderGroup : public BE::System { -public: - MAKE_HANDLE(uint32, DirectionalLight) - MAKE_HANDLE(uint32, PointLight) - - LightsRenderGroup(const InitializeInfo& initializeInfo) : System(initializeInfo, u8"LightsRenderGroup"), directionalLights(8, GetPersistentAllocator()), pointLights(16, GetPersistentAllocator()) - { - } - - DirectionalLightHandle CreateDirectionalLight() { - return DirectionalLightHandle(directionalLights.Emplace()); - } - - PointLightHandle CreatePointLight() { - auto handle = PointLightHandle(pointLights.Emplace()); - auto& light = pointLights[handle()]; - light.Lumens = 1.0f; light.Color.R() = 1.0f; light.Color.G() = 1.0f; light.Color.B() = 1.0f; - light.Radius = 0.5f; - GetApplicationManager()->DispatchEvent(this, EventHandle(u8"OnAddPointLight"), GTSL::MoveRef(handle)); - return handle; - } - - void SetRotation(const DirectionalLightHandle lightHandle, const GTSL::Rotator rotator) { - directionalLights[lightHandle()].Rotation = rotator; - } - - void SetColor(const DirectionalLightHandle lightHandle, const GTSL::RGBA color) { - directionalLights[lightHandle()].Color = color; - } - - void SetColor(PointLightHandle point_light_handle, const GTSL::RGB color) { - auto& light = pointLights[point_light_handle()]; - light.Color = color; - GetApplicationManager()->DispatchEvent(this, EventHandle(u8"OnUpdatePointLight"), GTSL::MoveRef(point_light_handle), GTSL::MoveRef(light.Position), GTSL::MoveRef(light.Color), GTSL::MoveRef(light.Lumens), GTSL::MoveRef(light.Radius)); - } - - void SetLumens(PointLightHandle point_light_handle, const float32 lumens) { - auto& light = pointLights[point_light_handle()]; - light.Lumens = lumens; - GetApplicationManager()->DispatchEvent(this, EventHandle(u8"OnUpdatePointLight"), GTSL::MoveRef(point_light_handle), GTSL::MoveRef(light.Position), GTSL::MoveRef(light.Color), GTSL::MoveRef(light.Lumens), GTSL::MoveRef(light.Radius)); - } - - void SetPosition(PointLightHandle point_light_handle, GTSL::Vector3 position) { - auto& light = pointLights[point_light_handle()]; - light.Position = position; - GetApplicationManager()->DispatchEvent(this, EventHandle(u8"OnUpdatePointLight"), GTSL::MoveRef(point_light_handle), GTSL::MoveRef(light.Position), GTSL::MoveRef(light.Color), GTSL::MoveRef(light.Lumens), GTSL::MoveRef(light.Radius)); - } - - void SetRadius(PointLightHandle point_light_handle, const float32 radius) { - auto& light = pointLights[point_light_handle()]; - light.Radius = radius; - GetApplicationManager()->DispatchEvent(this, EventHandle(u8"OnUpdatePointLight"), GTSL::MoveRef(point_light_handle), GTSL::MoveRef(light.Position), GTSL::MoveRef(light.Color), GTSL::MoveRef(light.Lumens), GTSL::MoveRef(light.Radius)); - } - - GTSL::Vector3 GetPosition(const PointLightHandle point_light_handle) const { - return pointLights[point_light_handle()].Position; - } - -private: - struct DirectionalLight { - GTSL::RGBA Color; - GTSL::Rotator Rotation; - }; - GTSL::FixedVector directionalLights; - - struct PointLight { - GTSL::RGB Color; - float32 Lumens; - GTSL::Vector3 Position; - float32 Radius; - }; - GTSL::FixedVector pointLights; - -public: - [[nodiscard]] auto& GetDirectionalLights() const { return directionalLights; } -}; diff --git a/src/ByteEngine/Render/RenderOrchestrator.cpp b/src/ByteEngine/Render/RenderOrchestrator.cpp deleted file mode 100644 index 9b65d7ea..00000000 --- a/src/ByteEngine/Render/RenderOrchestrator.cpp +++ /dev/null @@ -1,1682 +0,0 @@ -#include "RenderOrchestrator.h" - -#undef MemoryBarrier - -#include -#include -#include "LightsRenderGroup.h" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Game/Tasks.h" -#include "UIManager.h" -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Application/Templates/GameApplication.h" -#include "ByteEngine/Game/CameraSystem.h" - -static constexpr GTSL::Vector2 SQUARE_VERTICES[] = { { -0.5f, 0.5f }, { 0.5f, 0.5f }, { 0.5f, -0.5f }, { -0.5f, -0.5f } }; -//static constexpr GTSL::Vector2 SQUARE_VERTICES[] = { { -1.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, -1.0f }, { -1.0f, -1.0f } }; -static constexpr uint16 SQUARE_INDICES[] = { 0, 1, 3, 1, 2, 3 }; - -static bool IsDelim(char32_t tst) { - const char32_t* DELIMS = U" \n\t\r\f"; - do { // Delimiter string cannot be empty, so don't check for it. Real code should assert on it. - if (tst == *DELIMS) - return true; - ++DELIMS; - } while (*DELIMS); - - return false; -} - -void d(GTSL::StringView string, GTSL::StaticVector& tokens) { - auto begin = string.begin(); - - while (begin != string.end() && IsDelim(*begin)) { ++begin; } - - while(begin < string.end()) { - auto tokenBegin = begin; - - do { - ++begin; - } while (!IsDelim(*begin) && begin != string.end()); - - tokens.EmplaceBack(tokenBegin, begin); - - do { - ++begin; - } while (begin != string.end() && IsDelim(*begin)); - } -} - -inline uint32 PRECEDENCE(const GTSL::StringView optor) { - GTSL::StaticMap PRECEDENCE(16); - PRECEDENCE.Emplace(u8"=", 1); - PRECEDENCE.Emplace(u8"||", 2); - PRECEDENCE.Emplace(u8"<", 7); PRECEDENCE.Emplace(u8">", 7); PRECEDENCE.Emplace(u8"<=", 7); PRECEDENCE.Emplace(u8">=", 7); PRECEDENCE.Emplace(u8"==", 7); PRECEDENCE.Emplace(u8"!=", 7); - PRECEDENCE.Emplace(u8"+", 10); PRECEDENCE.Emplace(u8"-", 10); - PRECEDENCE.Emplace(u8"*", 20); PRECEDENCE.Emplace(u8"/", 20); PRECEDENCE.Emplace(u8"%", 20); - - return PRECEDENCE[optor]; -} - -RenderOrchestrator::RenderOrchestrator(const InitializeInfo& initializeInfo) : System(initializeInfo, u8"RenderOrchestrator"), -rayTracingSets(16, GetPersistentAllocator()), shaderHandlesDebugMap(16, GetPersistentAllocator()), shaders(16, GetPersistentAllocator()), -resources(16, GetPersistentAllocator()), dataKeys(16, GetPersistentAllocator()), dataKeysMap(32, GetPersistentAllocator()), updateKeys(16, GetPersistentAllocator()), -renderingTree(128, GetPersistentAllocator()), renderPassesMap(16, GetPersistentAllocator()), renderPasses(16), pipelines(8, GetPersistentAllocator()), -shaderGroups(16, GetPersistentAllocator()), shaderGroupsByName(16, GetPersistentAllocator()), shaderGroupInstanceByName(16, GetPersistentAllocator()), textures(16, GetPersistentAllocator()), attachments(16, GetPersistentAllocator()), elements(16, GetPersistentAllocator()), sets(16, GetPersistentAllocator()), queuedSetUpdates(1, 8, GetPersistentAllocator()), setLayoutDatas(2, GetPersistentAllocator()), pendingWrites(32, GetPersistentAllocator()) -{ - auto* renderSystem = initializeInfo.AppManager->GetSystem(u8"RenderSystem"); - - tag = BE::Application::Get()->GetConfig()[u8"Rendering"][u8"renderTechnique"]; - - //renderBuffers.EmplaceBack().BufferHandle = renderSystem->CreateBuffer(RENDER_DATA_BUFFER_PAGE_SIZE, GAL::BufferUses::STORAGE, true, true, RenderSystem::BufferHandle()); - - for (uint32 i = 0; i < renderSystem->GetPipelinedFrames(); ++i) { - descriptorsUpdates.EmplaceBack(GetPersistentAllocator()); - } - - elements.Emplace(0, GetPersistentAllocator()); - - tryAddDataType(u8"global", u8"uint8", 1); - tryAddDataType(u8"global", u8"uint16", 2); - tryAddDataType(u8"global", u8"uint32", 4); - tryAddDataType(u8"global", u8"uint64", 8); - tryAddDataType(u8"global", u8"float32", 4); - tryAddDataType(u8"global", u8"vec2s", 2 * 2); - tryAddDataType(u8"global", u8"vec2u", 4 * 2); - tryAddDataType(u8"global", u8"vec2i", 4 * 2); - tryAddDataType(u8"global", u8"vec2f", 4 * 2); - tryAddDataType(u8"global", u8"vec3f", 4 * 3); - tryAddDataType(u8"global", u8"vec4f", 4 * 4); - tryAddDataType(u8"global", u8"u16vec2", 2 * 2); - tryAddDataType(u8"global", u8"matrix4f", 4 * 4 * 4); - tryAddDataType(u8"global", u8"matrix3x4f", 4 * 3 * 4); - tryAddDataType(u8"global", u8"ptr_t", 8); - tryAddDataType(u8"global", u8"ShaderHandle", 32); - - RegisterType(u8"global", u8"IndirectDispatchCommand", INDIRECT_DISPATCH_COMMAND_DATA); - RegisterType(u8"global", u8"TextureReference", { { u8"uint32", u8"Instance" } }); - RegisterType(u8"global", u8"ImageReference", { { u8"uint32", u8"Instance" } }); - - { - //uint64 allocatedSize; - //GetPersistentAllocator().Allocate(1024 * 8, 32, reinterpret_cast(&buffer[0]), &allocatedSize); //TODO: free - } - - onTextureInfoLoadHandle = initializeInfo.AppManager->RegisterTask(this, u8"onTextureInfoLoad", DependencyBlock(TypedDependency(u8"TextureResourceManager"), TypedDependency(u8"RenderSystem")), &RenderOrchestrator::onTextureInfoLoad); - onTextureLoadHandle = initializeInfo.AppManager->RegisterTask(this, u8"loadTexture", DependencyBlock(TypedDependency(u8"TextureResourceManager"), TypedDependency(u8"RenderSystem")), &RenderOrchestrator::onTextureLoad); - - onShaderInfosLoadHandle = initializeInfo.AppManager->RegisterTask(this, u8"onShaderGroupInfoLoad", DependencyBlock(TypedDependency(u8"ShaderResourceManager")), &RenderOrchestrator::onShaderInfosLoaded); - onShaderGroupLoadHandle = initializeInfo.AppManager->RegisterTask(this, u8"onShaderGroupLoad", DependencyBlock(TypedDependency(u8"ShaderResourceManager"), TypedDependency(u8"RenderSystem")), &RenderOrchestrator::onShadersLoaded); - - initializeInfo.AppManager->EnqueueScheduledTask(initializeInfo.AppManager->RegisterTask(this, SETUP_TASK_NAME, DependencyBlock(), &RenderOrchestrator::Setup, u8"GameplayEnd", u8"RenderSetup")); - initializeInfo.AppManager->EnqueueScheduledTask(initializeInfo.AppManager->RegisterTask(this, RENDER_TASK_NAME, DependencyBlock(TypedDependency(u8"RenderSystem")), &RenderOrchestrator::Render, u8"Render", u8"Render")); - - { - const auto taskDependencies = GTSL::StaticVector{ { u8"RenderSystem", AccessTypes::READ_WRITE } }; - onRenderEnable(initializeInfo.AppManager, taskDependencies); - } - - { //sampler must be built before set layouts, as it is used as inmutable sampler - auto& sampler = samplers.EmplaceBack(); - sampler.Initialize(renderSystem->GetRenderDevice(), 0); - } - - { - GTSL::StaticVector subSetInfos; - subSetInfos.EmplaceBack(SubSetTypes::READ_TEXTURES, 128, &textureSubsetsHandle); - subSetInfos.EmplaceBack(SubSetTypes::WRITE_TEXTURES, 128, &imagesSubsetHandle); - subSetInfos.EmplaceBack(SubSetTypes::SAMPLER, 16, &samplersSubsetHandle, samplers); - - globalSetLayout = AddSetLayout(renderSystem, SetLayoutHandle(), subSetInfos); - globalBindingsSet = AddSet(renderSystem, u8"GlobalData", globalSetLayout, subSetInfos); - } - - { - tryAddElement(u8"global", u8"CommonPermutation", ElementData::ElementType::SCOPE); - RegisterType(u8"global.CommonPermutation", u8"GlobalData", GLOBAL_DATA); - globalDataDataKey = MakeDataKey(renderSystem, u8"global.CommonPermutation", u8"GlobalData"); - globalData = AddDataNode({}, u8"GlobalData", globalDataDataKey); - bnoise[0] = createTexture({ u8"bnoise_v_0", GetApplicationManager(), renderSystem, GetApplicationManager()->GetSystem(u8"TextureResourceManager") }); - bnoise[1] = createTexture({ u8"bnoise_v_1", GetApplicationManager(), renderSystem, GetApplicationManager()->GetSystem(u8"TextureResourceManager") }); - bnoise[2] = createTexture({ u8"bnoise_v_2", GetApplicationManager(), renderSystem, GetApplicationManager()->GetSystem(u8"TextureResourceManager") }); - bnoise[3] = createTexture({ u8"bnoise_v_3", GetApplicationManager(), renderSystem, GetApplicationManager()->GetSystem(u8"TextureResourceManager") }); - - auto bwk = GetBufferWriteKey(renderSystem, globalDataDataKey); - bwk[u8"blueNoise2D"][0] = bnoise[0]; - bwk[u8"blueNoise2D"][1] = bnoise[1]; - bwk[u8"blueNoise2D"][2] = bnoise[2]; - bwk[u8"blueNoise2D"][3] = bnoise[3]; - } - - { - RegisterType(u8"global.CommonPermutation", u8"ViewData", VIEW_DATA); - cameraMatricesHandle = RegisterType(u8"global.CommonPermutation", u8"CameraData", CAMERA_DATA); - cameraDataKeyHandle = MakeDataKey(renderSystem, u8"global.CommonPermutation", u8"CameraData"); - //cameraDataNode = AddDataNode(globalData, u8"CameraData", cameraDataKeyHandle); - } - - if constexpr (BE_DEBUG) { - pipelineStages |= BE::Application::Get()->GetConfig()[u8"RenderOrchestrator"][u8"debugSync"].GetBool() ? GAL::PipelineStages::ALL_GRAPHICS : GAL::PipelineStage(0); - } - - { - AddAttachment(u8"Albedo", 16, 4, GAL::ComponentType::FLOAT, GAL::TextureType::COLOR, false); - - AddAttachment(u8"UI", 16, 4, GAL::ComponentType::FLOAT, GAL::TextureType::COLOR, false); - - if (tag == GTSL::ShortString<16>(u8"Forward")) { - AddAttachment(u8"Normal", 16, 4, GAL::ComponentType::FLOAT, GAL::TextureType::COLOR, false); - AddAttachment(u8"WorldSpacePosition", 16, 4, GAL::ComponentType::FLOAT, GAL::TextureType::COLOR, false); - AddAttachment(u8"ViewSpacePosition", 16, 4, GAL::ComponentType::FLOAT, GAL::TextureType::COLOR, false); - AddAttachment(u8"Lighting", 16, 4, GAL::ComponentType::FLOAT, GAL::TextureType::COLOR, false); - AddAttachment(u8"Roughness", 8, 1, GAL::ComponentType::INT, GAL::TextureType::COLOR, false); - AddAttachment(u8"Shadow", 8, 1, GAL::ComponentType::INT, GAL::TextureType::COLOR, false); - } else if(tag == GTSL::ShortString<16>(u8"Visibility")) { - AddAttachment(u8"Visibility", 32, 2, GAL::ComponentType::INT, GAL::TextureType::COLOR, false); - } - - AddAttachment(u8"Depth", 32, 1, GAL::ComponentType::FLOAT, GAL::TextureType::DEPTH, true); - - // AO - AddAttachment(u8"AO", 8, 1, GAL::ComponentType::INT, GAL::TextureType::COLOR, true); - AddAttachment(u8"Mean", 8, 1, GAL::ComponentType::INT, GAL::TextureType::COLOR, false); - AddAttachment(u8"Variance", 8, 1, GAL::ComponentType::INT, GAL::TextureType::COLOR, false); - AddAttachment(u8"PartialDistanceDerivatives", 16, 2, GAL::ComponentType::FLOAT, GAL::TextureType::COLOR, false); - AddAttachment(u8"TSPP", 8, 1, GAL::ComponentType::INT, GAL::TextureType::COLOR, false); - // AO - } - - for (uint32 f = 0; f < renderSystem->GetPipelinedFrames(); ++f) { - graphicsCommandLists[f] = renderSystem->CreateCommandList(u8"Graphics Command List", GAL::QueueTypes::GRAPHICS, GAL::PipelineStages::COLOR_ATTACHMENT_OUTPUT, false); - graphicsWorkloadHandle[f] = renderSystem->CreateWorkload(u8"Frame work", GAL::QueueTypes::GRAPHICS, GAL::PipelineStages::COLOR_ATTACHMENT_OUTPUT); - transferCommandList[f] = renderSystem->CreateCommandList(u8"Transfer Command List", GAL::QueueTypes::GRAPHICS, GAL::PipelineStages::TRANSFER); - } - - const auto& config = BE::Application::Get()->GetConfig(); - - auto* windowSystem = GetApplicationManager()->GetSystem(u8"WindowSystem"); - - { - auto& v = views.EmplaceBack(); - v.name = u8"Lighting"; - v.windowHandle = static_cast(BE::Application::Get())->GetWindowHandle(); - v.renderContext = renderSystem->CreateRenderContext(windowSystem, v.windowHandle); - v.workloadHandles[0] = renderSystem->CreateWorkload(u8"Swapchain Image Acquisition", GAL::QueueTypes::GRAPHICS, GAL::PipelineStages::TRANSFER); - v.workloadHandles[1] = renderSystem->CreateWorkload(u8"Swapchain Image Acquisition", GAL::QueueTypes::GRAPHICS, GAL::PipelineStages::TRANSFER); - } - - for(auto rp : config[u8"RenderOrchestrator"][u8"debugViews"]) { - if(!attachments.Find(rp)) { BE_LOG_WARNING(u8"Tried to enable debug view for attachment ", GTSL::StringView(rp), u8", but no such attachment exists."); continue; } - - auto& dv = views.EmplaceBack(rp.GetStringView()); - - dv.windowHandle = windowSystem->CreateWindow(u8"debugView", rp.GetStringView(), { 1920, 1080 }); - dv.renderContext = renderSystem->CreateRenderContext(windowSystem, dv.windowHandle); - - for (uint32 f = 0; f < renderSystem->GetPipelinedFrames(); ++f) { - dv.workloadHandles[f] = renderSystem->CreateWorkload(u8"Debug view image acquisition", GAL::QueueTypes::GRAPHICS, GAL::PipelineStages::TRANSFER); - } - } - - for(auto rp : config[u8"RenderOrchestrator"][u8"renderPasses"]) { - if(auto enabled = rp[u8"enabled"]) { - - } - } - - randomB(); randomB(); randomB(); -} - -void RenderOrchestrator::Setup(TaskInfo taskInfo) { -} - -template -void Skim(GTSL::HashMap& hash_map, auto predicate, const ALLOC& allocator) { - GTSL::Vector toSkim(8192 * 2, allocator); - GTSL::PairForEach(hash_map, [&](K key, V& val) { if (predicate(val)) { toSkim.EmplaceBack(key); } }); - for (auto e : toSkim) { hash_map.Remove(e); } -} - -inline float32 Halton(uint32 i, uint32 b) { - float32 f = 1.0f, r = 0.0f; - - while (i > 0) { - f /= static_cast(b); - r = r + f * static_cast(i % b); - i = static_cast(floorf(static_cast(i) / static_cast(b))); - } - - return r; -} - -void RenderOrchestrator::Render(TaskInfo taskInfo, RenderSystem* renderSystem) { - const uint8 currentFrame = renderSystem->GetCurrentFrame(); auto beforeFrame = static_cast(currentFrame - static_cast(1)) % renderSystem->GetPipelinedFrames(); - - renderSystem->Wait(graphicsWorkloadHandle[currentFrame]); // We HAVE to wait or else descriptor update fails because command list may be in use - - for(uint32 i = 0; i < views; ++i) { - auto& dv = views[i]; - if (auto res = renderSystem->AcquireImage(dv.renderContext, dv.workloadHandles[currentFrame], GetApplicationManager()->GetSystem(u8"WindowSystem")); res || dv.sizeHistory[currentFrame] != dv.sizeHistory[beforeFrame]) { - if(i == 0u) { // Only resize attachments if master window was resized. - OnResize(renderSystem, res.Get()); - } else { - dv.sizeHistory[currentFrame] = views[0].sizeHistory[currentFrame]; - } - } - } - - GTSL::Extent2D renderArea = renderSystem->GetRenderExtent(views[0].renderContext); - - updateDescriptors(taskInfo); - - bool debugRenderNodes = BE::Application::Get()->GetConfig()[u8"RenderOrchestrator"][u8"debugRenderNodes"].GetBool(); - - { - auto bwk = GetBufferWriteKey(renderSystem, globalDataDataKey); - bwk[u8"frameIndex"] = frameIndex++; - bwk[u8"elapsedTime"] = BE::Application::Get()->GetClock()->GetElapsedTime().As(); - bwk[u8"deltaTime"] = BE::Application::Get()->GetClock()->GetDeltaTime().As(); - bwk[u8"framePipelineDepth"] = static_cast(renderSystem->GetPipelinedFrames()); - bwk[u8"random"][0] = static_cast(randomA()); bwk[u8"random"][1] = static_cast(randomB()); - bwk[u8"random"][2] = static_cast(randomA()); bwk[u8"random"][3] = static_cast(randomB()); - } - - { - auto* cameraSystem = taskInfo.AppManager->GetSystem(u8"CameraSystem"); - - auto fovs = cameraSystem->GetFieldOfViews(); - - if (fovs.ElementCount()) { - //SetNodeState(cameraDataNode, true); // Set state on data key, to fullfil resource counts - auto fov = cameraSystem->GetFieldOfViews()[0]; auto aspectRatio = static_cast(renderArea.Width) / static_cast(renderArea.Height); - - auto fExtent = GTSL::Vector2(renderArea.Width, renderArea.Height); - - float32 nearValue = 0.1f, farValue = 1000.0f; - - if constexpr (INVERSE_Z) { - std::swap(nearValue, farValue); - } - - uint32 jitterIndex = frameIndex % 8; - - float haltonX = 2.0f * Halton(jitterIndex + 1, 2) - 1.0f; - float haltonY = 2.0f * Halton(jitterIndex + 1, 3) - 1.0f; - float jitterX = (haltonX / fExtent.X()); - float jitterY = (haltonY / fExtent.Y()); - - GTSL::Matrix4 projectionMatrix = GTSL::Math::BuildPerspectiveMatrix(fov, aspectRatio, nearValue, farValue); - projectionMatrix[1][1] *= API == GAL::RenderAPI::VULKAN ? -1.0f : 1.0f; // Vulkan has inverted y - - auto invertedProjectionMatrix = GTSL::Math::BuildInvertedPerspectiveMatrix(fov, aspectRatio, nearValue, farValue); - invertedProjectionMatrix[1][1] *= API == GAL::RenderAPI::VULKAN ? -1.0f : 1.0f; // Vulkan has inverted y - - auto viewMatrix = cameraSystem->GetCameraTransform(); - - auto cameraPosition = cameraSystem->GetCameraPosition(CameraSystem::CameraHandle{0}); - - viewMatrix[0][3] *= -1.0f; viewMatrix[1][3] *= -1.0f; viewMatrix[2][3] *= -1.0f; // Negate coordinates to make view matrix - - auto cameraData = GetBufferWriteKey(renderSystem, cameraDataKeyHandle); - cameraData[u8"viewHistory"][2] = cameraData[u8"viewHistory"][1]; - cameraData[u8"viewHistory"][1] = cameraData[u8"viewHistory"][0]; - - auto currentView = cameraData[u8"viewHistory"][0]; - - currentView[u8"view"] = viewMatrix; - currentView[u8"proj"] = projectionMatrix; - currentView[u8"viewInverse"] = GTSL::Math::Inverse(viewMatrix); - currentView[u8"projInverse"] = invertedProjectionMatrix; - currentView[u8"vp"] = projectionMatrix * viewMatrix; - currentView[u8"vpInverse"] = GTSL::Math::Inverse(viewMatrix) * invertedProjectionMatrix; - currentView[u8"position"] = GTSL::Vector4(cameraPosition, 1.0f); - currentView[u8"near"] = nearValue; - currentView[u8"far"] = farValue; - currentView[u8"extent"] = renderArea; - currentView[u8"extentReciprocal"] = GTSL::Vector2(1) / fExtent; - currentView[u8"aspectRatio"] = fExtent.X() / fExtent.Y(); - } - else { //disable rendering for everything which depends on this view - //SetNodeState(cameraDataNode, false); - } - } - - for(auto& renderPassNodeHandle : renderPasses) { - auto& renderPass = getPrivateNode(renderPassNodeHandle); - - auto bwk = GetBufferWriteKey(renderSystem, renderPass.DataKey); - - for (auto i = 0u; i < renderPass.Attachments.GetLength(); ++i) { - const auto& e = renderPass.Attachments[i]; - - if(auto a = attachments.TryGet(e.Attachment)) { - if(GTSL::IsIn(e.Name, u8"History")) { // If attachment name is history that means we want to access the previous frames' data for that attachment - bwk[e.Name] = a.Get().ImageIndeces[beforeFrame]; - } else { - bwk[e.Name] = a.Get().ImageIndeces[currentFrame]; - } - } - } - } - - auto processExecutionString = [renderArea](const GTSL::StringView execution) { - GTSL::StaticVector tokens; - - GTSL::StaticVector operators; - - GTSL::StaticVector, 16> output; - - d(execution, tokens); - - while (tokens) { - auto token = tokens.back(); tokens.PopBack(); - - if (GTSL::IsNumber(token) or IsAnyOf(token, u8"windowExtent", u8"localSize")) { - output.EmplaceBack(token); - } - else { //is an operator - while (operators && PRECEDENCE(operators.back()) > PRECEDENCE(token)) { - output.EmplaceBack(operators.back()); - operators.PopBack(); - } - - operators.EmplaceBack(token); - } - } - - while (operators) { - output.EmplaceBack(operators.back()); - operators.PopBack(); - } - - GTSL::StaticVector numbers; - - //evaluate - for (uint32 i = 0; i < output; ++i) { - auto token = output[i]; - if (GTSL::IsNumber(token) or IsAnyOf(token, u8"windowExtent", u8"localSize")) { - if (token == u8"windowExtent") { - numbers.EmplaceBack(renderArea); - } - else if (token == u8"localSize") { - numbers.EmplaceBack(GTSL::Extent3D(32, 32, 1)); - } - else { - numbers.EmplaceBack(GTSL::ToNumber(token).Get()); - } - } - else { //operator - auto a = numbers.back(); numbers.PopBack(); - - auto b = numbers.back(); numbers.PopBack(); - - switch (GTSL::Hash(token)) { - case GTSL::Hash(u8"+"): numbers.EmplaceBack(a + b); break; - case GTSL::Hash(u8"-"): numbers.EmplaceBack(a - b); break; - case GTSL::Hash(u8"*"): numbers.EmplaceBack(a * b); break; - case GTSL::Hash(u8"/"): numbers.EmplaceBack(a / b); break; - } - } - } - - return numbers.back(); - }; - - uint32 counterStack[16] = { 0u }; - uint32 counterI = 0; - - if(isRenderTreeDirty) { // If render tree is dirty then every command buffer for every frame has to be updated - if(BE::Application::Get()->GetConfig()[u8"RenderOrchestrator"][u8"optimizeRenderTree"].GetBool()) { - renderingTree.Optimize(); - } - - for(uint32 f = 0; f < renderSystem->GetPipelinedFrames(); ++f) { - isCommandBufferUpdated[f] = false; - } - } - - if(!isCommandBufferUpdated[currentFrame] or isRenderTreeDirty) { - if(debugRenderNodes) { - BE_LOG_SUCCESS(u8"Started baking command buffer."); - } - - renderSystem->StartCommandList(graphicsCommandLists[currentFrame]); - - auto& commandBuffer = *renderSystem->GetCommandList(graphicsCommandLists[currentFrame]); - - BindSet(renderSystem, commandBuffer, globalBindingsSet, GAL::ShaderStages::VERTEX | GAL::ShaderStages::COMPUTE | GAL::ShaderStages::RAY_GEN); - - RenderState renderState; - - auto visitNode = [&](const decltype(renderingTree)::Key key, const uint32_t level) -> void { - printNode(key, level, debugRenderNodes, true); - - const auto& baseData = renderingTree.GetAlpha(key); - - auto debugState = [&] { - if(debugRenderNodes) { - auto& shaderGroup = shaderGroups[renderState.BoundShaderGroupIndex]; - for(uint32 i = 0; auto& e : shaderGroup.PushConstantLayout) { - auto& element = getElement(getDataKey(renderState.dataKeys[i]).Handle); - auto dt = element.DataType; - RTrimLast(dt, u8'['); - dt += u8"*"; - ++i; - - if(dt != GTSL::StringView(e.Type)) { - BE_LOG_WARNING(u8"Pipeline expected push constant layout does not match current layout. Shader declared: ", e.Type, u8", but bound type is: ", dt, u8"."); - } - } - - if(shaderGroup.PushConstantLayout.GetLength() != renderState.streamsCount) { - BE_LOG_WARNING(u8"Bound push constant range doesn't match shader expect range.") - } - } - }; - - switch (renderingTree.GetNodeType(key)) { - case RTT::GetTypeIndex(): { - const auto& dataNode = renderingTree.GetClass(key); - - if constexpr (BE_DEBUG) { - commandBuffer.BeginRegion(renderSystem->GetRenderDevice(), elements[getDataKey(dataNode.DataKey).Handle()].Name); - } - - if (dataNode.DataKey) { - if (dataNode.UseCounter) { - ++counterI; - } - - const DataStreamHandle dataStreamHandle = renderState.AddDataStream(dataNode.DataKey); - const auto& dataKey = getDataKey(dataNode.DataKey); - - GAL::DeviceAddress address = renderSystem->GetBufferAddress(dataKey.Buffer[1]) + dataKeysMap[dataNode.DataKey()].Second; // Get READ buffer handle - - auto& setLayout = setLayoutDatas[globalSetLayout()]; address += dataKey.Offset; - commandBuffer.UpdatePushConstant(renderSystem->GetRenderDevice(), setLayout.pipelineLayout, dataStreamHandle() * 8, GTSL::Range(8, reinterpret_cast(&address)), setLayout.Stage); - - if(BE::Application::Get()->GetConfig()[u8"RenderOrchestrator"][u8"debugBuffers"].GetBool()) { - PrintMember(dataNode.DataKey, renderSystem); - } - } - - break; - } - case RTT::GetTypeIndex(): { - const PipelineBindData& pipeline_bind_data = renderingTree.GetClass(key); - const auto& shaderGroupInstance = shaderGroupInstances[pipeline_bind_data.Handle()]; - const auto& shaderGroup = shaderGroups[shaderGroupInstance.ShaderGroupIndex]; - uint32 pipelineIndex = 0xFFFFFFFF; - - if (shaderGroup.RasterPipelineIndex != 0xFFFFFFFF) { - pipelineIndex = shaderGroup.RasterPipelineIndex; - } else if (shaderGroup.ComputePipelineIndex != 0xFFFFFFFF) { - pipelineIndex = shaderGroup.ComputePipelineIndex; - } else if (shaderGroup.RTPipelineIndex != 0xFFFFFFFF) { - pipelineIndex = shaderGroup.RTPipelineIndex; - } else { - BE_LOG_WARNING(u8"Pipeline bind data node with no valid pipeline reference."); - } - - renderState.BoundPipelineIndex = pipelineIndex; - renderState.BoundShaderGroupIndex = shaderGroupInstance.ShaderGroupIndex; - - commandBuffer.BindPipeline(renderSystem->GetRenderDevice(), pipelines[pipelineIndex].pipeline, renderState.ShaderStages); - break; - } - case RTT::GetTypeIndex(): { - const DispatchData& dispatchData = renderingTree.GetClass(key); - - const auto& pipeline = pipelines[renderState.BoundPipelineIndex]; - const auto& execution = pipeline.ExecutionString; - const auto executionExtent = processExecutionString(execution); - commandBuffer.Dispatch(renderSystem->GetRenderDevice(), executionExtent); - - break; - } - case RTT::GetTypeIndex(): { - const RayTraceData& rayTraceData = renderingTree.GetClass(key); - const auto& pipelineData = pipelines[shaderGroups[shaderGroupInstances[rayTraceData.ShaderGroupIndex].ShaderGroupIndex].RTPipelineIndex]; - - CommandList::ShaderTableDescriptor shaderTableDescriptors[4]; - - for (uint32 i = 0, offset = 0; i < 3; ++i) { - shaderTableDescriptors[i].Entries = pipelineData.RayTracingData.ShaderGroups[i].ShaderCount; - shaderTableDescriptors[i].EntrySize = GTSL::Math::RoundUpByPowerOf2(GetSize(pipelineData.RayTracingData.ShaderGroups[i].TableHandle), renderSystem->GetShaderGroupHandleAlignment()); - shaderTableDescriptors[i].Address = renderSystem->GetBufferAddress(getDataKey(pipelineData.ShaderBindingTableBuffer).Buffer[1]) + offset; - - offset += GTSL::Math::RoundUpByPowerOf2(GetSize(pipelineData.RayTracingData.ShaderGroups[i].TableHandle), renderSystem->GetShaderGroupHandleAlignment()); - } - - const auto executionExtent = processExecutionString(pipelineData.ExecutionString); - - commandBuffer.TraceRays(renderSystem->GetRenderDevice(), GTSL::Range(4, shaderTableDescriptors), executionExtent); - - break; - } - case RTT::GetTypeIndex(): { - const VertexBufferBindData& meshData = renderingTree.GetClass(key); - const auto vertexBuffer = renderSystem->GetBuffer(meshData.Handle); - GTSL::StaticVector buffers; - for (uint32 i = 0; i < meshData.Offsets.GetLength(); ++i) { - buffers.EmplaceBack(vertexBuffer); - } - commandBuffer.BindVertexBuffers(renderSystem->GetRenderDevice(), buffers, meshData.Offsets, meshData.VertexSize * meshData.VertexCount, meshData.VertexSize); - break; - } - case RTT::GetTypeIndex(): { - const IndexBufferBindData& meshData = renderingTree.GetClass(key); - commandBuffer.BindIndexBuffer(renderSystem->GetRenderDevice(), renderSystem->GetBuffer(meshData.BufferHandle), 0, meshData.IndexCount, meshData.IndexType); - break; - } - case RTT::GetTypeIndex(): { - const MeshData& meshData = renderingTree.GetClass(key); - commandBuffer.DrawIndexed(renderSystem->GetRenderDevice(), meshData.IndexCount, meshData.InstanceCount, meshData.InstanceIndex, meshData.IndexOffset, meshData.VertexOffset); - counterStack[counterI - 1] += meshData.InstanceCount; - - break; - } - case RTT::GetTypeIndex(): { - const DrawData& draw_data = renderingTree.GetClass(key); - commandBuffer.Draw(renderSystem->GetRenderDevice(), draw_data.VertexCount, draw_data.InstanceCount, counterStack[counterI - 1]); - counterStack[counterI - 1] += draw_data.InstanceCount; - break; - } - case RTT::GetTypeIndex(): { - const RenderPassData& renderPassData = renderingTree.GetClass(key); - - transitionImages(commandBuffer, renderSystem, &renderPassData); - - switch (renderPassData.Type) { - case PassTypes::RASTER: { - renderState.ShaderStages = GAL::ShaderStages::VERTEX | GAL::ShaderStages::FRAGMENT; - - GTSL::StaticVector renderPassTargetDescriptions; - for (uint8 i = 0; i < renderPassData.Attachments.GetLength(); ++i) { - if (renderPassData.Attachments[i].Access & GAL::AccessTypes::WRITE) { - auto& e = renderPassTargetDescriptions.EmplaceBack(); - const auto& attachment = attachments.At(renderPassData.Attachments[i].Name); - e.ClearValue = attachment.ClearColor; - e.Start = renderPassData.Attachments[i].Layout; - e.End = renderPassData.Attachments[i].Layout; - e.LoadOperation = renderPassData.Attachments[i].LoadOperation; - e.StoreOperation = GAL::Operations::DO; - e.format = attachment.format; - e.texture = renderSystem->GetTexture(attachment.TextureHandle[currentFrame]); - e.textureView = renderSystem->GetTextureView(attachment.TextureHandle[currentFrame]); - } - } - - commandBuffer.BeginRenderPass(renderSystem->GetRenderDevice(), renderArea, renderPassTargetDescriptions); - break; - } - case PassTypes::COMPUTE: { - renderState.ShaderStages = GAL::ShaderStages::COMPUTE; - break; - } - case PassTypes::RAY_TRACING: { - renderState.ShaderStages = GAL::ShaderStages::RAY_GEN | GAL::ShaderStages::CLOSEST_HIT | GAL::ShaderStages::MISS | GAL::ShaderStages::INTERSECTION | GAL::ShaderStages::CALLABLE; - break; - } - } - - break; - } - } - }; - - auto endNode = [&](const uint32 key, const uint32_t level) { - if(debugRenderNodes) { - BE_LOG_WARNING(u8"Node: ", key, u8", Level: ", level); - } - - switch (renderingTree.GetNodeType(key)) { - case RTT::GetTypeIndex(): { - const auto& node = getPrivateNode(key); - - renderState.PopData(); - - if(node.UseCounter) { - --counterI; - counterStack[counterI] = 0u; - } - - if constexpr (BE_DEBUG) { - commandBuffer.EndRegion(renderSystem->GetRenderDevice()); - } - - break; - } - case RTT::GetTypeIndex(): { - const auto& renderPassData = renderingTree.GetClass(key); - if (renderPassData.Type == PassTypes::RASTER) { - commandBuffer.EndRenderPass(renderSystem->GetRenderDevice()); - } - - break; - } - default: break; - } - }; - - ForEach(renderingTree, visitNode, endNode); - - GTSL::StaticVector preTransitions, postTransitions; - - // Do pre copy pipeline barriers - for(auto& dv : views) { - // Transition view swapchain image - preTransitions.EmplaceBack(GAL::PipelineStages::TRANSFER, GAL::PipelineStages::TRANSFER, GAL::AccessTypes::READ, GAL::AccessTypes::WRITE, CommandList::TextureBarrier{ renderSystem->GetSwapchainTexture(dv.renderContext), GAL::TextureLayout::UNDEFINED, GAL::TextureLayout::TRANSFER_DESTINATION, renderSystem->GetSwapchainFormat() }); - - auto& attachment = attachments.At(dv.name); - - // Transition attachment - preTransitions.EmplaceBack(attachment.ConsumingStages, GAL::PipelineStages::TRANSFER, attachment.AccessType, - GAL::AccessTypes::READ, CommandList::TextureBarrier{ renderSystem->GetTexture(attachment.TextureHandle[currentFrame]), attachment.Layout[currentFrame], - GAL::TextureLayout::TRANSFER_SOURCE, attachment.format }); - - updateImage(currentFrame, attachment, GAL::TextureLayout::TRANSFER_SOURCE, GAL::PipelineStages::TRANSFER, GAL::AccessTypes::READ); - } - - commandBuffer.AddPipelineBarrier(renderSystem->GetRenderDevice(), preTransitions, GetTransientAllocator()); - - // Do copies from attachments to swapchain images - for(auto& dv : views) { - auto& attachment = attachments.At(dv.name); - - commandBuffer.BlitTexture(renderSystem->GetRenderDevice(), *renderSystem->GetTexture(attachment.TextureHandle[currentFrame]), GAL::TextureLayout::TRANSFER_SOURCE, attachment.format, dv.sizeHistory[currentFrame], *renderSystem->GetSwapchainTexture(dv.renderContext), GAL::TextureLayout::TRANSFER_DESTINATION, renderSystem->GetSwapchainFormat(), GTSL::Extent3D(renderSystem->GetRenderExtent(dv.renderContext))); - } - - // Do post copy pipeline barriers - for(auto& dv : views) { - postTransitions.EmplaceBack(GAL::PipelineStages::TRANSFER, GAL::PipelineStages::TRANSFER, GAL::AccessTypes::READ, GAL::AccessTypes::WRITE, CommandList::TextureBarrier { renderSystem->GetSwapchainTexture(dv.renderContext), GAL::TextureLayout::TRANSFER_DESTINATION, - GAL::TextureLayout::PRESENTATION, renderSystem->GetSwapchainFormat() }); - } - - commandBuffer.AddPipelineBarrier(renderSystem->GetRenderDevice(), postTransitions, GetTransientAllocator()); - - renderSystem->EndCommandList(graphicsCommandLists[currentFrame]); - - if(debugRenderNodes) { - BE_LOG_SUCCESS(u8"Ended baking command buffer."); - } - - isRenderTreeDirty = false; - isCommandBufferUpdated[currentFrame] = true; - } - - { - auto processPendingWrite = [&](PendingWriteData& pending_write_data) { - bool c = pending_write_data.FrameCountdown[currentFrame], b = pending_write_data.FrameCountdown[beforeFrame]; - - if (c) { - renderSystem->AddBufferUpdate(transferCommandList[currentFrame], pending_write_data.Buffer[0], pending_write_data.Buffer[1]); - pending_write_data.FrameCountdown[beforeFrame] = false; - pending_write_data.FrameCountdown[currentFrame] = false; - return true; - } - - //pending_write_data.FrameCountdown[currentFrame] = false; - - return false; - }; - - Skim(pendingWrites, processPendingWrite, GetPersistentAllocator()); - } - - { - renderSystem->StartCommandList(transferCommandList[currentFrame]); - renderSystem->EndCommandList(transferCommandList[currentFrame]); - - GTSL::StaticVector commandLists; - GTSL::StaticVector workloads; - - commandLists.EmplaceBack(transferCommandList[renderSystem->GetCurrentFrame()]); - - workloads.EmplaceBack(buildAccelerationStructuresWorkloadHandle[renderSystem->GetCurrentFrame()]); - if (BE::Application::Get()->GetBoolOption(u8"rayTracing")) { - } - - for(auto& dv : views) { - workloads.EmplaceBack(dv.workloadHandles[currentFrame]); - } - - workloads.EmplaceBack(graphicsWorkloadHandle[currentFrame]); - - commandLists.EmplaceBack(graphicsCommandLists[currentFrame]); - - renderSystem->Submit(GAL::QueueTypes::GRAPHICS, { { { transferCommandList[currentFrame] }, {}, { graphicsWorkloadHandle[currentFrame]}}, {{graphicsCommandLists[currentFrame]}, workloads, {graphicsWorkloadHandle[currentFrame]}}}, graphicsWorkloadHandle[renderSystem->GetCurrentFrame()]); // Wait on image acquisition to render maybe, //Signal graphics workload - - auto windowSystem = GetApplicationManager()->GetSystem(u8"WindowSystem"); - - GTSL::StaticVector renderContexts; - - for(const auto& e : views) { - renderContexts.EmplaceBack(e.renderContext); - } - - renderSystem->Present(windowSystem, renderContexts, { graphicsWorkloadHandle[currentFrame] }); // Wait on graphics work to present - } - - renderSystem->Wait(graphicsWorkloadHandle[currentFrame]); - - //TODO: wait on transfer work to start next frame, or else reads will be corrupted since, next frame may have started -} - -RenderModelHandle RenderOrchestrator::CreateShaderGroup(GTSL::StringView shader_group_instance_name) { - auto shaderGroupReference = shaderGroupInstanceByName.TryEmplace(shader_group_instance_name); - - uint32 id = 0xFFFFFFFF; - - if (shaderGroupReference.State()) { - id = shaderGroupInstances.GetLength(); - shaderGroupReference.Get() = id; - - ShaderLoadInfo sli(GetPersistentAllocator()); - GetApplicationManager()->GetSystem(u8"ShaderResourceManager")->LoadShaderGroupInfo(GetApplicationManager(), Id(shader_group_instance_name), onShaderInfosLoadHandle, GTSL::MoveRef(sli)); - - auto& shaderGroupInstance = shaderGroupInstances.EmplaceBack(); - - shaderGroupInstance.Resource = makeResource(GTSL::StringView(shader_group_instance_name)); - addDependencyOnResource(shaderGroupInstance.Resource); // Add dependency the pipeline itself - shaderGroupInstance.DataKey = MakeDataKey(); - shaderGroupInstance.Name = shader_group_instance_name; - shaderGroupInstance.UpdateKey = CreateUpdateKey(); - } else { - auto& material = shaderGroups[shaderGroupReference.Get()]; - id = shaderGroupReference.Get(); - } - - return RenderModelHandle(id); -} - -void RenderOrchestrator::AddAttachment(GTSL::StringView attachment_name, uint8 bitDepth, uint8 componentCount, GAL::ComponentType compType, GAL::TextureType type, bool is_multiframe) { - Attachment attachment; - attachment.Name = attachment_name; - attachment.Uses = GAL::TextureUse(); - - attachment.Uses |= GAL::TextureUses::ATTACHMENT; - attachment.Uses |= GAL::TextureUses::SAMPLE; - - if (type == GAL::TextureType::COLOR) { - attachment.format = GAL::FormatDescriptor(compType, componentCount, bitDepth, GAL::TextureType::COLOR, 0, componentCount >= 2 ? 1 : 0, componentCount >= 3 ? 2 : 0, componentCount >= 4 ? 3 : 0); - attachment.Uses |= GAL::TextureUses::STORAGE; - attachment.Uses |= GAL::TextureUses::TRANSFER_SOURCE; - attachment.ClearColor = GTSL::RGBA(1, 1, 1, 1); - } else { - attachment.format = GAL::FormatDescriptor(compType, componentCount, bitDepth, GAL::TextureType::DEPTH, 0, 0, 0, 0); - attachment.ClearColor = GTSL::RGBA(INVERSE_Z ? 0.0f: 1.0f, 0, 0, 0); - } - - attachment.Layout[0] = GAL::TextureLayout::UNDEFINED; attachment.Layout[1] = GAL::TextureLayout::UNDEFINED; attachment.Layout[2] = GAL::TextureLayout::UNDEFINED; - attachment.AccessType = GAL::AccessTypes::READ; - attachment.ConsumingStages = GAL::PipelineStages::TOP_OF_PIPE; - - for(uint32 f = 0; f < 2u; ++f) { - attachment.ImageIndeces[f] = imageIndex++; - ++textureIndex; - } - - attachments.Emplace(attachment_name, attachment); -} - -RenderOrchestrator::NodeHandle RenderOrchestrator::AddRenderPassNode(NodeHandle parent_node_handle, GTSL::StringView instance_name, GTSL::StringView render_pass_name, RenderSystem* renderSystem, PassData pass_data, const GTSL::Range innner) { - GTSL::StaticVector members; - - for (auto& e : pass_data.Attachments) { - if(!(e.Access & GAL::AccessTypes::WRITE)) { - members.EmplaceBack(nullptr, u8"TextureReference", GTSL::StringView(e.Name)); - } else { - members.EmplaceBack(nullptr, u8"ImageReference", GTSL::StringView(e.Name)); - } - } - - CreateScope(u8"global", render_pass_name); - - const auto scope = GTSL::StaticString<64>(u8"global") + u8"." + render_pass_name; - - auto member = RegisterType(scope, u8"RenderPassData", members); - - NodeHandle leftNodeHandle(0xFFFFFFFF); - - const auto dataKey = MakeDataKey(renderSystem, scope, u8"RenderPassData"); - const auto renderPassDataNode = AddDataNode(leftNodeHandle, parent_node_handle, dataKey); - const auto renderPassNodeHandleResult = addInternalNode(GTSL::Hash(instance_name), renderPassDataNode); - - if(!renderPassNodeHandleResult) { return renderPassNodeHandleResult.Get(); } - - NodeHandle renderPassNodeHandle = renderPassNodeHandleResult.Get(); - - RenderPassData& renderPass = getPrivateNode(renderPassNodeHandle); - renderPass.DataKey = dataKey; - - auto renderPassIndex = renderPasses.GetLength(); - renderPassesMap.Emplace(render_pass_name, renderPassIndex); - renderPasses.EmplaceBack(renderPassNodeHandle); - - renderPass.resourceHandle = makeResource(render_pass_name); - addDependencyOnResource(renderPass.resourceHandle); //add dependency on render pass texture creation - - BindResourceToNode(renderPassNodeHandle, renderPass.resourceHandle); - - getNode(renderPassNodeHandle).Name = GTSL::StringView(instance_name); - - PassTypes renderPassType = PassTypes::RASTER; - GAL::PipelineStage pipelineStage; - - NodeHandle resultHandle = renderPassNodeHandle; - - switch (pass_data.type) { - case PassTypes::RASTER: { - renderPassType = PassTypes::RASTER; - pipelineStage = GAL::PipelineStages::COLOR_ATTACHMENT_OUTPUT; - - for (const auto& e : pass_data.Attachments) { - auto& attachmentData = renderPass.Attachments.EmplaceBack(); - - attachmentData.Name = e.Name; - attachmentData.Attachment = e.Attachment; - attachmentData.Access = e.Access; - - if (renderPassIndex) { - attachmentData.LoadOperation = GAL::Operations::DO; //UNDEFINED ? - } else { - attachmentData.LoadOperation = GAL::Operations::CLEAR; //UNDEFINED ? - } - - if (e.Access & GAL::AccessTypes::READ) { - attachmentData.Layout = GAL::TextureLayout::SHADER_READ; - attachmentData.ConsumingStages = GAL::PipelineStages::TOP_OF_PIPE; - } else { - attachmentData.Layout = GAL::TextureLayout::ATTACHMENT; - attachmentData.ConsumingStages = GAL::PipelineStages::COLOR_ATTACHMENT_OUTPUT; - } - - } - - break; - } - case PassTypes::COMPUTE: { - renderPassType = PassTypes::COMPUTE; - pipelineStage = GAL::PipelineStages::COMPUTE; - - for (const auto& e : pass_data.Attachments) { - auto& attachmentData = renderPass.Attachments.EmplaceBack(); - - attachmentData.Name = e.Name; - attachmentData.Attachment = e.Attachment; - attachmentData.Access = e.Access; - attachmentData.ConsumingStages = GAL::PipelineStages::COMPUTE; - - if (e.Access & GAL::AccessTypes::READ) { - attachmentData.Layout = GAL::TextureLayout::SHADER_READ; - } else { - attachmentData.Layout = GAL::TextureLayout::GENERAL; - } - } - - auto sgh = CreateShaderGroup(render_pass_name); - resultHandle = AddMaterial(renderPassNodeHandle, sgh); - - for(const auto e : innner) { - resultHandle = AddDataNode(resultHandle, e.Name, e.DKH); - } - - resultHandle = addInternalNode(GTSL::Hash(render_pass_name), resultHandle).Get(); - - GTSL::StaticString<128> namee(u8"Dispatch: "); namee += render_pass_name; - - setNodeName(resultHandle, namee); - - break; - } - case PassTypes::RAY_TRACING: { - renderPassType = PassTypes::RAY_TRACING; - pipelineStage = GAL::PipelineStages::RAY_TRACING; - - for (const auto& e : pass_data.Attachments) { - auto& attachmentData = renderPass.Attachments.EmplaceBack(); - - attachmentData.Name = e.Name; - attachmentData.Attachment = e.Attachment; - attachmentData.Access = e.Access; - - attachmentData.ConsumingStages = GAL::PipelineStages::RAY_TRACING; - - if (e.Access & GAL::AccessTypes::READ) { - attachmentData.Layout = GAL::TextureLayout::SHADER_READ; - } - else { - attachmentData.Layout = GAL::TextureLayout::ATTACHMENT; - } - - } - - break; - } - } - - renderPass.Type = renderPassType; - renderPass.PipelineStages = pipelineStage; - - auto bwk = GetBufferWriteKey(renderSystem, renderPass.DataKey); - - for (auto i = 0u; i < pass_data.Attachments.GetLength(); ++i) { - const auto& attachmentReference = pass_data.Attachments[i]; - - AddNodeDependency(renderPassNodeHandle); - - if(auto a = attachments.TryGet(attachmentReference.Attachment)) { - if(GTSL::IsIn(attachmentReference.Name, u8"History")) { // Set image reference as attachment for previous hit since history means we access previous frame's data - bwk[pass_data.Attachments[i].Name] = a.Get().ImageIndeces[(renderSystem->GetCurrentFrame() - 1) % renderSystem->GetPipelinedFrames()]; - } else { - bwk[pass_data.Attachments[i].Name] = a.Get().ImageIndeces[(renderSystem->GetCurrentFrame() - 1) % renderSystem->GetPipelinedFrames()]; - } - - FulfillNodeDependency(renderPassNodeHandle); - } else { - BE_LOG_WARNING(u8"Render pass: ", render_pass_name, u8", references attachment: ", attachmentReference.Name, u8", which does not exist. Render pass will be disabled."); - } - } - - return resultHandle; -} - -void RenderOrchestrator::OnResize(RenderSystem* renderSystem, const GTSL::Extent2D newSize) -{ - //pendingDeleteFrames = renderSystem->GetPipelinedFrames(); - - auto currentFrame = renderSystem->GetCurrentFrame(); - auto beforeFrame = uint8(currentFrame - uint8(1)) % renderSystem->GetPipelinedFrames(); - - auto resize = [&](Attachment& attachment) -> void { - GTSL::StaticString<64> name; name += GTSL::StringView(attachment.Name); GTSL::ToString(name, currentFrame); - - attachment.TextureHandle[currentFrame] = renderSystem->CreateTexture(name, attachment.format, newSize, attachment.Uses, false, attachment.TextureHandle[currentFrame]); - - for(uint32 i = 0; i < 2u; ++i) { - for(uint32 f = 0; f < GTSL::Math::Clamp(2u, 0u, frameIndex + 1u); ++f) { - if (attachment.format.Type == GAL::TextureType::COLOR) { //if attachment is of type color (not depth), write image descriptor - WriteBinding(renderSystem, imagesSubsetHandle, attachment.TextureHandle[f], attachment.ImageIndeces[f], i); - } - - WriteBinding(renderSystem, textureSubsetsHandle, attachment.TextureHandle[f], attachment.ImageIndeces[f], i); - } - } - - attachment.Layout[currentFrame] = GAL::TextureLayout::UNDEFINED; - }; - - if (views[0].sizeHistory[currentFrame] != newSize) { - views[0].sizeHistory[currentFrame] = newSize; - GTSL::ForEach(attachments, resize); - } - - for (const auto apiRenderPassData : renderPasses) { - auto& layer = getPrivateNode(apiRenderPassData); - signalDependencyToResource(layer.resourceHandle); - setRenderTreeAsDirty(apiRenderPassData); - } -} - -void RenderOrchestrator::ToggleRenderPass(NodeHandle renderPassName, bool enable) -{ - if (!renderPassName) { BE_LOG_WARNING(u8"Tried to ", enable ? u8"enable" : u8"disable", u8" a render pass which does not exist."); return; } - - auto& renderPassNode = getPrivateNode(renderPassName); - - switch (renderPassNode.Type) { - case PassTypes::RASTER: break; - case PassTypes::COMPUTE: break; - case PassTypes::RAY_TRACING: enable = enable && BE::Application::Get()->GetBoolOption(u8"rayTracing"); break; // Enable render pass only if function is enaled in settings - default: break; - } - - SetNodeState(renderPassName, enable); -} - -void RenderOrchestrator::onRenderEnable(ApplicationManager* gameInstance, const GTSL::Range dependencies) { - //gameInstance->AddTask(SETUP_TASK_NAME, &RenderOrchestrator::Setup, DependencyBlock(), u8"GameplayEnd", u8"RenderStart"); - //gameInstance->AddTask(RENDER_TASK_NAME, &RenderOrchestrator::Render, DependencyBlock(), u8"RenderDo", u8"RenderFinished"); -} - -void RenderOrchestrator::onRenderDisable(ApplicationManager* gameInstance) { - //gameInstance->RemoveTask(SETUP_TASK_NAME, u8"GameplayEnd"); - //gameInstance->RemoveTask(RENDER_TASK_NAME, u8"RenderDo"); -} - -void RenderOrchestrator::OnRenderEnable(TaskInfo taskInfo, bool oldFocus) { - renderingEnabled = true; -} - -void RenderOrchestrator::OnRenderDisable(TaskInfo taskInfo, bool oldFocus) { - renderingEnabled = false; -} - -void RenderOrchestrator::transitionImages(CommandList commandBuffer, RenderSystem* renderSystem, const RenderPassData* renderPass) -{ - GTSL::StaticVector barriers; - - GAL::PipelineStage initialStage; - - auto buildTextureBarrier = [&](const AttachmentData& attachmentData, GAL::PipelineStage attachmentStages, GAL::AccessType access) { - auto& attachment = attachments.At(attachmentData.Attachment); - - CommandList::TextureBarrier textureBarrier; - textureBarrier.texture = renderSystem->GetTexture(attachment.TextureHandle[renderSystem->GetCurrentFrame()]); - textureBarrier.CurrentLayout = attachment.Layout[renderSystem->GetCurrentFrame()]; - textureBarrier.Format = attachment.format; - textureBarrier.TargetLayout = attachmentData.Layout; - barriers.EmplaceBack(initialStage, renderPass->PipelineStages, attachment.AccessType, access, textureBarrier); - - initialStage |= attachment.ConsumingStages; - - updateImage(renderSystem->GetCurrentFrame(), attachment, attachmentData.Layout, renderPass->PipelineStages, access); - }; - - for (auto& e : renderPass->Attachments) { buildTextureBarrier(e, e.ConsumingStages, e.Access); } - - commandBuffer.AddPipelineBarrier(renderSystem->GetRenderDevice(), barriers, GetTransientAllocator()); -} - -//TODO: GRANT CONTINUITY TO ALLOCATED PIPELINES PER SHADER GROUP - -void RenderOrchestrator::onShaderInfosLoaded(TaskInfo taskInfo, ShaderResourceManager* materialResourceManager, - ShaderResourceManager::ShaderGroupInfo shader_group_info, ShaderLoadInfo shaderLoadInfo) -{ - if constexpr (BE_DEBUG) { - bool valid = true; - - for(auto& e : shader_group_info.Shaders) { //If any shader is size zero, then shader group cannot be used. - if(e.Size == 0u) { valid = false; break; } - } - - if (!valid or !shader_group_info.Shaders) { - BE_LOG_ERROR(u8"Tried to load shader group ", shader_group_info.Name, u8" which is not valid. ", BE::FIX_OR_CRASH_STRING); - return; - } - } - - uint32 size = 0; - - for (auto& s : shader_group_info.Shaders) { size += s.Size; } - - shaderLoadInfo.Buffer.Allocate(size, 16); - shaderLoadInfo.Buffer.PushBytes(size); - - auto shaderGroupWasEmplaced = shaderGroupsByName.TryEmplace(shader_group_info.Name, ~0u); - - if(shaderGroupWasEmplaced) { - auto shaderGroupIndex = shaderGroups.Emplace(); - shaderGroupWasEmplaced.Get() = shaderGroupIndex; - auto& shaderGroup = shaderGroups[shaderGroupIndex]; - - shaderGroup.Name = shader_group_info.Name; - shaderGroup.Buffer = MakeDataKey(); - shaderGroup.Resource = makeResource(shader_group_info.Name); - - for(auto& e : shader_group_info.Instances) { - if(!shaderGroupInstanceByName.Find(e.Name)) { continue; } - auto& instance = shaderGroupInstances[shaderGroupInstanceByName[e.Name]]; - instance.Name = e.Name; - instance.ShaderGroupIndex = shaderGroupIndex; - addDependencyOnResource(shaderGroup.Resource, instance.Resource); - } - } - - materialResourceManager->LoadShaderGroup(taskInfo.AppManager, GTSL::MoveRef(shader_group_info), onShaderGroupLoadHandle, shaderLoadInfo.Buffer.GetRange(), GTSL::MoveRef(shaderLoadInfo)); -} - -void RenderOrchestrator::onShadersLoaded(TaskInfo taskInfo, ShaderResourceManager*, RenderSystem* renderSystem, ShaderResourceManager::ShaderGroupInfo shader_group_info, GTSL::Range buffer, ShaderLoadInfo shaderLoadInfo) -{ - auto& shaderGroup = shaderGroups[shaderGroupsByName[shader_group_info.Name]]; - - if(shaderGroup.Loaded) { return; } - - addScope(u8"global", shader_group_info.Name); - - GTSL::StaticVector pipelineStates; - - GTSL::HashMap parameters(8, GetTransientAllocator()); - - GTSL::StaticVector, 8> vertexStreams; - - struct ShaderBundleData { - GTSL::StaticVector Shaders; - GAL::ShaderStage Stage; - uint32 PipelineIndex = 0; - GTSL::ShortString<32> Set; - bool Transparency = false; - }; - GTSL::StaticVector shaderBundles; - GTSL::StaticVector members; - GTSL::KeyMap loadedShadersMap(8, GetTransientAllocator()); //todo: differentiate hash from hash + name, since a different hash could be interpreted as a different shader, when in reality it functionally represents the same shader but with different code - - GTSL::StaticString<64> executionString; - - shaderGroupNotify(this, renderSystem); - - // DEBUGGING ONLY: whether to check for integrity in shader member definitions, etc - const auto debugShaders = BE::Application::Get()->GetConfig()[u8"RenderOrchestrator"][u8"inspectShaders"].GetBool(); - - // Construct vertex stream description for pipeline from shader group info. - for (uint8 ai = 0; auto& a : shader_group_info.VertexElements) { - auto& stream = vertexStreams.EmplaceBack(); - - for (auto& b : a) { - GAL::ShaderDataType type; - - switch (GTSL::Hash(b.Type)) { - case GTSL::Hash(u8"vec2f"): type = GAL::ShaderDataType::FLOAT2; break; - case GTSL::Hash(u8"vec3f"): type = GAL::ShaderDataType::FLOAT3; break; - case GTSL::Hash(u8"vec4f"): type = GAL::ShaderDataType::FLOAT4; break; - } - - stream.EmplaceBack(GAL::Pipeline::VertexElement{ GTSL::ShortString<32>(b.Name.c_str()), type, ai++ }); - } - } - - for (uint32 offset = 0, si = 0; si < shader_group_info.Shaders; offset += shader_group_info.Shaders[si].Size, ++si) { - const auto& shaderInfo = shader_group_info.Shaders[si]; - - //TODO: cheap hack to filter shaders by render technique - if (Contains(shaderInfo.Tags.GetRange(), PermutationManager::ShaderTag(u8"Domain", u8"World"))) { - if (!Contains(shaderInfo.Tags.GetRange(), PermutationManager::ShaderTag(u8"RenderTechnique", tag)) && !Contains(shader_group_info.Tags, PermutationManager::ShaderTag(u8"RenderTechnique", tag))) { - BE_LOG_WARNING(u8"Ignoring shader: ", shaderInfo.Name, u8" because it does not feature needed tag: ", tag); - continue; - } - } - - if (auto res = shaders.TryEmplace(shaderInfo.Hash)) { - auto& shader = res.Get(); - - shader.Shader.Initialize(renderSystem->GetRenderDevice(), GTSL::Range(shaderInfo.Size, shaderLoadInfo.Buffer.GetData() + offset)); - shader.Type = shaderInfo.Type; - shader.Name = shaderInfo.Name; - loadedShadersMap.Emplace(shaderInfo.Hash); - - if(shaderInfo.DebugData){ // Check if shader symbols match active runtime symbols - auto json = GTSL::JSON(shaderInfo.DebugData, GetPersistentAllocator()); - - for(auto jsonStruct : json[u8"structs"]) { - auto structName = jsonStruct[u8"name"].GetStringView(); - - auto handle = tryGetDataTypeHandle(structName); - - if(!handle) { - if(debugShaders) { - BE_LOG_WARNING(u8"Could not find compatible shader declared symbol: ", structName); - } - - continue; - } - - auto& element = getElement(handle.Get()); - - for(auto c : jsonStruct[u8"members"]) { - auto memberSearchResult = tryGetDataTypeHandle(handle.Get(), c[u8"name"]); - - if(!memberSearchResult) { - if(debugShaders) { - BE_LOG_WARNING(u8"Shader symbol ", structName, u8", has member: ", c[u8"name"], u8", which matching renderer symbol doesn't."); - } - } - } - - for(auto& e : element.children) { - auto& f = getElement(e.Handle); - if(f.Type != ElementData::ElementType::MEMBER) { continue; } - - [&]() { - for(auto c : jsonStruct[u8"members"]) { - if(c[f.Name]) { - return; - } - } - - if(debugShaders) { - BE_LOG_WARNING(u8"Renderer symbol ", element.Name, u8", has member: ", f.Name, u8", which matching shader symbol doesn't."); - } - }; - } - } - - if(!shaderGroup.PushConstantLayout) { - for(auto e : json[u8"pushConstant"][u8"members"]) { - shaderGroup.PushConstantLayout.EmplaceBack(e[u8"type"], e[u8"name"]); - } - } - } - } - - if (auto executionExists = GTSL::Find(shaderInfo.Tags, [&](const PermutationManager::ShaderTag& tag) { return static_cast(tag.First) == u8"Execution"; })) { - executionString = executionExists.Get()->Second; - } - - bool foundGroup = false; - auto shaderStageFlag = GAL::ShaderTypeToShaderStageFlag(shaderInfo.Type); - - for (auto& e : shaderBundles) { - if (e.Stage & (GAL::ShaderStages::VERTEX | GAL::ShaderStages::FRAGMENT) && shaderStageFlag & (GAL::ShaderStages::VERTEX | GAL::ShaderStages::FRAGMENT)) { - e.Shaders.EmplaceBack(si); - e.Stage |= shaderStageFlag; - foundGroup = true; - break; - } - - if (e.Stage & (GAL::ShaderStages::RAY_GEN | GAL::ShaderStages::CLOSEST_HIT | GAL::ShaderStages::MISS | GAL::ShaderStages::INTERSECTION) && shaderStageFlag & (GAL::ShaderStages::RAY_GEN | GAL::ShaderStages::CLOSEST_HIT | GAL::ShaderStages::MISS | GAL::ShaderStages::INTERSECTION)) { - e.Shaders.EmplaceBack(si); - e.Stage |= shaderStageFlag; - foundGroup = true; - break; - } - } - - if (!foundGroup) { - auto& sb = shaderBundles.EmplaceBack(); - sb.Shaders.EmplaceBack(si); - sb.Stage = shaderStageFlag; - if(auto r = GTSL::Find(shaderInfo.Tags, [&](const PermutationManager::ShaderTag& tag) { return static_cast(tag.First) == u8"Set"; })) { - sb.Set = GTSL::StringView(r.Get()->Second); - } - - } else { - switch (shaderInfo.Type) { - case GAL::ShaderType::VERTEX: break; - case GAL::ShaderType::FRAGMENT: break; //todo: set transparency - case GAL::ShaderType::COMPUTE: break; - case GAL::ShaderType::TASK: break; - case GAL::ShaderType::MESH: break; - case GAL::ShaderType::RAY_GEN: break; - case GAL::ShaderType::CLOSEST_HIT: break; - case GAL::ShaderType::ANY_HIT: break; - case GAL::ShaderType::INTERSECTION: break; - case GAL::ShaderType::MISS: break; - case GAL::ShaderType::CALLABLE: break; - default: ; - } - } - } - - GTSL::StaticVector specializationEntries; - GTSL::StaticBuffer<1024> specializationData; - - { - auto& debugEntry = specializationEntries.EmplaceBack(); - debugEntry.Size = 4; debugEntry.Offset = 0u; debugEntry.ID = 0u; - specializationData.AllocateStructure(BE::Application::Get()->GetConfig()[u8"RenderOrchestrator"][u8"debugShaders"].GetBool()); - - for (uint32 pi = 0; const auto & p : shader_group_info.Parameters) { - { - parameters.Emplace(p.Name, p.Type, p.Name, p.Value); - members.EmplaceBack(MemberInfo{ &shaderGroup.ParametersHandles.Emplace(Id(p.Name)), p.Type, p.Name }); - } - } - - auto& specializations = pipelineStates.EmplaceBack(GAL::Pipeline::PipelineStateBlock::SpecializationData{}); - - specializations.Specialization.Entries = specializationEntries; - specializations.Specialization.Data = specializationData.GetRange(); - } - - for (auto& e : shaderBundles) { - GTSL::Vector shaderInfos(8, GetTransientAllocator()); - - if (e.Stage & (GAL::ShaderStages::VERTEX | GAL::ShaderStages::FRAGMENT)) { - if (shaderGroup.RasterPipelineIndex == 0xFFFFFFFF) { //if no pipeline already exists for this stage, create one - shaderGroup.RasterPipelineIndex = pipelines.Emplace(GetPersistentAllocator()); - } - - e.PipelineIndex = shaderGroup.RasterPipelineIndex; - - for (auto s : e.Shaders) { - auto& shaderInfo = shaderInfos.EmplaceBack(); - auto& shader = shaders[shader_group_info.Shaders[s].Hash]; - shaderInfo.Type = shader.Type; - shaderInfo.Shader = shader.Shader; - } - - GTSL::StaticVector attachmentStates; - - GAL::Pipeline::PipelineStateBlock::RenderContext context; - - GTSL::StaticString<128> renderPass{ u8"ForwardRenderPass" }; - - if (auto r = GTSL::Find(shader_group_info.Tags, [&](const PermutationManager::ShaderTag& tag) { return static_cast(tag.First) == u8"RenderPass"; })) { - renderPass = GTSL::StringView(r.Get()->Second); - } - - bool transparency = false; - - if (auto r = GTSL::Find(shader_group_info.Tags, [&](const PermutationManager::ShaderTag& tag) { return static_cast(tag.First) == u8"Transparency"; })) { - transparency = r.Get()->Second == GTSL::StringView(u8"true"); - } - - //TODO: if shader group gets processed before render pass it will fail - if(auto renderPassReference = renderPassesMap.TryGet(renderPass)) { - const auto& renderPassNode = getPrivateNode(renderPasses[renderPassReference.Get()]); - - for (const auto& writeAttachment : renderPassNode.Attachments) { - if (writeAttachment.Access & GAL::AccessTypes::WRITE) { - auto& attachment = attachments.At(writeAttachment.Name); - auto& attachmentState = attachmentStates.EmplaceBack(); - attachmentState.BlendEnable = transparency; attachmentState.Format = attachment.format; - } - } - } else { - BE_LOG_ERROR(u8"Shader group: ", shader_group_info.Name, u8", references render pass: ", renderPass, u8" which does not exist."); - return; - } - - context.Attachments = attachmentStates; - pipelineStates.EmplaceBack(context); - - if (!transparency) { - GAL::Pipeline::PipelineStateBlock::DepthState depth; - depth.compareOperation = INVERSE_Z ? GAL::CompareOperation::GREATER : GAL::CompareOperation::LESS; - pipelineStates.EmplaceBack(depth); - } - - GAL::Pipeline::PipelineStateBlock::RasterState rasterState; - rasterState.cullMode = GAL::CullMode::CULL_BACK; - rasterState.windingOrder = GAL::WindingOrder::CLOCKWISE; - pipelineStates.EmplaceBack(rasterState); - - GAL::Pipeline::PipelineStateBlock::ViewportState viewportState; - viewportState.ViewportCount = 1; - pipelineStates.EmplaceBack(viewportState); - - auto& vertexState = pipelineStates.EmplaceBack(GAL::Pipeline::PipelineStateBlock::VertexState{}); - - GTSL::StaticVector, 8> vertexStreamsRanges; - - for(auto& vs : vertexStreams) { vertexStreamsRanges.EmplaceBack(vs); } - - vertexState.Vertex.VertexStreams = vertexStreamsRanges; - - pipelines[e.PipelineIndex].pipeline.InitializeRasterPipeline(renderSystem->GetRenderDevice(), pipelineStates, shaderInfos, setLayoutDatas[globalSetLayout()].pipelineLayout, renderSystem->GetPipelineCache()); - } - - if (e.Stage & GAL::ShaderStages::COMPUTE) { - if (shaderGroup.ComputePipelineIndex == 0xFFFFFFFF) { //if no pipeline already exists for this stage, create one - shaderGroup.ComputePipelineIndex = pipelines.Emplace(GetPersistentAllocator()); - } - - e.PipelineIndex = shaderGroup.ComputePipelineIndex; - - auto& pipeline = pipelines[e.PipelineIndex]; - - for (auto s : e.Shaders) { - auto& shaderInfo = shaderInfos.EmplaceBack(); - auto& shader = shaders[shader_group_info.Shaders[s].Hash]; - shaderInfo.Type = shader.Type; - shaderInfo.Shader = shader.Shader; - } - - pipeline.ExecutionString = executionString; - - pipeline.pipeline.InitializeComputePipeline(renderSystem->GetRenderDevice(), pipelineStates, shaderInfos, setLayoutDatas[globalSetLayout()].pipelineLayout, renderSystem->GetPipelineCache()); - } - - if (e.Stage & (GAL::ShaderStages::RAY_GEN | GAL::ShaderStages::CLOSEST_HIT)) { - if (!BE::Application::Get()->GetBoolOption(u8"rayTracing")) { continue; } - - if(auto r = rayTracingSets.TryEmplace(Id(e.Set), 0xFFFFFFFFu)) { - shaderGroup.RTPipelineIndex = pipelines.Emplace(GetPersistentAllocator()); - r.Get() = shaderGroup.RTPipelineIndex; - } else { - shaderGroup.RTPipelineIndex = r.Get(); - } - - e.PipelineIndex = shaderGroup.RTPipelineIndex; - - auto& pipelineData = pipelines[e.PipelineIndex]; - - //add newly loaded shaders to new pipeline update - for (auto s : e.Shaders) { - pipelineData.Shaders.EmplaceBack(shader_group_info.Shaders[s].Hash); - } - - GTSL::Sort(pipelineData.Shaders, [&](uint64 a, uint64 b) { return shaders[a].Type > shaders[b].Type; }); - - //add already loaded shaders to shaderInfos, todo: use pipeline libraries to accumulate state properly - for (auto s : pipelineData.Shaders) { - auto& shaderInfo = shaderInfos.EmplaceBack(); - auto& shader = shaders[s]; - shaderInfo.Type = shader.Type; - shaderInfo.Shader = shader.Shader; - //shaderInfo.Blob = GTSL::Range(shader_group_info.Shaders[s].Size, shaderLoadInfo.Buffer.GetData() + offset); - } - - GTSL::Vector rayTracingGroups(16, GetTransientAllocator()); - - GPUPipeline::PipelineStateBlock::RayTracingState rayTracePipelineState; - rayTracePipelineState.MaxRecursionDepth = 1; - - for (uint32 i = 0; i < pipelineData.Shaders; ++i) { - auto& shaderInfo = shaders[pipelineData.Shaders[i]]; - - GPUPipeline::RayTraceGroup group; uint8 rtShaderGroupIndex = 0xFF; - - switch (shaderInfo.Type) { - case GAL::ShaderType::RAY_GEN: - group.ShaderGroup = GAL::ShaderGroupType::GENERAL; group.GeneralShader = i; - rtShaderGroupIndex = GAL::RAY_GEN_TABLE_INDEX; - GTSL::Max(&rayTracePipelineState.MaxRecursionDepth, static_cast(1)); - break; - case GAL::ShaderType::MISS: - group.ShaderGroup = GAL::ShaderGroupType::GENERAL; group.GeneralShader = i; - rtShaderGroupIndex = GAL::MISS_TABLE_INDEX; - break; - case GAL::ShaderType::CALLABLE: - group.ShaderGroup = GAL::ShaderGroupType::GENERAL; group.GeneralShader = i; - rtShaderGroupIndex = GAL::CALLABLE_TABLE_INDEX; - break; - case GAL::ShaderType::CLOSEST_HIT: - group.ShaderGroup = GAL::ShaderGroupType::TRIANGLES; group.ClosestHitShader = i; - rtShaderGroupIndex = GAL::HIT_TABLE_INDEX; - break; - case GAL::ShaderType::ANY_HIT: - group.ShaderGroup = GAL::ShaderGroupType::TRIANGLES; group.AnyHitShader = i; - rtShaderGroupIndex = GAL::HIT_TABLE_INDEX; - break; - case GAL::ShaderType::INTERSECTION: - group.ShaderGroup = GAL::ShaderGroupType::PROCEDURAL; group.IntersectionShader = i; - rtShaderGroupIndex = GAL::HIT_TABLE_INDEX; - break; - default: BE_LOG_MESSAGE(u8"Non raytracing shader found in raytracing material"); - } - - rayTracingGroups.EmplaceBack(group); - - if (loadedShadersMap.Find(pipelineData.Shaders[i])) { // Only increment shader count when a new shader is added (not when updated since the shader is already there) - ++pipelineData.RayTracingData.ShaderGroups[rtShaderGroupIndex].ShaderCount; - } - } - - rayTracePipelineState.Groups = rayTracingGroups; - pipelineStates.EmplaceBack(rayTracePipelineState); - - auto oldPipeline = pipelineData.pipeline; - - pipelineData.ExecutionString = executionString; - - pipelineData.pipeline.InitializeRayTracePipeline(renderSystem->GetRenderDevice(), pipelineData.pipeline, pipelineStates, shaderInfos, setLayoutDatas[globalSetLayout()].pipelineLayout, renderSystem->GetPipelineCache()); - - if (oldPipeline.GetHandle()) { //TODO: defer deletion - oldPipeline.Destroy(renderSystem->GetRenderDevice()); - } - } - - signalDependencyToResource(shaderGroup.Resource); //add ref count for pipeline load itself, todo: do we signal even when we are doing a pipeline update? - - for(auto& k : shader_group_info.Instances) { - if(!shaderGroupInstanceByName.Find(k.Name)) { continue; } - auto& instance = shaderGroupInstances[shaderGroupInstanceByName[k.Name]]; - signalDependencyToResource(instance.Resource); //add ref count for pipeline load itself, todo: do we signal even when we are doing a pipeline update? - } - } - - if (!shaderGroup.Loaded) { - shaderGroup.Loaded = true; - - GTSL::StaticString<64> scope(u8"global"); scope << u8"." << GTSL::StringView(shader_group_info.Name); - - auto materialDataMember = RegisterType(scope, u8"ShaderParametersData", members); - shaderGroup.Buffer = MakeDataKey(renderSystem, scope, u8"ShaderParametersData[4]", shaderGroup.Buffer); // Create shader group data in array, with an element for each instance - - auto bwk = GetBufferWriteKey(renderSystem, shaderGroup.Buffer); - - for (uint8 ii = 0; auto & i : shader_group_info.Instances) { //TODO: check parameters against stored layout to check if everything is still compatible - if(!shaderGroupInstanceByName.Find(i.Name)) { continue; } - auto& instance = shaderGroupInstances[shaderGroupInstanceByName[i.Name]]; - - WriteUpdateKey(renderSystem, instance.UpdateKey, uint32(ii)); - - CopyDataKey(instance.DataKey, shaderGroup.Buffer, instance.Name == u8"BlurV" ? 8 : 0); - - auto instanceElement = bwk[ii]; - - for (uint32 pi = 0; auto & p : i.Parameters) { - GTSL::StaticString<32> parameterValue; - - const auto& parameter = parameters[p.First]; - - // If shader group instance has specialized value for parameter, use that, else, fallback to shader group default value for parameter. - if (p.Second) { - parameterValue = p.Second; - } else { - parameterValue = parameter.DefaultValue; - } - - switch (GTSL::Hash(parameter.Type)) { - case GTSL::Hash(u8"vec2u"): { - struct vec2u { uint32 x, y; }; - - vec2u vec = { GTSL::ToNumber({1, 1, parameterValue.c_str()}).Get(), GTSL::ToNumber({1, 1, parameterValue.c_str() + 3}).Get() }; - - instanceElement[parameter.Name] = vec; - break; - } - case GTSL::Hash(u8"TextureReference"): { - CreateTextureInfo createTextureInfo; - createTextureInfo.renderSystem = renderSystem; - createTextureInfo.applicationManager = taskInfo.AppManager; - createTextureInfo.textureResourceManager = taskInfo.AppManager->GetSystem(u8"TextureResourceManager"); - createTextureInfo.TextureName = parameterValue; - auto textureReference = createTexture(createTextureInfo); - - instanceElement[p.First] = textureReference; - - for (auto& e : shaderBundles) { - addPendingResourceToTexture(parameterValue, instance.Resource); - } - - break; - } - case GTSL::Hash(u8"ImageReference"): { - if (auto textureReference = attachments.TryGet(parameterValue)) { - uint32 textureComponentIndex = textureReference.Get().ImageIndeces[0]; // TODO: noo - instanceElement[p.First] = textureComponentIndex; - } else { - BE_LOG_WARNING(u8"Default parameter value of ", GTSL::StringView(parameterValue), u8" for shader group ", shader_group_info.Name, u8" parameter ", p.First, u8" could not be found."); - } - - break; - } - } - - ++pi; - } - - ++ii; - } - } - - for (auto& e : shaderBundles) { - if (e.Stage & (GAL::ShaderStages::RAY_GEN | GAL::ShaderStages::CLOSEST_HIT | GAL::ShaderStages::ANY_HIT | GAL::ShaderStages::MISS | GAL::ShaderStages::CALLABLE)) { - if (!BE::Application::Get()->GetBoolOption(u8"rayTracing")) { continue; } - - auto& pipeline = pipelines[e.PipelineIndex]; auto& rtPipelineData = pipeline.RayTracingData; - - GTSL::Vector shaderGroupHandlesBuffer(e.Shaders.GetLength(), GetTransientAllocator()); - pipeline.pipeline.GetShaderGroupHandles(renderSystem->GetRenderDevice(), 0, pipeline.Shaders.GetLength(), shaderGroupHandlesBuffer); - GTSL::StaticVector tablePerGroup[4]; - - for (uint32 shaderGroupIndex = 0, shaderCount = 0; shaderGroupIndex < 4; ++shaderGroupIndex) { - auto& groupData = rtPipelineData.ShaderGroups[shaderGroupIndex]; - for (uint32 i = 0; i < groupData.ShaderCount; ++i, ++shaderCount) { - auto& entry = rtPipelineData.ShaderGroups[shaderGroupIndex].Instances.EmplaceBack(); - tablePerGroup[shaderGroupIndex].EmplaceBack(&entry.ShaderHandle, u8"ShaderHandle", u8"shaderHandle"); - tablePerGroup[shaderGroupIndex].EmplaceBack(&entry.Elements.EmplaceBack(), u8"ptr_t", u8"materialData"); - } - } - - GTSL::StaticVector tables{ - { &rtPipelineData.ShaderGroups[0].TableHandle, tablePerGroup[0], u8"RayGenTable", u8"rayGenTable", renderSystem->GetShaderGroupBaseAlignment()}, - { &rtPipelineData.ShaderGroups[1].TableHandle, tablePerGroup[1], u8"ClosestHitTable", u8"closestHitTable", renderSystem->GetShaderGroupBaseAlignment()}, - { &rtPipelineData.ShaderGroups[2].TableHandle, tablePerGroup[2], u8"MissTable", u8"missTable", renderSystem->GetShaderGroupBaseAlignment()}, - { &rtPipelineData.ShaderGroups[3].TableHandle, tablePerGroup[3], u8"CallableTable", u8"callableTable", renderSystem->GetShaderGroupBaseAlignment()}, - }; - RegisterType(GTSL::StaticString<128>(u8"global") << u8"." << GTSL::StringView(shader_group_info.Name), u8"ShaderTableData", tables); - pipeline.ShaderBindingTableBuffer = MakeDataKey(renderSystem, GTSL::StaticString<128>(u8"global") << u8"." << GTSL::StringView(shader_group_info.Name), u8"ShaderTableData", pipeline.ShaderBindingTableBuffer, GAL::BufferUses::SHADER_BINDING_TABLE); - - auto bWK = GetBufferWriteKey(renderSystem, pipeline.ShaderBindingTableBuffer); - - for (uint32 shaderGroupIndex = 0, shaderCount = 0; shaderGroupIndex < 4; ++shaderGroupIndex) { - auto& groupData = rtPipelineData.ShaderGroups[shaderGroupIndex]; - for (uint32 i = 0; i < groupData.ShaderCount; ++i, ++shaderCount) { - auto table = bWK[tables[shaderGroupIndex].Name]; - table[u8"shaderHandle"] = shaderGroupHandlesBuffer[shaderCount]; - - uint64 shaderHandleHash = 0; - - shaderHandleHash = quickhash64({ 32, reinterpret_cast(&shaderGroupHandlesBuffer[shaderCount]) }); - - if(auto r = shaderHandlesDebugMap.TryEmplace(shaderHandleHash, shaders[pipeline.Shaders[shaderCount]].Name); !r) { - BE_LOG_ERROR(u8"Could not emplace "); - } - } - } - } - } -} - -uint32 RenderOrchestrator::createTexture(const CreateTextureInfo& createTextureInfo) { - - if (auto t = textures.TryEmplace(createTextureInfo.TextureName)) { - t.Get().Index = textureIndex++; ++imageIndex; - auto textureLoadInfo = TextureLoadInfo(RenderAllocation()); - createTextureInfo.textureResourceManager->LoadTextureInfo(createTextureInfo.applicationManager, Id(createTextureInfo.TextureName), onTextureInfoLoadHandle, GTSL::MoveRef(textureLoadInfo)); - t.Get().Resource = makeResource(createTextureInfo.TextureName); - return t.Get().Index; - } - else { - return t.Get().Index; - } -} - -void RenderOrchestrator::onTextureInfoLoad(TaskInfo taskInfo, TextureResourceManager* resourceManager, RenderSystem* renderSystem, - TextureResourceManager::TextureInfo textureInfo, TextureLoadInfo loadInfo) -{ - GTSL::StaticString<128> name(u8"Texture resource: "); name += GTSL::Range(textureInfo.GetName()); - - loadInfo.TextureHandle = renderSystem->CreateTexture(name, textureInfo.Format, textureInfo.Extent, GAL::TextureUses::SAMPLE | GAL::TextureUses::ATTACHMENT, true); - - auto dataBuffer = renderSystem->GetTextureRange(loadInfo.TextureHandle); - - resourceManager->LoadTexture(taskInfo.AppManager, textureInfo, dataBuffer, onTextureLoadHandle, GTSL::MoveRef(loadInfo)); -} - -void RenderOrchestrator::onTextureLoad(TaskInfo taskInfo, TextureResourceManager* resourceManager, RenderSystem* renderSystem, TextureResourceManager::TextureInfo textureInfo, TextureLoadInfo loadInfo) -{ - renderSystem->UpdateTexture(transferCommandList[renderSystem->GetCurrentFrame()], loadInfo.TextureHandle); - - auto& texture = textures[textureInfo.GetName()]; - - for(uint8 f = 0; f < renderSystem->GetPipelinedFrames(); ++f) { - WriteBinding(renderSystem, textureSubsetsHandle, loadInfo.TextureHandle, texture.Index, f); - } - - signalDependencyToResource(texture.Resource); -} \ No newline at end of file diff --git a/src/ByteEngine/Render/RenderOrchestrator.h b/src/ByteEngine/Render/RenderOrchestrator.h deleted file mode 100644 index adf859a6..00000000 --- a/src/ByteEngine/Render/RenderOrchestrator.h +++ /dev/null @@ -1,2391 +0,0 @@ -#pragma once - -#include "ByteEngine/Game/System.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include "Culling.h" -#include "RenderSystem.h" -#include "RenderTypes.h" -#include "UIManager.h" -#include "ByteEngine/Id.h" -#include "ByteEngine/Game/Tasks.h" -#include "ByteEngine/Resources/FontResourceManager.h" -#include "ByteEngine/Resources/ShaderResourceManager.h" -#include "ByteEngine/Resources/TextureResourceManager.h" - -#include "ByteEngine/Graph.hpp" - -class RenderOrchestrator; -class RenderState; -class RenderGroup; -struct TaskInfo; - -//Data Entry -// - Data on a globally accesible buffer - -//Make Member -// - Make a struct declaration - -//Add Node -// - Adds a node to the render tree - -//Make Data Ker -// - Adds a member allocation to the global buffer - -//Bind Data Key -// - Bind a data key to a node - -//Assists in determining a type's name when used in a shader, can assist validation -template -struct TypeNamer { - //if type is not known return empty - static constexpr const char8_t* NAME = nullptr; -}; - -template<> -struct TypeNamer { - static constexpr const char8_t* NAME = u8"ptr_t"; -}; - -template<> -struct TypeNamer { - static constexpr const char8_t* NAME = u8"float32"; -}; - -template<> -struct TypeNamer { - static constexpr const char8_t* NAME = u8"matrix3x4f"; -}; - -inline void ToString(auto& string, const GTSL::Range*> range) { - for (uint32 i = 0; i < range.ElementCount(); ++i) { - if (i) { string += u8", "; } - string += range[i]; - } -} - -/** - * \brief Renders a frame according to a specfied model/pipeline. - * E.J: Forward Rendering, Deferred Rendering, Ray Tracing, etc. - */ -class RenderPipeline : public BE::System { -public: - RenderPipeline(const InitializeInfo& initialize_info, const char8_t* name) : System(initialize_info, name) {} -}; - -class RenderOrchestrator : public BE::System { -public: - MAKE_HANDLE(uint32, ElementData); - - enum class PassTypes : uint8 { - RASTER, COMPUTE, RAY_TRACING - }; - - enum class NodeType : uint8 { - DISPATCH, RAY_TRACE, MATERIAL, MESHES, RENDER_PASS, LAYER - }; - - struct Member { - Member() = default; - Member(const GTSL::StringView type, const GTSL::StringView name) : Type(type), Name(name) {} - - GTSL::StringView Type, Name; - }; - - struct MemberHandle { - MemberHandle() = default; - MemberHandle(const ElementDataHandle han) : Handle(han) {} - - ElementDataHandle Handle; uint32 Index = 0; - }; - - struct NodeHandle { - NodeHandle() = default; - NodeHandle(const uint32 val) : value(val) {} - - uint32 operator()() const { return value; } - - operator bool() const { return value; } - - bool operator==(const NodeHandle& other) const { - return value == other.value; - } - private: - uint32 value = 0; - }; - -protected: - MAKE_HANDLE(uint64, Resource); - - struct AttachmentData { - GTSL::StaticString<64> Name, Attachment; - GAL::TextureLayout Layout; - GAL::PipelineStage ConsumingStages; - GAL::AccessType Access; - GAL::Operations LoadOperation; - }; - - struct APIRenderPassData { - RenderPass renderPass; - uint8 APISubPass = 0, SubPassCount = 0; - }; - -public: - struct MemberInfo : Member { - MemberInfo() = default; - MemberInfo(MemberHandle* memberHandle, GTSL::StringView type, GTSL::StringView name) : Member(type, name), Handle(memberHandle) {} - MemberInfo(MemberHandle* memberHandle, GTSL::Range memberInfos, GTSL::StringView type, GTSL::StringView name, const uint32 alignment = 0) : Member(type, name), Handle(memberHandle), MemberInfos(memberInfos), alignment(alignment) {} - - MemberHandle* Handle = nullptr; - GTSL::Range MemberInfos; - uint16 alignment = 1; - }; - - explicit RenderOrchestrator(const InitializeInfo& initializeInfo); - - MAKE_HANDLE(uint32, Set); - - struct SubSetDescription { - SetHandle setHandle; uint32 Subset; - GAL::BindingType Type; - }; - - MAKE_HANDLE(SubSetDescription, SubSet); - MAKE_HANDLE(uint64, SetLayout); - MAKE_HANDLE(uint32, DataKey); - - // ------------ Data Keys ------------ - - DataKeyHandle MakeDataKey() { - auto pos = dataKeysMap.GetLength(); - dataKeysMap.EmplaceBack(dataKeys.Emplace(), 0u); - return DataKeyHandle(pos); - } - - [[nodiscard]] DataKeyHandle MakeDataKey(RenderSystem* renderSystem, const GTSL::StringView scope, const GTSL::StringView type, DataKeyHandle data_key_handle = DataKeyHandle(), GAL::BufferUse buffer_uses = GAL::BufferUse()) { - RenderSystem::BufferHandle b[2]{}; - - GTSL::StaticString<128> string(u8"Buffer: "); string << scope << u8"." << type; - const auto handle = addMember(scope, type, string); - - const auto size = GetSize(handle.Get()); - - b[0] = renderSystem->CreateBuffer(size, buffer_uses, true, b[0]); // Create host local, mappable buffer - b[1] = renderSystem->CreateBuffer(size, buffer_uses, false, b[1]); // Create device local buffer to copy content into - - if(!data_key_handle) { - data_key_handle = MakeDataKey(); - } - - auto& dataKey = getDataKey(data_key_handle); - - dataKey.Buffer[0] = b[0]; - dataKey.Buffer[1] = b[1]; - dataKey.Handle = handle.Get(); - - return data_key_handle; - } - - void UpdateDataKey(const DataKeyHandle data_key_handle) { - auto& dataKey = getDataKey(data_key_handle); - - for (auto& e : dataKey.Nodes) { - SetNodeState(e, static_cast(dataKey.Buffer[0]) && static_cast(dataKey.Buffer[1])); - renderingTree.UpdateNodeKey(e(), dataKeysMap[data_key_handle()].First); - setRenderTreeAsDirty(e); - } - } - - void CopyDataKey(const DataKeyHandle from, const DataKeyHandle to, uint32 offset) { - if(from == to) { BE_LOG_WARNING(u8"Trying to transfer from same data key."); return; } - - { // Scope variables since some will be invalidated after deletion - auto& sourceDataKey = getDataKey(from); - auto& destinationDataKey = getDataKey(to); - - if(sourceDataKey.Buffer[0]) { - BE_LOG_WARNING(u8"Trying to delete data key handle: ", from(), u8", which contains initialized members."); - return; - } - - destinationDataKey.Nodes.PushBack(sourceDataKey.Nodes); // Transfer associated nodes - - sourceDataKey.Offset = offset; - } - - dataKeys.Pop(dataKeysMap[from()].First); // Remove data key entry - dataKeysMap[from()].First = dataKeysMap[to()].First; // Update entry pointer - dataKeysMap[from()].Second = offset; - UpdateDataKey(from); - } - - // ------------ Data Keys ------------ - - void Setup(TaskInfo taskInfo); - void Render(TaskInfo taskInfo, RenderSystem* renderSystem); - - //HACKS, REMOVE - NodeHandle GetGlobalDataLayer() const { return globalData; } - //HACKS, REMOVE - - [[nodiscard]] RenderModelHandle CreateShaderGroup(GTSL::StringView shader_group_instance_name); - - void AddAttachment(GTSL::StringView attachment_name, uint8 bitDepth, uint8 componentCount, GAL::ComponentType compType, GAL::TextureType type, bool is_multiframe); - - NodeHandle AddVertexBufferBind(RenderSystem* render_system, NodeHandle parent_node_handle, RenderSystem::BufferHandle buffer_handle, GTSL::Range*> meshVertexLayout) { - auto nodeHandle = addInternalNode(0, parent_node_handle); - - if(!nodeHandle) { return nodeHandle.Get(); } - - auto& node = getPrivateNode(nodeHandle.Get()); - node.Handle = buffer_handle; node.VertexCount = 0; node.VertexSize = 0; - - { - uint32 offset = 0; - - for (auto& i : meshVertexLayout) { - node.VertexSize += GAL::GraphicsPipeline::GetVertexSize(i); - } - - auto bufferSize = render_system->GetBufferRange(buffer_handle).Bytes(); - - for (auto& i : meshVertexLayout) { - node.Offsets.EmplaceBack(offset); - offset += GAL::GraphicsPipeline::GetVertexSize(i) * (bufferSize / node.VertexSize); - } - } - - - return nodeHandle.Get(); - } - - void AddVertices(const NodeHandle node_handle, uint32 count) { - auto nodeType = renderingTree.GetNodeType(node_handle()); - - setRenderTreeAsDirty(node_handle); - - if(nodeType == RTT::GetTypeIndex()) { - auto& node = getPrivateNode(node_handle); - node.VertexCount += count; - return; - } - - if(nodeType == RTT::GetTypeIndex()) { - auto& node = getPrivateNode(node_handle); - node.VertexCount += count; - return; - } - } - - NodeHandle AddIndexBufferBind(NodeHandle parent_node_handle, RenderSystem::BufferHandle buffer_handle) { - auto nodeHandle = addInternalNode(0, parent_node_handle); - if(!nodeHandle) { return nodeHandle.Get(); } - auto& node = getPrivateNode(nodeHandle.Get()); - node.BufferHandle = buffer_handle; node.IndexCount = 0; node.IndexType = GAL::IndexType::UINT16; - return nodeHandle.Get(); - } - - void AddIndices(const NodeHandle node_handle, uint32 count) { - auto& node = getPrivateNode(node_handle); - node.IndexCount += count; - setRenderTreeAsDirty(node_handle); - } - - void SetBaseInstanceIndex(NodeHandle node_handle, uint32 base_instance_handle) { - getPrivateNode(node_handle).InstanceIndex = base_instance_handle; - setRenderTreeAsDirty(node_handle); - } - - uint32 GetInstanceIndex(const NodeHandle handle, const uint32 instance_handle) { - const auto& node = getPrivateNode(handle); - return node.Instances[instance_handle]; - } - - template - uint32 GetInstanceIndex(const NodeHandle handle, const T& instance_handle) { - const auto& node = getPrivateNode(handle); - return node.Instances[instance_handle()]; - } - - template - void AddInstance(NodeHandle data_node_handle, NodeHandle mesh_node_handle, T handle) { - auto typeIndex = renderingTree.GetNodeType(mesh_node_handle()); - auto& dataNode = getPrivateNode(data_node_handle); - - dataNode.Instances.Emplace(handle(), dataNode.Instance); - - if(typeIndex == RTT::GetTypeIndex()) { - auto& meshNode = getPrivateNode(mesh_node_handle); - meshNode.InstanceIndex = !meshNode.InstanceCount ? dataNode.Instance : meshNode.InstanceIndex; - meshNode.InstanceCount++; - SetNodeState(mesh_node_handle, meshNode.InstanceCount); - } else { - auto& meshNode = getPrivateNode(mesh_node_handle); - meshNode.InstanceCount++; - SetNodeState(mesh_node_handle, meshNode.InstanceCount); - } - - ++dataNode.Instance; - } - - struct BufferWriteKey { - uint32 Offset = 0; - RenderSystem* render_system = nullptr; RenderOrchestrator* render_orchestrator = nullptr; - RenderSystem::BufferHandle buffer_handle; - GTSL::StaticString<256> Path{ u8"global" }; - ElementDataHandle ElementHandle; - - BufferWriteKey() { - - } - - BufferWriteKey(const BufferWriteKey&) = default; - BufferWriteKey(uint32 newOffset, GTSL::StringView path, const ElementDataHandle element_data_handle, const BufferWriteKey& other) : BufferWriteKey(other) { Offset = newOffset; Path = path; ElementHandle = element_data_handle; } - - BufferWriteKey operator[](const uint32 index) { - auto& e = render_orchestrator->getElement(ElementHandle); - - BE_ASSERT(render_orchestrator->getElement(ElementHandle).Type == ElementData::ElementType::MEMBER, u8"Type is not what it should be."); - if(e.Mem.Multiplier == 1) { - render_orchestrator->getLogger()->PrintObjectLog(render_orchestrator, BE::Logger::VerbosityLevel::FATAL, u8"Tried to access ", Path, u8" as array but it isn't."); - return BufferWriteKey{ 0xFFFFFFFF, Path, ElementHandle, *this }; - } - - if(index >= e.Mem.Multiplier) { - render_orchestrator->getLogger()->PrintObjectLog(render_orchestrator, BE::Logger::VerbosityLevel::FATAL, u8"Tried to access index ", index, u8" of ", Path, u8" but array size is ", e.Mem.Multiplier); - return BufferWriteKey{ 0xFFFFFFFF, Path, ElementHandle, *this }; - } - - return BufferWriteKey{ Offset + render_orchestrator->GetSize(ElementHandle, true) * index, Path + u8"." + e.Name, ElementHandle, *this }; - } - - BufferWriteKey operator[](const GTSL::StringView path) { - auto newPath = Path; newPath << u8"." << path; - if(auto r = render_orchestrator->GetRelativeOffset(ElementHandle, path)) { - return BufferWriteKey{ Offset + r.Get().Second, newPath, r.Get().First, *this }; - } else { - render_orchestrator->getLogger()->PrintObjectLog(render_orchestrator, BE::Logger::VerbosityLevel::FATAL, u8"Tried to access ", Path, u8" while writing, which doesn't exist."); - return BufferWriteKey{ 0xFFFFFFFF, Path, ElementHandle, *this }; - } - } - - BufferWriteKey operator()(const ElementDataHandle element_data_handle, const uint32 offset) const { - auto newPath = Path; - return BufferWriteKey{ offset, newPath, element_data_handle, *this }; - } - - template - const BufferWriteKey& operator=(const T& obj) const { - if (Offset == ~0u or !validateType()) { return *this; } - *reinterpret_cast(render_system->GetBufferPointer(buffer_handle) + Offset) = obj; - return *this; - } - - const BufferWriteKey& operator=(const BufferWriteKey& other) const { - if (Offset == ~0u or GTSL::StringView(render_orchestrator->getElement(ElementHandle).DataType) != GTSL::StringView(render_orchestrator->getElement(other.ElementHandle).DataType)) { return *this; } - auto& element = render_orchestrator->getElement(ElementHandle); - GTSL::MemCopy(render_orchestrator->GetSize(element.Mem.TypeHandle), render_system->GetBufferPointer(other.buffer_handle), render_system->GetBufferPointer(buffer_handle) + Offset); - return *this; - } - - const BufferWriteKey& operator=(const RenderSystem::AccelerationStructureHandle acceleration_structure_handle) const { - if (Offset == ~0u or !validateType()) { return *this; } - *reinterpret_cast(render_system->GetBufferPointer(buffer_handle) + Offset) = render_system->GetTopLevelAccelerationStructureAddress(acceleration_structure_handle); - return *this; - } - - const BufferWriteKey& operator=(const RenderSystem::BufferHandle obj) const { - if (Offset == ~0u or !validateType()) { return *this; } - *reinterpret_cast(render_system->GetBufferPointer(buffer_handle) + Offset) = render_system->GetBufferAddress(obj); - return *this; - } - - const BufferWriteKey& operator=(const DataKeyHandle obj) const { - return (*this).operator=(render_orchestrator->dataKeys[obj()].Buffer[1]); // When copying copy destination buffer address - } - - template - bool validateType() const { - auto name = TypeNamer::NAME; - - if(name) { - if(render_orchestrator->getElement(render_orchestrator->getElement(ElementHandle).Mem.TypeHandle).Name == name) { - return true; - } - - render_orchestrator->getLogger()->PrintObjectLog(render_orchestrator, BE::Logger::VerbosityLevel::FATAL, u8"Tried to access ", Path, u8" while writing, but types don't match."); - return false; - } - - return true; - } - }; - - // ------------ Update Keys ------------ - - MAKE_HANDLE(uint32, UpdateKey) - - UpdateKeyHandle CreateUpdateKey() { - auto index = updateKeys.GetLength(); - auto& updateKey = updateKeys.EmplaceBack(); - return UpdateKeyHandle(index); - } - - UpdateKeyHandle GetShaderGroupIndexUpdateKey(RenderModelHandle shader_group_handle) { - return shaderGroupInstances[shader_group_handle()].UpdateKey; - } - - template - void WriteUpdateKey(RenderSystem* render_system, const UpdateKeyHandle update_key_handle, T val) { - auto& updateKey = updateKeys[update_key_handle()]; - - for(auto& e : updateKey.BWKs) { - auto bwk = GetBufferWriteKey(render_system, e.DKH); - bwk(e.EDH, e.Offset) = val; - } - - updateKey.Value = val; - } - - void SubscribeToUpdate(const UpdateKeyHandle update_key_handle, const BufferWriteKey buffer_write_key, const DataKeyHandle data_key_handle) { - auto& updateKey = updateKeys[update_key_handle()]; - updateKey.BWKs.EmplaceBack(GTSL::MoveRef(data_key_handle), GTSL::MoveRef(buffer_write_key.ElementHandle), GTSL::MoveRef(buffer_write_key.Offset)); - buffer_write_key = updateKey.Value; - } - - // ------------ Update Keys ------------ - - GTSL::Delegate shaderGroupNotify; - DataKeyHandle globalDataDataKey, cameraDataKeyHandle; - - void AddNotifyShaderGroupCreated(GTSL::Delegate notify_delegate) { - shaderGroupNotify = notify_delegate; - } - - struct ND - { - GTSL::StringView Name; - DataKeyHandle DKH; - }; - - struct PassData { - struct AttachmentReference { - GTSL::StaticString<64> Name, Attachment; - GAL::AccessType Access; - }; - GTSL::StaticVector Attachments; - - PassTypes type; - }; - NodeHandle AddRenderPassNode(NodeHandle parent_node_handle, GTSL::StringView instance_name, GTSL::StringView render_pass_name, RenderSystem* - renderSystem, PassData pass_data, const GTSL::Range innner = {}); - - void OnResize(RenderSystem* renderSystem, const GTSL::Extent2D newSize); - - /** - * \brief Enables or disables the rendering of a render pass - * \param renderPassName Name of the render Pass to toggle - * \param enable Whether to enable(true) or disable(false) the render pass - */ - void ToggleRenderPass(NodeHandle renderPassName, bool enable); - - MAKE_HANDLE(uint8, IndexStream) MAKE_HANDLE(uint8, DataStream) - - void OnRenderEnable(TaskInfo taskInfo, bool oldFocus); - void OnRenderDisable(TaskInfo taskInfo, bool oldFocus); - - MemberHandle CreateScope(const GTSL::StringView scope, const GTSL::StringView name) { - return tryAddElement(scope, name, ElementData::ElementType::SCOPE).Get(); - } - - MemberHandle RegisterType(GTSL::StringView parents, GTSL::StringView structName, const GTSL::Range members) { - GTSL::StaticVector mem; - - for(auto& e : members) { - mem.EmplaceBack(nullptr, e.Type, e.Name); - } - - return RegisterType(parents, structName, mem); - } - - MemberHandle RegisterType(GTSL::StringView parents, GTSL::StringView structName, const GTSL::Range members) { - auto parseMembers = [&](auto&& self, GTSL::StringView par, GTSL::StringView typeName, GTSL::StringView name, GTSL::Range levelMembers, uint16 level) -> ElementDataHandle { - auto currentScope = GTSL::StaticString<128>(par) << u8"." << typeName; - - auto dataTypeEmplace = tryAddElement(par, typeName, ElementData::ElementType::TYPE); - - if(dataTypeEmplace.State() == 1) { //when element already exists clear data to redeclare element - auto& e = getElement(dataTypeEmplace.Get()); - e.TyEl.Size = 0; - } - - uint32 offset = 0; - - for (uint8 m = 0; m < levelMembers.ElementCount(); ++m) { - auto& member = levelMembers[m]; - - ElementDataHandle handle; - - if (member.MemberInfos.ElementCount()) { - handle = self(self, currentScope, member.Type, member.Name, levelMembers[m].MemberInfos, level + 1); - getElement(handle).TyEl.Alignment = 64; - } - - handle = addMember(currentScope, member.Type, member.Name).Get(); - - if (handle) { - offset = GTSL::Math::RoundUpByPowerOf2(offset, static_cast(member.alignment)); - - if (member.Handle) { - *member.Handle = MemberHandle{ tryGetDataTypeHandle(currentScope, member.Type).Get() }; - } - - offset += GetSize(handle) * 1; - } - } - - return dataTypeEmplace.Get(); - }; - - auto handle = parseMembers(parseMembers, parents, structName, u8"root", members, 0); - return MemberHandle{ handle }; - } - - NodeHandle AddMaterial(NodeHandle parent_node_handle, RenderModelHandle materialHandle) { - auto& shaderGroupInstance = shaderGroupInstances[materialHandle()]; - - if(shaderGroupInstance.Name == u8"BlurH" || shaderGroupInstance.Name == u8"BlurV" || shaderGroupInstance.Name == u8"Barrel" || shaderGroupInstance.Name == u8"Floor") { - auto materialDataNode = AddDataNode(parent_node_handle, shaderGroupInstance.Name, shaderGroupInstance.DataKey); - auto pipelineBindNode = addPipelineBindNode(materialDataNode, materialHandle); - auto& materialNode = getNode(pipelineBindNode); - setNodeName(pipelineBindNode, shaderGroupInstance.Name); - return pipelineBindNode; - } else { - auto pipelineBindNode = addPipelineBindNode(parent_node_handle, materialHandle); - auto& materialNode = getNode(pipelineBindNode); - setNodeName(pipelineBindNode, shaderGroupInstance.Name); - return pipelineBindNode; - } - } - - NodeHandle AddMesh(const NodeHandle parentNodeHandle, uint32 meshId, uint32 indexCount, uint32 indexOffset, uint32 vertexOffset) { - auto nodeHandle = addInternalNode(meshId, parentNodeHandle); - if(!nodeHandle) { return nodeHandle.Get(); } - - getNode(nodeHandle.Get()).Name = GTSL::ShortString<32>(u8"Render Mesh"); - auto& node = getPrivateNode(nodeHandle.Get()); - node.IndexCount = indexCount; - node.IndexOffset = indexOffset; node.VertexOffset = vertexOffset; - return nodeHandle.Get(); - } - - void addPendingWrite(RenderSystem* render_system, RenderSystem::BufferHandle source_buffer_handle, RenderSystem::BufferHandle destination_buffer_handle) { - auto key = uint64(source_buffer_handle()) << 32; - - auto write = pendingWrites.TryEmplace(key); - - write.Get().FrameCountdown[render_system->GetCurrentFrame()] = true; - write.Get().Buffer[0] = source_buffer_handle; - write.Get().Buffer[1] = destination_buffer_handle; - } - - NodeHandle AddDataNode(NodeHandle left_node_handle, NodeHandle parent, const DataKeyHandle data_key_handle) { - auto nodeHandle = addInternalNode(data_key_handle(), left_node_handle, parent); - if(!nodeHandle) { return nodeHandle.Get(); } - - auto& dataNode = getPrivateNode(nodeHandle.Get()); - - auto& dataKey = dataKeys[data_key_handle()]; - dataKey.Nodes.EmplaceBack(nodeHandle.Get()); - UpdateDataKey(data_key_handle); - setNodeName(nodeHandle.Get(), getElement(dataKey.Handle).Name); - dataNode.DataKey = data_key_handle; - dataNode.UseCounter = false; - return nodeHandle.Get(); - } - - [[nodiscard]] NodeHandle AddDataNode(const NodeHandle parent_node_handle, const GTSL::StringView node_name, const DataKeyHandle data_key_handle, bool use_counter = false) { - auto nodeHandle = addInternalNode(data_key_handle(), parent_node_handle); - if(!nodeHandle) { return nodeHandle.Get(); } - - auto& dataNode = getPrivateNode(nodeHandle.Get()); - - auto& dataKey = getDataKey(data_key_handle); - dataKey.Nodes.EmplaceBack(nodeHandle.Get()); - UpdateDataKey(data_key_handle); - setNodeName(nodeHandle.Get(), node_name); - dataNode.DataKey = data_key_handle; - dataNode.UseCounter = use_counter; - return nodeHandle.Get(); - } - - BufferWriteKey GetBufferWriteKey(RenderSystem* render_system, const DataKeyHandle data_key_handle) { - const auto& dataKey = getDataKey(data_key_handle); - BufferWriteKey buffer_write_key; - buffer_write_key.render_system = render_system; - buffer_write_key.render_orchestrator = this; - buffer_write_key.buffer_handle = dataKey.Buffer[0]; - buffer_write_key.ElementHandle = dataKey.Handle; - addPendingWrite(render_system, dataKey.Buffer[0], dataKey.Buffer[1]); - return buffer_write_key; - } - - void WriteBinding(RenderSystem* render_system, SubSetHandle subSetHandle, uint32 bindingIndex, AccelerationStructure accelerationStructure) { - for (uint8 f = 0; f < render_system->GetPipelinedFrames(); ++f) { - descriptorsUpdates[f].AddAccelerationStructureUpdate(subSetHandle, bindingIndex, { accelerationStructure }); - } - } - - void WriteBinding(SubSetHandle subSetHandle, uint32 bindingIndex, AccelerationStructure accelerationStructure, uint8 f) { - descriptorsUpdates[f].AddAccelerationStructureUpdate(subSetHandle, bindingIndex, { accelerationStructure }); - } - - void PushConstant(const RenderSystem* renderSystem, CommandList commandBuffer, SetLayoutHandle layout, uint32 offset, GTSL::Range range) const { - const auto& set = setLayoutDatas[layout()]; - commandBuffer.UpdatePushConstant(renderSystem->GetRenderDevice(), set.pipelineLayout, offset, range, set.Stage); - } - - void BindSet(RenderSystem* renderSystem, CommandList commandBuffer, SetHandle setHandle, GAL::ShaderStage shaderStage) { - auto& set = sets[setHandle()]; - commandBuffer.BindBindingsSets(renderSystem->GetRenderDevice(), shaderStage, GTSL::Range(1, &set.bindingsSet[renderSystem->GetCurrentFrame()]), set.pipelineLayout, set.Level); - } - - void WriteBinding(const RenderSystem* renderSystem, SubSetHandle setHandle, RenderSystem::TextureHandle textureHandle, uint32 bindingIndex, uint8 frameIndex) { - GAL::TextureLayout layout; GAL::BindingType bindingType; - - if (setHandle().Type == GAL::BindingType::STORAGE_IMAGE) { - layout = GAL::TextureLayout::GENERAL; - bindingType = GAL::BindingType::STORAGE_IMAGE; - } - else { - layout = GAL::TextureLayout::SHADER_READ; - bindingType = GAL::BindingType::SAMPLED_IMAGE; - } - - BindingsPool::TextureBindingUpdateInfo info; - info.TextureView = *renderSystem->GetTextureView(textureHandle); - info.Layout = layout; - info.Format; - - descriptorsUpdates[frameIndex].AddTextureUpdate(setHandle, bindingIndex, info); - } - - enum class SubSetTypes : uint8 { - BUFFER, READ_TEXTURES, WRITE_TEXTURES, RENDER_ATTACHMENT, ACCELERATION_STRUCTURE, SAMPLER - }; - - struct SubSetDescriptor { - SubSetTypes type; uint32 BindingsCount; - SubSetHandle* Handle; - GTSL::Range Sampler; - }; - SetLayoutHandle AddSetLayout(RenderSystem* renderSystem, SetLayoutHandle parentName, const GTSL::Range subsets) { - uint64 hash = quickhash64(GTSL::Range(subsets.Bytes(), reinterpret_cast(subsets.begin()))); - - SetLayoutHandle parentHandle; - uint32 level; - - if (parentName) { - auto& parentSetLayout = setLayoutDatas[parentName()]; - parentHandle = parentName; level = parentSetLayout.Level + 1; - } else { - parentHandle = SetLayoutHandle(); level = 0; - } - - auto& setLayoutData = setLayoutDatas.Emplace(hash); - - setLayoutData.Parent = parentHandle; - setLayoutData.Level = level; - - GTSL::StaticVector bindingsSetLayouts; - - // Traverse tree to find parent's pipeline layouts - { - auto lastSet = parentHandle; - - for (uint8 i = 0; i < level; ++i) { bindingsSetLayouts.EmplaceBack(); } - - for (uint8 i = 0, l = level - 1; i < level; ++i, --l) { - bindingsSetLayouts[l] = setLayoutDatas[lastSet()].bindingsSetLayout; - lastSet = setLayoutDatas[lastSet()].Parent; - } - } - - setLayoutData.Stage = GAL::ShaderStages::VERTEX | GAL::ShaderStages::FRAGMENT | GAL::ShaderStages::RAY_GEN | GAL::ShaderStages::CLOSEST_HIT | GAL::ShaderStages::ANY_HIT | GAL::ShaderStages::MISS | GAL::ShaderStages::CALLABLE | GAL::ShaderStages::INTERSECTION | GAL::ShaderStages::COMPUTE; - - GTSL::StaticVector subSetDescriptors; - - for (const auto& e : subsets) { - BindingsSetLayout::BindingDescriptor binding_descriptor; - - if (e.BindingsCount != 1) { binding_descriptor.Flags = GAL::BindingFlags::PARTIALLY_BOUND; } - binding_descriptor.BindingsCount = e.BindingsCount; - - switch (e.type) { - case SubSetTypes::BUFFER: binding_descriptor.Type = GAL::BindingType::STORAGE_BUFFER; break; - case SubSetTypes::READ_TEXTURES: binding_descriptor.Type = GAL::BindingType::SAMPLED_IMAGE; break; - case SubSetTypes::WRITE_TEXTURES: binding_descriptor.Type = GAL::BindingType::STORAGE_IMAGE; break; - case SubSetTypes::RENDER_ATTACHMENT: binding_descriptor.Type = GAL::BindingType::INPUT_ATTACHMENT; break; - case SubSetTypes::SAMPLER: { - binding_descriptor.Type = GAL::BindingType::SAMPLER; - binding_descriptor.Samplers = e.Sampler; - binding_descriptor.BindingsCount = e.Sampler.ElementCount(); - break; - } - case SubSetTypes::ACCELERATION_STRUCTURE: - binding_descriptor.Type = GAL::BindingType::ACCELERATION_STRUCTURE; - binding_descriptor.Stage = GAL::ShaderStages::RAY_GEN; - break; - } - - binding_descriptor.Stage = setLayoutData.Stage; - - subSetDescriptors.EmplaceBack(binding_descriptor); - } - - setLayoutData.bindingsSetLayout.Initialize(renderSystem->GetRenderDevice(), subSetDescriptors); - bindingsSetLayouts.EmplaceBack(setLayoutData.bindingsSetLayout); - - GAL::PushConstant pushConstant; - pushConstant.Stage = setLayoutData.Stage; - pushConstant.NumberOf4ByteSlots = 32; - setLayoutData.pipelineLayout.Initialize(renderSystem->GetRenderDevice(), &pushConstant, bindingsSetLayouts); - - return SetLayoutHandle(hash); - } - - SetHandle AddSet(RenderSystem* renderSystem, GTSL::StringView setName, SetLayoutHandle setLayoutHandle, const GTSL::Range setInfo) { - GTSL::StaticVector bindingDescriptors; - - for (auto& ss : setInfo) { - GAL::ShaderStage enabledShaderStages = GAL::ShaderStages::VERTEX | GAL::ShaderStages::FRAGMENT | GAL::ShaderStages::RAY_GEN | GAL::ShaderStages::CLOSEST_HIT | GAL::ShaderStages::ANY_HIT | GAL::ShaderStages::MISS | GAL::ShaderStages::CALLABLE | GAL::ShaderStages::INTERSECTION | GAL::ShaderStages::COMPUTE; - - switch (ss.type) { - case SubSetTypes::BUFFER: - bindingDescriptors.EmplaceBack(GAL::BindingType::STORAGE_BUFFER, enabledShaderStages, ss.BindingsCount, GAL::BindingFlags::PARTIALLY_BOUND); - break; - case SubSetTypes::READ_TEXTURES: - bindingDescriptors.EmplaceBack(GAL::BindingType::SAMPLED_IMAGE, enabledShaderStages, ss.BindingsCount, GAL::BindingFlags::PARTIALLY_BOUND); - break; - case SubSetTypes::WRITE_TEXTURES: - bindingDescriptors.EmplaceBack(GAL::BindingType::STORAGE_IMAGE, enabledShaderStages, ss.BindingsCount, GAL::BindingFlags::PARTIALLY_BOUND); - break; - case SubSetTypes::RENDER_ATTACHMENT: - bindingDescriptors.EmplaceBack(GAL::BindingType::INPUT_ATTACHMENT, enabledShaderStages, ss.BindingsCount, GAL::BindingFlags::PARTIALLY_BOUND); - break; - case SubSetTypes::ACCELERATION_STRUCTURE: - bindingDescriptors.EmplaceBack(GAL::BindingType::ACCELERATION_STRUCTURE, enabledShaderStages, ss.BindingsCount, GAL::BindingFlag()); - break; - case SubSetTypes::SAMPLER: - bindingDescriptors.EmplaceBack(GAL::BindingType::SAMPLER, enabledShaderStages, ss.BindingsCount, GAL::BindingFlag()); - break; - default:; - } - } - - auto setHandle = makeSetEx(renderSystem, Id(setName), setLayoutHandle, bindingDescriptors); - - auto& set = sets[setHandle()]; - uint32 i = 0; - for (auto& ss : setInfo) { - *ss.Handle = SubSetHandle({ setHandle, i, bindingDescriptors[i].Type }); - ++i; - } - - return setHandle; - } - - struct BindingsSetData { - BindingsSetLayout Layout; - BindingsSet BindingsSets[MAX_CONCURRENT_FRAMES]; - uint32 DataSize = 0; - }; - - // Evaluates a node's state variables and sets it's enable state accordingly - // Used to enable a node only if dependencies have been fulfilled - void revalNode(const NodeHandle node_handle) { - auto& node = getNode(node_handle); - const bool fulfilled = node.References >= node.L; - const bool nodeState = node.Enabled && fulfilled; - if(nodeState != renderingTree.GetNodeState(node_handle())) { - renderingTree.ToggleBranch(node_handle(), nodeState); - setRenderTreeAsDirty(node_handle); - } - - if(BE::Application::Get()->GetConfig()[u8"RenderOrchestrator"][u8"debugResourceFulfillment"].GetBool()) { - if(nodeState) { - BE_LOG_MESSAGE(u8"Node: ", node.Name, u8", was enabled."); - } else { - BE_LOG_MESSAGE(u8"Node: ", node.Name, u8", was disabled."); - } - } - } - - void AddNodeDependency(const NodeHandle node_handle) { - auto& node = getNode(node_handle); - ++node.L; - revalNode(node_handle); - } - - void FulfillNodeDependency(const NodeHandle node_handle) { - auto& node = getNode(node_handle); - ++node.References; - revalNode(node_handle); - } - - void SetNodeState(const NodeHandle node_handle, const bool state) { - auto& node = getNode(node_handle); - node.Enabled = state; - revalNode(node_handle); - } - - void PrintMember(const DataKeyHandle data_key_handle, RenderSystem* render_system) const { - byte* beginPointer; - - GTSL::SemiString string(u8"\n", GetTransientAllocator()); //start struct on new line, looks better when printed - - const auto& dataKey = getDataKey(data_key_handle); - const uint32 startOffset = dataKey.Offset; - - auto walkTree = [&](const ElementDataHandle member_handle, uint32 level, uint32 offset, auto&& self) -> uint32 { - auto& e = elements[member_handle()]; - auto& dt = getElement(e.Mem.TypeHandle); - - GTSL::StaticString<128> dtt; - - for (uint32 t = 0; t < e.Mem.Multiplier && t < 4; ++t) { // Clamp printed array elements to 16 - string += u8"\n"; - - for (uint32 i = 0; i < level; ++i) { string += U' '; } //insert tab for every space deep we are to show struct depth - - dtt = e.DataType; - - string += u8"offset: "; ToString(string, offset - startOffset); string += u8", "; string += dt.DataType; string += u8" "; - if(e.Mem.Multiplier > 1) { - string += '['; GTSL::ToString(string, t); string += u8"] "; - dtt = dt.Name; - } - string += e.Name; string += u8": "; - - - if (FindLast(dt.DataType, U'*')) { - GTSL::ToString(string, reinterpret_cast(beginPointer + offset)[0]); - } - else { - switch (GTSL::Hash(dtt)) { - case GTSL::Hash(u8"ptr_t"): { - GTSL::ToString(string, reinterpret_cast(beginPointer + offset)[0]); - break; - } - case GTSL::Hash(u8"uint32"): { - GTSL::ToString(string, reinterpret_cast(beginPointer + offset)[0]); - break; - } - case GTSL::Hash(u8"uint64"): { - GTSL::ToString(string, reinterpret_cast(beginPointer + offset)[0]); - break; - } - case GTSL::Hash(u8"float32"): { - GTSL::ToString(string, reinterpret_cast(beginPointer + offset)[0]); - break; - } - case GTSL::Hash(u8"TextureReference"): { - auto textureHandle = reinterpret_cast(beginPointer + offset)[0]; - - GTSL::ToString(string, textureHandle); string += u8", "; - break; - } - case GTSL::Hash(u8"ImageReference"): { - GTSL::ToString(string, reinterpret_cast(beginPointer + offset)[0]); - break; - } - case GTSL::Hash(u8"vec2f"): { - auto pointer = reinterpret_cast(beginPointer + offset)[0]; - GTSL::ToString(string, pointer.X()); string += u8", "; - GTSL::ToString(string, pointer.Y()); - break; - } - case GTSL::Hash(u8"vec2u"): { - auto pointer = reinterpret_cast(beginPointer + offset); - GTSL::ToString(string, pointer[0]); string += u8", "; - GTSL::ToString(string, pointer[1]); - break; - } - case GTSL::Hash(u8"vec3f"): { - auto pointer = reinterpret_cast(beginPointer + offset)[0]; - GTSL::ToString(string, pointer.X()); string += u8", "; - GTSL::ToString(string, pointer.Y()); string += u8", "; - GTSL::ToString(string, pointer.Z()); - break; - } - case GTSL::Hash(u8"vec4f"): { - auto pointer = reinterpret_cast(beginPointer + offset)[0]; - GTSL::ToString(string, pointer.X()); - GTSL::ToString(string, pointer.Y()); - GTSL::ToString(string, pointer.Z()); - GTSL::ToString(string, pointer.W()); - break; - } - case GTSL::Hash(u8"matrix3x4f"): { - auto matrixPointer = reinterpret_cast(beginPointer + offset)[0]; - - for (uint8 r = 0; r < 3; ++r) { - for (uint32 i = 0; i < level && r; ++i) { string += U' '; } //insert tab for every space deep we are to show struct depth - - for (uint8 c = 0; c < 4; ++c) { - GTSL::ToString(string, matrixPointer[r][c]); string += u8" "; - } - - string += U'\n'; - } - - break; - } - case GTSL::Hash(u8"matrix4f"): { - auto matrixPointer = reinterpret_cast(beginPointer + offset)[0]; - - for (uint8 r = 0; r < 4; ++r) { - for (uint32 i = 0; i < level && r; ++i) { string += U' '; } //insert tab for every space deep we are to show struct depth - - for (uint8 c = 0; c < 4; ++c) { - GTSL::ToString(string, matrixPointer[r][c]); string += u8" "; - } - - string += U'\n'; - } - - break; - } - case GTSL::Hash(u8"ShaderHandle"): { - - for (uint32 i = 0; i < 4; ++i) { - uint64 val = reinterpret_cast(beginPointer + offset)[i]; - if (i) { string << u8"-"; } ToString(string, val); - } - - uint64 shaderHandleHash = quickhash64({ 32, reinterpret_cast(beginPointer + offset) }); - - if (auto r = shaderHandlesDebugMap.TryGet(shaderHandleHash)) { - string << u8", handle for shader: "; - GTSL::ToString(string, r.Get()); - } - else { - string << u8", shader handle not found."; - } - - break; - } - } - } - - uint32 size = 0; - - for (auto& e : dt.children) { - if (getElement(e.Handle).Type == ElementData::ElementType::MEMBER) { - size = GTSL::Math::RoundUpByPowerOf2(size, getElement(getElement(ElementDataHandle(e.Handle)).Mem.TypeHandle).TyEl.Alignment); - size += self(e.Handle, level + 1, offset + size, self); - } - } - - offset += dt.TyEl.Size; - - BE_ASSERT(dt.Type == ElementData::ElementType::TYPE, u8"Type is not what it should be."); - } - - return dt.TyEl.Size * e.Mem.Multiplier; //todo: align - }; - - beginPointer = render_system->GetBufferPointer(dataKey.Buffer[0]); - string += u8"\nAddress: "; GTSL::ToString(string, static_cast(render_system->GetBufferAddress(dataKey.Buffer[0]))); - string += u8"\n"; - walkTree(ElementDataHandle(dataKey.Handle), 0, startOffset, walkTree); - - BE_LOG_MESSAGE(string); - } - - NodeHandle AddSquare(const NodeHandle parent_node_handle) { - auto nodeHandle = addInternalNode(0, parent_node_handle); - if(!nodeHandle) { return nodeHandle.Get(); } - setNodeName(nodeHandle.Get(), u8"Square"); - getPrivateNode(nodeHandle.Get()).VertexCount = 6; - SetNodeState(nodeHandle.Get(), false); - return nodeHandle.Get(); - } - - NodeHandle AddRayTraceNode(const NodeHandle parent_node_handle, const RenderModelHandle material_instance_handle) { - auto handle = addInternalNode(222, parent_node_handle); - if(!handle) { return handle.Get(); } - getPrivateNode(handle.Get()).ShaderGroupIndex = material_instance_handle(); - return handle.Get(); - } - -private: - inline static const auto RENDER_TASK_NAME{ u8"RenderOrchestrator::Render" }; - inline static const auto SETUP_TASK_NAME{ u8"RenderOrchestrator::Setup" }; - inline static const auto CLASS_NAME{ u8"RenderOrchestrator" }; - - inline static constexpr uint32 RENDER_DATA_BUFFER_SIZE = 262144; - inline static constexpr uint32 RENDER_DATA_BUFFER_SLACK_SIZE = 4096; - inline static constexpr uint32 RENDER_DATA_BUFFER_PAGE_SIZE = RENDER_DATA_BUFFER_SIZE + RENDER_DATA_BUFFER_SLACK_SIZE; - - void onRenderEnable(ApplicationManager* gameInstance, const GTSL::Range dependencies); - void onRenderDisable(ApplicationManager* gameInstance); - - bool renderingEnabled = false; - - uint32 renderDataOffset = 0; - SetLayoutHandle globalSetLayout; - SetHandle globalBindingsSet; - NodeHandle rayTraceNode; - - MemberHandle cameraMatricesHandle; - MemberHandle globalDataHandle; - SubSetHandle textureSubsetsHandle; - SubSetHandle imagesSubsetHandle; - SubSetHandle samplersSubsetHandle; - - RenderSystem::CommandListHandle graphicsCommandLists[MAX_CONCURRENT_FRAMES]; - RenderSystem::CommandListHandle buildCommandList[MAX_CONCURRENT_FRAMES], transferCommandList[MAX_CONCURRENT_FRAMES]; - - RenderSystem::WorkloadHandle graphicsWorkloadHandle[MAX_CONCURRENT_FRAMES], buildAccelerationStructuresWorkloadHandle[MAX_CONCURRENT_FRAMES]; - - GTSL::HashMap rayTracingSets; - - GTSL::StaticVector, 8>, 16> vertexLayouts; - - GTSL::HashMap, BE::PAR> shaderHandlesDebugMap; - - struct RenderState { - GAL::ShaderStage ShaderStages; - uint8 streamsCount = 0, buffersCount = 0; - - uint32 BoundPipelineIndex, BoundShaderGroupIndex; - - DataKeyHandle dataKeys[128 / 8]; - - DataStreamHandle AddDataStream(const DataKeyHandle data_key_handle) { - dataKeys[buffersCount] = data_key_handle; - ++buffersCount; - return DataStreamHandle(streamsCount++); - } - - void PopData() { - --streamsCount; --buffersCount; - } - }; - - struct ShaderData { - GAL::VulkanShader Shader; - GAL::ShaderType Type; - GTSL::StaticString<64> Name; - }; - GTSL::HashMap shaders; - - struct MeshData { - uint32 InstanceCount = 0; - uint32_t IndexCount, IndexOffset, VertexOffset, InstanceIndex; - }; - - struct DispatchData { - GTSL::Extent3D DispatchSize; - }; - - struct PipelineBindData { - RenderModelHandle Handle; - }; - - struct RayTraceData { - uint32 ShaderGroupIndex = 0xFFFFFFFF; - }; - - struct RenderPassData { - PassTypes Type; - GTSL::StaticVector Attachments; - GAL::PipelineStage PipelineStages; - MemberHandle RenderTargetReferences; - ResourceHandle resourceHandle; - DataKeyHandle DataKey; - }; - - struct DataNode { - DataKeyHandle DataKey; - bool UseCounter; - uint32 Instance = 0; - GTSL::HashMap Instances; - }; - - struct PublicNode { - GTSL::ShortString<32> Name; - NodeType Type; uint8 Level = 0; - uint32 InstanceCount = 0; - uint32 References = 0, L = 0; - bool Enabled = true; - }; - - //Node's names are nnot provided inn the CreateNode functions since we don't want to generate debug names in release builds, and the compiler won't eliminate the useless string generation code - //if it were provided in the less easy to see through CreateNode functions - void setNodeName(const NodeHandle internal_node_handle, const GTSL::StringView name) { - if constexpr (BE_DEBUG) { getNode(internal_node_handle).Name = name; } - } - - [[nodiscard]] NodeHandle addNode(const GTSL::StringView nodeName, const NodeHandle parent, const NodeType layerType) { - auto l = addNode(nodeName, parent, layerType); - auto& t = getNode(l); - t.Name = nodeName; - return l; - } - - PublicNode& getNode(const NodeHandle nodeHandle) { - return renderingTree.GetAlpha(nodeHandle()); - } - - template - T& getPrivateNode(const NodeHandle internal_node_handle) { - return renderingTree.GetClass(internal_node_handle()); - } - - NodeHandle globalData; - - void transitionImages(CommandList commandBuffer, RenderSystem* renderSystem, const RenderPassData* internal_layer); - - struct ShaderLoadInfo { - ShaderLoadInfo() = default; - ShaderLoadInfo(const BE::PAR& allocator) noexcept : Buffer(allocator), MaterialIndex(0) {} - ShaderLoadInfo(ShaderLoadInfo&& other) noexcept : Buffer(MoveRef(other.Buffer)), MaterialIndex(other.MaterialIndex), handle(other.handle) {} - GTSL::Buffer Buffer; uint32 MaterialIndex; - NodeHandle handle; - }; - - uint64 resourceCounter = 0; - - ResourceHandle makeResource(const GTSL::StringView resource_name) { - auto& resource = resources.Emplace(++resourceCounter); - resource.Name = resource_name; - return ResourceHandle(resourceCounter); - } - - void BindResourceToNode(NodeHandle node_handle, ResourceHandle resource_handle) { - if (!resources.Find(resource_handle())) { BE_LOG_ERROR(u8"Invalid resource handle: ", resource_handle()); return; } - - auto& resource = resources[resource_handle()]; - - resource.NodeHandles.EmplaceBack(node_handle); - - SetNodeState(node_handle, resource.isValid()); - } - - void addDependencyOnResource(const ResourceHandle resourceHandle) { - if (!resources.Find(resourceHandle())) { BE_LOG_ERROR(u8"Invalid resource handle: ", resourceHandle()); return; } - ++resources[resourceHandle()].Target; - } - - void addDependencyOnResource(const ResourceHandle waiterHandle, const ResourceHandle providerHandle) { - if (!resources.Find(waiterHandle())) { BE_LOG_ERROR(u8"Invalid resource handle: ", waiterHandle()); return; } - - auto& provider = resources[providerHandle()]; auto& waiter = resources[waiterHandle()]; - - provider.Children.EmplaceBack(waiterHandle); - - ++waiter.Target; - - bool enableValue = waiter.isValid(); - - for (auto e : waiter.NodeHandles) { - SetNodeState(e, enableValue); - } - } - - void signalDependencyToResource(ResourceHandle resource_handle) { - if (resources.Find(resource_handle())) { - tryEnableResource(resource_handle); - } - else { - BE_LOG_WARNING(u8"Tried to enable resource: ", resource_handle(), u8" which is not available."); - } - } - - void tryEnableResource(ResourceHandle resource_handle) { - auto& resource = resources[resource_handle()]; - ++resource.Count; - if (resource.isValid()) { - for (auto e : resource.Children) { - tryEnableResource(e); - } - - for (const auto& e : resource.NodeHandles) { - SetNodeState(e, true); - } - } - } - - struct ResourceData { - GTSL::ShortString<32> Name; - GTSL::StaticVector NodeHandles; - uint32 Count = 0, Target = 0; - GTSL::StaticVector Children; - - bool isValid() const { return Count >= Target; } - }; - GTSL::HashMap resources; - - // ------------ Data Keys ------------ - - struct DataKeyData { - uint32 Offset = 0; - RenderSystem::BufferHandle Buffer[2]; - GTSL::StaticVector Nodes; - ElementDataHandle Handle; - }; - GTSL::FixedVector dataKeys; - GTSL::Vector, BE::PAR> dataKeysMap; - - DataKeyData& getDataKey(const DataKeyHandle data_key_handle) { - return dataKeys[dataKeysMap[data_key_handle()].First]; - } - - const DataKeyData& getDataKey(const DataKeyHandle data_key_handle) const { - return dataKeys[dataKeysMap[data_key_handle()].First]; - } - - // ------------ Data Keys ------------ - - void onShaderInfosLoaded(TaskInfo taskInfo, ShaderResourceManager*, ShaderResourceManager::ShaderGroupInfo shaderInfos, ShaderLoadInfo shaderLoadInfo); - - void onShadersLoaded(TaskInfo taskInfo, ShaderResourceManager*, RenderSystem*, ShaderResourceManager::ShaderGroupInfo, GTSL::Range buffer, ShaderLoadInfo shaderLoadInfo); - - struct DrawData { - uint32 VertexCount = 0, InstanceCount = 0; - }; - - struct VertexBufferBindData { - uint32 VertexCount = 0, VertexSize = 0; - RenderSystem::BufferHandle Handle; - GTSL::StaticVector Offsets; - }; - - struct IndexBufferBindData { - uint32 IndexCount = 0; - GAL::IndexType IndexType; - RenderSystem::BufferHandle BufferHandle; - }; - - struct IndirectComputeDispatchData { - - }; - - GTSL::MultiTree renderingTree; - using RTT = decltype(renderingTree); - - bool isCommandBufferUpdated[MAX_CONCURRENT_FRAMES]{ false }; - bool isRenderTreeDirty = false; - - void setRenderTreeAsDirty(const NodeHandle dirty_node_handle) { isRenderTreeDirty = true; } - - template - GTSL::Result addInternalNode(const uint64 key, NodeHandle publicParentHandle) { - auto betaNodeHandle = renderingTree.Emplace(key, 0xFFFFFFFF, publicParentHandle()); - setRenderTreeAsDirty(publicParentHandle); - return { NodeHandle(betaNodeHandle.Get()), betaNodeHandle.State() }; - } - - template - GTSL::Result addInternalNode(const uint64 key, NodeHandle leftNodeHandle, NodeHandle publicParentHandle) { - auto betaNodeHandle = renderingTree.Emplace(key, leftNodeHandle(), publicParentHandle()); - setRenderTreeAsDirty(publicParentHandle); - return { NodeHandle(betaNodeHandle.Get()), betaNodeHandle.State() }; - } - - NodeHandle addPipelineBindNode(const NodeHandle parent_node_handle, const RenderModelHandle material_instance_handle) { - auto handle = addInternalNode(555, parent_node_handle); - - if(!handle) { return handle.Get(); } - - getPrivateNode(handle.Get()).Handle = material_instance_handle; - BindResourceToNode(handle.Get(), shaderGroupInstances[material_instance_handle()].Resource); - return handle.Get(); - } - - static auto parseScopeString(const GTSL::StringView parents) { - GTSL::StaticVector, 8> strings; - - { - uint32 i = 0; - - while (i < parents.GetCodepoints()) { - auto& string = strings.EmplaceBack(); - - while (parents[i] != U'.' and i < parents.GetCodepoints()) { - string += parents[i]; - ++i; - } - - ++i; - } - } - - return strings; - } - - GTSL::HashMap renderPassesMap; - GTSL::StaticVector renderPasses; - - struct Pipeline { - Pipeline(const BE::PAR& allocator) {} - - GPUPipeline pipeline; - //ResourceHandle ResourceHandle; - DataKeyHandle ShaderBindingTableBuffer; - - GTSL::StaticVector Shaders; - - struct RayTracingData { - struct ShaderGroupData { - MemberHandle TableHandle; - - struct InstanceData { - MemberHandle ShaderHandle; - GTSL::StaticVector Elements; - }; - - uint32 ShaderCount = 0; - - GTSL::StaticVector Instances; - } ShaderGroups[4]; - - uint32 PipelineIndex; - } RayTracingData; - - GTSL::StaticString<64> ExecutionString; - }; - GTSL::FixedVector pipelines; - - struct ShaderGroupData { - GTSL::StaticString<64> Name; - DataKeyHandle Buffer; - GTSL::StaticMap ParametersHandles; - GTSL::StaticVector Parameters; - bool Loaded = false; - uint32 RasterPipelineIndex = 0xFFFFFFFF, ComputePipelineIndex = 0xFFFFFFFF, RTPipelineIndex = 0xFFFFFFFF; - ResourceHandle Resource; - GTSL::StaticVector PushConstantLayout; - }; - GTSL::FixedVector shaderGroups; - - struct ShaderGroupInstanceData { - GTSL::StaticString<64> Name; - ResourceHandle Resource; - uint32 ShaderGroupIndex = 0; - DataKeyHandle DataKey; - UpdateKeyHandle UpdateKey; - }; - GTSL::StaticVector shaderGroupInstances; - - GTSL::HashMap shaderGroupsByName, shaderGroupInstanceByName; - - uint32 textureIndex = 0, imageIndex = 0; - - void printNode(const uint32 nodeHandle, uint32 level, bool d, bool e) { - if (!d) { return; } - - GTSL::StaticString<256> message; - - message += u8"Node: "; GTSL::ToString(message, nodeHandle); message += u8", Depth: ", GTSL::ToString(message, level); message += u8", Type: "; - - switch (renderingTree.GetNodeType(nodeHandle)) { - case decltype(renderingTree)::GetTypeIndex(): { message += u8"DataNode"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"PipelineBind"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"MeshDraw"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"VertexBufferBind"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"IndexBufferBind"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"RenderPass"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"Draw"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"Dispatch"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"Raytrace"; break; } - case decltype(renderingTree)::GetTypeIndex(): { message += u8"Compute Dispatch"; break; } - default: { message += u8"null"; break; } - } - - message += u8", Name: "; message += getNode(nodeHandle).Name; - - if(e) { - BE_LOG_MESSAGE(message) - } else { - message += u8", Unfulfilled dependencies: "; - - GTSL::StaticVector, 16> deps; - - for(auto& e : resources) { - if(e.NodeHandles.Find(NodeHandle(nodeHandle))) { - if (!e.isValid()) { //todo: recurse - deps.EmplaceBack(e.Name); - } - } - } - - ToString(message, deps); - - BE_LOG_WARNING(message) - } - } - - struct CreateTextureInfo { - GTSL::ShortString<64> TextureName; - ApplicationManager* applicationManager = nullptr; - RenderSystem* renderSystem = nullptr; - TextureResourceManager* textureResourceManager = nullptr; - }; - uint32 createTexture(const CreateTextureInfo& createTextureInfo); - - struct MaterialLoadInfo { - MaterialLoadInfo(RenderSystem* renderSystem, GTSL::Buffer&& buffer, uint32 index, uint32 instanceIndex, TextureResourceManager* tRM) : renderSystem(renderSystem), Buffer(MoveRef(buffer)), Component(index), InstanceIndex(instanceIndex), textureResourceManager(tRM) - { - } - - RenderSystem* renderSystem = nullptr; - GTSL::Buffer Buffer; - uint32 Component, InstanceIndex; - TextureResourceManager* textureResourceManager; - }; - - struct TextureLoadInfo { - TextureLoadInfo() = default; - - TextureLoadInfo(RenderAllocation renderAllocation) : allocation(renderAllocation) - {} - - RenderAllocation allocation; - RenderSystem::TextureHandle TextureHandle; - }; - void onTextureInfoLoad(TaskInfo taskInfo, TextureResourceManager* resourceManager, RenderSystem*, TextureResourceManager::TextureInfo textureInfo, TextureLoadInfo loadInfo); - void onTextureLoad(TaskInfo taskInfo, TextureResourceManager* resourceManager, RenderSystem*, TextureResourceManager::TextureInfo textureInfo, TextureLoadInfo loadInfo); - - struct TextureData { - ResourceHandle Resource; - uint32 Index = 0; - }; - GTSL::HashMap textures; - - void addPendingResourceToTexture(GTSL::StringView texture, ResourceHandle resource) { - addDependencyOnResource(resource, textures[texture].Resource); - } - - struct Attachment { - RenderSystem::TextureHandle TextureHandle[MAX_CONCURRENT_FRAMES]; - - GTSL::StaticString<64> Name; - GAL::TextureUse Uses; GAL::TextureLayout Layout[MAX_CONCURRENT_FRAMES]; - GAL::PipelineStage ConsumingStages; GAL::AccessType AccessType; - GTSL::RGBA ClearColor; GAL::FormatDescriptor format; - uint32 ImageIndeces[MAX_CONCURRENT_FRAMES]; - //bool IsMultiFrame = false; - }; - GTSL::HashMap attachments; - - void updateImage(uint8 frameIndex, Attachment& attachment, GAL::TextureLayout textureLayout, GAL::PipelineStage stages, GAL::AccessType writeAccess) { - attachment.Layout[frameIndex] = textureLayout; attachment.ConsumingStages = stages; attachment.AccessType = writeAccess; - } - - TaskHandle onTextureInfoLoadHandle; - TaskHandle onTextureLoadHandle; - TaskHandle onShaderInfosLoadHandle; - TaskHandle, ShaderLoadInfo> onShaderGroupLoadHandle; - - struct ElementData { - ElementData(const BE::PAR& allocator) : children() {} - - enum class ElementType { - NONE, SCOPE, TYPE, MEMBER - } Type = ElementType::NONE; - - GTSL::StaticString<64> DataType, Name; - - struct Member { - ElementDataHandle TypeHandle; - uint32 Alignment = 1; - uint32 Multiplier; - } Mem; - - struct TypeElement { - uint32 Size = 0, Alignment = 1; - } TyEl; - - struct Entry { - GTSL::StaticString<64> Name; - ElementDataHandle Handle; - }; - GTSL::StaticVector children; - }; - GTSL::Tree elements; - - void addScope(const GTSL::StringView scope, const GTSL::StringView name) { - tryAddElement(scope, name, ElementData::ElementType::SCOPE); - } - - GTSL::Result addMember(const GTSL::StringView scope, const GTSL::StringView type, const GTSL::StringView name) { - auto parents = parseScopeString(scope); - - ElementDataHandle parentHandle, typeHandle; - - auto typeString = GTSL::StaticString<128>(type); - uint32 multiplier = 1; - - if (auto pos = FindFirst(typeString, u8'[')) { - uint32 i = pos.Get(); - - while(i < typeString.GetCodepoints()) { - while(i < typeString.GetCodepoints() && typeString[i++] != u8'[') {} - - uint32 start = i; - - while(i < typeString.GetCodepoints() && typeString[i++] != u8']') {} - - uint32 end = i - 1; - - multiplier *= GTSL::ToNumber({ end - start, end - start, typeString.c_str() + start }).Get(); - } - - typeString.Drop(pos.Get()); - } - - if(auto r = tryGetDataTypeHandle(scope, typeString)) { - typeHandle = r.Get(); - } else { - BE_LOG_WARNING(u8"Failed to create member."); - return { ElementDataHandle(), false }; - } - - { - BE_ASSERT(getElement(typeHandle).Type == ElementData::ElementType::TYPE, u8""); - - auto elementResult = tryAddElement(scope, name, ElementData::ElementType::MEMBER); - auto& element = getElement(elementResult.Get()); - element.Mem.TypeHandle = typeHandle; - element.Mem.Alignment = getElement(typeHandle).TyEl.Alignment; - element.Mem.Multiplier = multiplier; - element.DataType = type; - - for (uint32 i = 1, j = parents.GetLength() - 1; i < parents; ++i, --j) { - auto& t = tryGetDataTypeHandle(scope, parents[j]).Get(); - auto& ttt = getElement(t); - if (ttt.Type != ElementData::ElementType::TYPE) { break; } - //BE_LOG_MESSAGE(u8"Pre size: ", ttt.TyEl.Size, u8", handle: ", t(), u8", name: ", ttt.Name); - ttt.TyEl.Size = GTSL::Math::RoundUpByPowerOf2(ttt.TyEl.Size, getElement(typeHandle).TyEl.Alignment); - ttt.TyEl.Size += getElement(typeHandle).TyEl.Size * multiplier; - //BE_LOG_MESSAGE(u8"Post size: ", ttt.TyEl.Size, u8", handle: ", t(), u8", name: ", ttt.Name); - } - - return { (ElementDataHandle&&)elementResult.Get(), true }; - } - - } - - //will return the handle to name element under parents scope - GTSL::Result tryGetDataTypeHandle(GTSL::Range parents, GTSL::StringView name) { - if (*(name.end() - 1) == U'*') { - return tryGetDataTypeHandle(u8"global", u8"ptr_t"); - } - - ElementDataHandle handle{ 1 }; - - for (auto& e : parents) { - if (e == u8"global") { - handle = ElementDataHandle(1); - } else { - if (auto r = GTSL::Find(elements[handle()].children, [&](const ElementData::Entry& entry) { return entry.Name == e; })) { - handle = ElementDataHandle(r.Get()->Handle); - } else { - break; - } - } - - if (auto r = GTSL::Find(elements[handle()].children, [&](const ElementData::Entry& entry) { return name == entry.Name; })) { - return { ElementDataHandle(r.Get()->Handle), true }; - } - } - - return { ElementDataHandle(), false }; - } - - GTSL::Result tryGetDataTypeHandle(GTSL::StringView scope) { - auto scopes = parseScopeString(scope); - - ElementDataHandle handle{ 1 }; - - for (uint32 i = 0; i < scopes.GetLength(); ++i) { - if (scopes[i] == u8"global") { - handle = ElementDataHandle(1); - } else { - if (auto r = GTSL::Find(elements[handle()].children, [&](const ElementData::Entry& entry) { return scopes[i] == entry.Name; })) { - handle = r.Get()->Handle; - } else { - return { ElementDataHandle(), false }; - } - } - } - - return { ElementDataHandle(handle), true }; - } - - GTSL::Result tryGetDataTypeHandle(GTSL::StringView parents, GTSL::StringView name) { - GTSL::StaticVector pppp; - - auto t = parseScopeString(parents); - - for (auto& e : t) { - pppp.EmplaceBack(e); - } - - return tryGetDataTypeHandle(pppp, name); - } - - GTSL::Result tryGetDataTypeHandle(ElementDataHandle parent, GTSL::StringView name) { - if (*(name.end() - 1) == U'*') { - return tryGetDataTypeHandle(u8"global", u8"ptr_t"); - } - - if (auto r = GTSL::Find(getElement(parent).children, [&](const ElementData::Entry& entry) { return name == entry.Name; })) { - return { ElementDataHandle(r.Get()->Handle), true }; - } - - return { ElementDataHandle(), false }; - } - - //will declare data type name under parents - //2 result if added - //1 result if exists - //0 result if failed - GTSL::Result tryAddElement(const GTSL::StringView parents, const GTSL::StringView name, ElementData::ElementType type) { - auto parentList = parseScopeString(parents); //parse parent list and make array - - ElementDataHandle parentHandle; - - if(auto r = tryGetDataTypeHandle(parents)) { - parentHandle = r.Get(); - } else { - return { ElementDataHandle(), 0 }; - } - - auto entry = tryEmplaceChild(name, parentHandle); - - if (!entry) { - return { ElementDataHandle(entry.Get()), 1 }; - } - - auto& child = elements[entry.Get()()]; - child.Name = name; - child.Type = type; - return { ElementDataHandle(entry.Get()), 2 }; - } - - ElementData& getElement(const ElementDataHandle element_data_handle) { - return elements[element_data_handle()]; - } - - const ElementData& getElement(const ElementDataHandle element_data_handle) const { - return elements[element_data_handle()]; - } - - GTSL::Result tryAddDataType(const GTSL::StringView parents, const GTSL::StringView name, uint32 size) { - if (auto r = tryAddElement(parents, name, ElementData::ElementType::TYPE); r.State()) { - getElement(r.Get()).TyEl.Size = size; - return { ElementDataHandle(r.Get()), (bool)r.State() }; - } else { - getElement(r.Get()).TyEl.Size = size; - return { ElementDataHandle(r.Get()), (bool)r.State() }; - } - } - - GTSL::Result tryEmplaceChild(const GTSL::StringView name, ElementDataHandle parentHandle) { - auto res = GTSL::Find(elements[parentHandle()].children, [&](const ElementData::Entry& entry) { return name == entry.Name; }); - - if(!res) { - auto newChildIndex = elements.Emplace(parentHandle(), GetPersistentAllocator()); - auto& newChild = elements[newChildIndex]; - newChild.Name = name; - elements[parentHandle()].children.EmplaceBack(name, ElementDataHandle(newChildIndex)); - - return { ElementDataHandle(newChildIndex), true}; - } - - return { ElementDataHandle(res.Get()->Handle), false}; - } - - GTSL::Result> GetRelativeOffset(const ElementDataHandle element_data_handle, const GTSL::StringView newScope) const { - ElementDataHandle handle = element_data_handle; - - auto getOffset = [&](const GTSL::StringView scope) -> GTSL::Result> { - uint32 offset = 0; - - if (handle != ElementDataHandle(1)) { //if we are not in global scope - if (getElement(handle).Type == ElementData::ElementType::MEMBER) { - handle = getElement(handle).Mem.TypeHandle; - } - - for (auto& k : elements[handle()].children) { - auto& t = getElement(k.Handle); - - if(t.Type != ElementData::ElementType::MEMBER) { continue; } - - offset = GTSL::Math::RoundUpByPowerOf2(offset, getElement(t.Mem.TypeHandle).TyEl.Alignment); - if (k.Name == newScope) { return { { k.Handle, static_cast(offset) }, true }; } - offset += getElement(t.Mem.TypeHandle).TyEl.Size * t.Mem.Multiplier; - } - } - - return { { ElementDataHandle(), 0 }, false }; - }; - - return getOffset(newScope); - } - - void updateDescriptors(TaskInfo taskInfo) { - auto* renderSystem = taskInfo.AppManager->GetSystem(u8"RenderSystem"); - - //for (auto& e : queuedSetUpdates) { - // resizeSet(renderSystem, e); - //} - - queuedSetUpdates.Clear(); - - auto& descriptorsUpdate = descriptorsUpdates[renderSystem->GetCurrentFrame()]; - - for (auto& set : descriptorsUpdate.sets) { - Vector bindingsUpdateInfos(16/*bindings sets*/, GetTransientAllocator()); - - for (auto& subSet : set.GetElements()) { - for (auto& b : subSet) { - for (auto& a : b.GetElements()) { - BindingsPool::BindingsUpdateInfo bindingsUpdateInfo; - bindingsUpdateInfo.Type = sets[set.First].SubSets[b.First].Type; - bindingsUpdateInfo.BindingsSet = &sets[set.First].bindingsSet[renderSystem->GetCurrentFrame()]; - bindingsUpdateInfo.SubsetIndex = b.First; - - for (auto& t : a) { - bindingsUpdateInfo.BindingIndex = t.First; - bindingsUpdateInfo.BindingUpdateInfos = t.GetElements(); - bindingsUpdateInfos.EmplaceBack(bindingsUpdateInfo); - } - } - } - - sets[set.First].bindingsPool[renderSystem->GetCurrentFrame()].Update(renderSystem->GetRenderDevice(), bindingsUpdateInfos, GetTransientAllocator()); - } - } - - descriptorsUpdate.Reset(); - } - - static constexpr GAL::BindingType BUFFER_BINDING_TYPE = GAL::BindingType::STORAGE_BUFFER; - - struct DescriptorsUpdate { - DescriptorsUpdate(const BE::PAR& allocator) : sets(16, allocator) { - } - - void AddBufferUpdate(SubSetHandle subSetHandle, uint32 binding, BindingsPool::BufferBindingUpdateInfo update) { - addUpdate(subSetHandle, binding, BindingsPool::BindingUpdateInfo(update)); - } - - void AddTextureUpdate(SubSetHandle subSetHandle, uint32 binding, BindingsPool::TextureBindingUpdateInfo update) { - addUpdate(subSetHandle, binding, BindingsPool::BindingUpdateInfo(update)); - } - - void AddAccelerationStructureUpdate(SubSetHandle subSetHandle, uint32 binding, BindingsPool::AccelerationStructureBindingUpdateInfo update) { - addUpdate(subSetHandle, binding, BindingsPool::BindingUpdateInfo(update)); - } - - void Reset() { - sets.Clear(); - } - - GTSL::SparseVector, BE::PAR>, BE::PAR> sets; - - private: - void addUpdate(SubSetHandle subSetHandle, uint32 binding, BindingsPool::BindingUpdateInfo update) { - if (sets.IsSlotOccupied(subSetHandle().setHandle())) { - auto& set = sets[subSetHandle().setHandle()]; - - if (set.IsSlotOccupied(subSetHandle().Subset)) { - auto& subSet = set[subSetHandle().Subset]; - - if (subSet.IsSlotOccupied(binding)) { - subSet[binding] = update; - } - else { //there isn't binding - subSet.EmplaceAt(binding, update); - } - } - else {//there isn't sub set - auto& subSet = set.EmplaceAt(subSetHandle().Subset, 32, sets.GetAllocator()); - //subSet.First = bindingType; - subSet.EmplaceAt(binding, update); - } - } - else { //there isn't set - auto& set = sets.EmplaceAt(subSetHandle().setHandle(), 16, sets.GetAllocator()); - auto& subSet = set.EmplaceAt(subSetHandle().Subset, 32, sets.GetAllocator()); - subSet.EmplaceAt(binding, update); - } - } - }; - - GTSL::StaticVector descriptorsUpdates; - - uint32 GetSize(const MemberHandle member_handle) { - return GetSize(ElementDataHandle(member_handle.Handle)); - } - - uint32 GetSize(const ElementDataHandle element_data_handle, bool getOnlyType = false) { - auto& e = elements[element_data_handle()]; - - switch (e.Type) { - case ElementData::ElementType::NONE: break; - case ElementData::ElementType::SCOPE: break; - case ElementData::ElementType::TYPE: return e.TyEl.Size; - case ElementData::ElementType::MEMBER: return getElement(e.Mem.TypeHandle).TyEl.Size * (getOnlyType ? 1 : e.Mem.Multiplier); - } - - BE_ASSERT(false, u8"Should not reach here"); - - return 0; - } - - /** - * \brief Stores all data per binding set. - */ - struct SetData { - Id Name; - //SetHandle Parent; - uint32 Level = 0; - PipelineLayout pipelineLayout; - BindingsSetLayout bindingsSetLayout; - BindingsPool bindingsPool[MAX_CONCURRENT_FRAMES]; - BindingsSet bindingsSet[MAX_CONCURRENT_FRAMES]; - - /** - * \brief Stores all data per sub set, and manages managed buffers. - * Each struct instance is pointed to by one binding. But a big per sub set buffer is used to store all instances. - */ - struct SubSetData { - GAL::BindingType Type; - uint32 AllocatedBindings = 0; - }; - GTSL::StaticVector SubSets; - }; - GTSL::FixedVector sets; - GTSL::PagedVector queuedSetUpdates; - - GTSL::StaticVector samplers; - - struct SetLayoutData { - uint8 Level = 0; - - SetLayoutHandle Parent; - BindingsSetLayout bindingsSetLayout; - PipelineLayout pipelineLayout; - GAL::ShaderStage Stage; - }; - GTSL::HashMap setLayoutDatas; - - SetHandle makeSetEx(RenderSystem* renderSystem, Id setName, SetLayoutHandle setLayoutHandle, GTSL::Range bindingDescriptors) { - auto setHandle = SetHandle(sets.Emplace()); - auto& set = sets[setHandle()]; - - auto& setLayout = setLayoutDatas[setLayoutHandle()]; - - set.Level = setLayout.Level; - set.bindingsSetLayout = setLayout.bindingsSetLayout; - set.pipelineLayout = setLayout.pipelineLayout; - - if (bindingDescriptors.ElementCount()) { - GTSL::StaticVector bindingsPoolSizes; - - for (auto& e : bindingDescriptors) { - bindingsPoolSizes.EmplaceBack(BindingsPool::BindingsPoolSize{ e.Type, e.BindingsCount * renderSystem->GetPipelinedFrames() }); - set.SubSets.EmplaceBack(); auto& subSet = set.SubSets.back(); - subSet.Type = e.Type; - subSet.AllocatedBindings = e.BindingsCount; - } - - for (uint8 f = 0; f < renderSystem->GetPipelinedFrames(); ++f) { - set.bindingsPool[f].Initialize(renderSystem->GetRenderDevice(), bindingsPoolSizes, 1); - set.bindingsSet[f].Initialize(renderSystem->GetRenderDevice(), set.bindingsPool[f], setLayout.bindingsSetLayout); - } - } - - return setHandle; - } - - friend class WorldRendererPipeline; - - byte* buffer[MAX_CONCURRENT_FRAMES]; uint32 offsets[MAX_CONCURRENT_FRAMES]{ 0 }; - - struct PendingWriteData { - RenderSystem::BufferHandle Buffer[2]; - bool FrameCountdown[MAX_CONCURRENT_FRAMES] = { false }; - }; - GTSL::HashMap pendingWrites; - - GTSL::ShortString<16> tag; - - static constexpr bool INVERSE_Z = true; - - GTSL::Math::RandomSeed randomA, randomB; - - uint32 bnoise[4] = { 0 }; - - uint32 frameIndex = 0; - - struct UpdateKeyData { - struct ttt - { - DataKeyHandle DKH; - ElementDataHandle EDH; - uint32 Offset; - }; - GTSL::StaticVector BWKs; - uint32 Value; - }; - GTSL::Vector updateKeys; - -#if BE_DEBUG - GAL::PipelineStage pipelineStages; - - struct DebugView { - GTSL::StaticString<64> name; - WindowSystem::WindowHandle windowHandle; - RenderSystem::RenderContextHandle renderContext; - RenderSystem::WorkloadHandle workloadHandles[MAX_CONCURRENT_FRAMES]; - GTSL::Extent2D sizeHistory[MAX_CONCURRENT_FRAMES]; - }; - GTSL::StaticVector views; -#endif - - void parseRenderPassJSON() { - GTSL::JSON json(GetPersistentAllocator()); - - GTSL::HashMap, BE::PAR> allAttachments(GetPersistentAllocator()); - GTSL::HashMap, BE::PAR> renderPassNodes(GetPersistentAllocator()); - - for(auto renderPass : json) { - auto name = renderPass[u8"name"]; - - auto& node = renderPassNodes.Emplace(name, 0u); - - for(auto attachment : renderPass[u8"attachments"]) { - auto name = attachment[u8"name"]; - - allAttachments.TryEmplace(name, name); - - auto use = attachment[u8"use"]; - - if(GTSL::StringView(use) == u8"INPUT") { - - } else if (GTSL::StringView(use) == u8"OUTPUT") { - - } else { - // TODO: error - } - } - - for(auto dependsOn : renderPass[u8"dependsOn"]) { - renderPassNodes[dependsOn].Connect(node); - } - } - - GTSL::Vector, BE::PAR> fullAttachments(GetPersistentAllocator()), transientAttachments(GetPersistentAllocator()); - } -}; - -inline uint64 Hash(char8_t c) { return c; } - -class UIRenderManager : public RenderManager { -public: - DECLARE_BE_TASK(OnCreateUIElement, BE_RESOURCES(RenderOrchestrator, UIManager), UIManager::UIElementHandle, UIManager::PrimitiveData::PrimitiveType); - - DECLARE_BE_TASK(OnFontLoad, BE_RESOURCES(RenderSystem, RenderOrchestrator), FontResourceManager::FontData, GTSL::Buffer); - - UIRenderManager(const InitializeInfo& initializeInfo) : RenderManager(initializeInfo, u8"UIRenderManager"), instancesMap(32, GetPersistentAllocator()), charToGlyphMap(GetPersistentAllocator()), characters(GetPersistentAllocator()) { - auto* renderSystem = initializeInfo.AppManager->GetSystem(u8"RenderSystem"); - auto* renderOrchestrator = initializeInfo.AppManager->GetSystem(u8"RenderOrchestrator"); - - auto tickTaskHandle = GetApplicationManager()->RegisterTask(this, u8"uiEveryFrame", DependencyBlock(TypedDependency(u8"RenderSystem"), TypedDependency(u8"RenderOrchestrator"), TypedDependency(u8"UIManager")), &UIRenderManager::everyFrame, u8"RenderSetup", u8"Render"); - GetApplicationManager()->EnqueueScheduledTask(tickTaskHandle); - - //TODO: check why setting an end stage stop the whole process - OnCreateUIElementTaskHandle = GetApplicationManager()->RegisterTask(this, u8"OnCreateUIElement", DependencyBlock(TypedDependency(u8"RenderOrchestrator"), TypedDependency(u8"UIManager")), &UIRenderManager::OnCreateUIElement); - - GetApplicationManager()->SubscribeToEvent(u8"UIManager", UIManager::GetOnCreateUIElementEventHandle(), OnCreateUIElementTaskHandle); - GetApplicationManager()->AddTypeSetupDependency(this, GetApplicationManager()->GetSystem(u8"UIManager")->GetUIElementTypeIdentifier(), OnCreateUIElementTaskHandle); - - renderOrchestrator->CreateScope(u8"global", u8"UI"); - - renderOrchestrator->RegisterType(u8"global.UI", u8"TextData", UI_TEXT_DATA); - renderOrchestrator->RegisterType(u8"global.UI", u8"LinearSegment", UI_LINEAR_SEGMENT); - renderOrchestrator->RegisterType(u8"global.UI", u8"QuadraticSegment", UI_QUADRATIC_SEGMENT); - renderOrchestrator->RegisterType(u8"global.UI", u8"GlyphContourData", UI_GLYPH_CONTOUR_DATA); - renderOrchestrator->RegisterType(u8"global.UI", u8"GlyphData", UI_GLYPH_DATA); - renderOrchestrator->RegisterType(u8"global.UI", u8"FontData", UI_FONT_DATA); - - renderOrchestrator->RegisterType(u8"global.UI", u8"UIInstance", UI_INSTANCE_DATA); - uiInstancesDataKey = renderOrchestrator->MakeDataKey(renderSystem, u8"global.UI", u8"UIInstance[16]"); - - renderOrchestrator->RegisterType(u8"global.UI", u8"UIData", UI_DATA); - uiDataDataKey = renderOrchestrator->MakeDataKey(renderSystem, u8"global.UI", u8"UIData"); - - { - RenderOrchestrator::PassData uiRenderPassData; - uiRenderPassData.type = RenderOrchestrator::PassTypes::RASTER; - uiRenderPassData.Attachments.EmplaceBack(GTSL::StringView(u8"UI"), GTSL::StringView(u8"UI"), GAL::AccessTypes::WRITE); - auto renderPassNodeHandle = renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"UI", u8"UIRenderPass", renderSystem, uiRenderPassData); - - auto uiDataNodeHandle = renderOrchestrator->AddDataNode(renderPassNodeHandle, u8"UIData", uiDataDataKey); - uiInstancesDataNodeHandle = renderOrchestrator->AddDataNode(uiDataNodeHandle, u8"UIInstancesData", uiInstancesDataKey, true); - - uiMaterialNodeHandle = renderOrchestrator->AddMaterial(uiInstancesDataNodeHandle, renderOrchestrator->CreateShaderGroup(u8"UI")); - textMaterialNodeHandle = renderOrchestrator->AddMaterial(uiInstancesDataNodeHandle, renderOrchestrator->CreateShaderGroup(u8"UIText")); - } - - meshNodeHandle = renderOrchestrator->AddSquare(uiMaterialNodeHandle); - textMeshNodeHandle = renderOrchestrator->AddSquare(textMaterialNodeHandle); - - // Load font data - OnFontLoadTaskHandle = GetApplicationManager()->RegisterTask(this, u8"OnFontLoad", DependencyBlock(TypedDependency(u8"RenderSystem"), TypedDependency(u8"RenderOrchestrator")), &UIRenderManager::OnFontLoad); - - auto* fontResourceManager = GetApplicationManager()->GetSystem(u8"FontResourceManager"); - fontResourceManager->LoadFont(u8"COOPBL", OnFontLoadTaskHandle); - // Load font data - } - - void OnCreateUIElement(const TaskInfo, RenderOrchestrator* render_orchestrator, UIManager* ui_manager, UIManager::UIElementHandle ui_element_handle, UIManager::PrimitiveData::PrimitiveType type) { - switch (type) { - break; case UIManager::PrimitiveData::PrimitiveType::NONE: - break; case UIManager::PrimitiveData::PrimitiveType::CANVAS: - break; case UIManager::PrimitiveData::PrimitiveType::ORGANIZER: - break; case UIManager::PrimitiveData::PrimitiveType::SQUARE: - render_orchestrator->AddInstance(uiInstancesDataNodeHandle, meshNodeHandle, ui_element_handle); - break; case UIManager::PrimitiveData::PrimitiveType::TEXT: { - auto string = ui_manager->GetString(ui_element_handle()); - - for(uint32 i = 0; i < string.GetCodepoints(); ++i) { - render_orchestrator->AddInstance(uiInstancesDataNodeHandle, textMeshNodeHandle, ui_element_handle); - } - } - break; case UIManager::PrimitiveData::PrimitiveType::CURVE: - break; - } - - instancesMap.Emplace(ui_element_handle(), 0); - } - - //void ui() { - // UIManager* ui; - // UIManager::TextPrimitive textPrimitive{ GetPersistentAllocator() }; - // - // RenderOrchestrator::BufferWriteKey text; - // text[u8"fontIndex"] = fontOrderMap[Id(textPrimitive.Font)]; - // - // for (uint32 i = 0; i < textPrimitive.Text; ++i) { - // text[u8"chars"][i] = fontCharMap[textPrimitive.Text[i]]; - // } - // - // for(const auto& e : ui->GetCanvases()) { - // } - // - // //ui->GetText - //} - - static GTSL::Matrix4 MakeOrthoMatrix(GTSL::Vector2 extent, const float32 nearPlane, const float32 farPlane) { - float32 w = extent.X() / extent.Y(); - - GTSL::Matrix4 matrix; - matrix[0][0] = static_cast(2) / (extent.X() - -extent.X()); - matrix[1][1] = static_cast(2) / (extent.Y() - -extent.Y()); - matrix[2][2] = static_cast(1) / (farPlane - nearPlane); - matrix[0][3] = -(w + -w) / (w - -w); - matrix[1][3] = -(1.0f + -1.0f) / (1.0f - -1.0f); - matrix[2][3] = -nearPlane / (farPlane - nearPlane); - - //matrix[0][3] = 0.0f; - //matrix[1][3] = 0.0f; - //matrix[2][3] = -nearPlane / (farPlane - nearPlane); - - return matrix; - } - - void everyFrame(TaskInfo, RenderSystem* render_system, RenderOrchestrator* render_orchestrator, UIManager* ui) { - ui->ProcessUpdates(); - - float32 r = 0; - - { - // TODO: value can be outdated - auto windowExtent = GTSL::Extent2D(1920, 1080); - auto windowSize = GTSL::Vector2(static_cast(windowExtent.Width), static_cast(windowExtent.Height)); - auto windowNormalizedSize = GTSL::Vector2(float32(windowExtent.Width) / static_cast(windowExtent.Height), 1.0f); - - auto screenExtent = GTSL::Extent2D(1920, 1080); - auto screenSize = GTSL::Vector2(screenExtent.Width, screenExtent.Height); - auto screenNormalizedSize = GTSL::Vector2(screenSize.X() / screenSize.Y(), 1.0f); - - auto renderSize = screenNormalizedSize * (windowSize / screenSize); - - r = GTSL::Math::LengthSquared(windowSize) / GTSL::Math::LengthSquared(screenSize); - - auto bwk = render_orchestrator->GetBufferWriteKey(render_system, uiDataDataKey); - - GTSL::Matrix4 projectionMatrix; - - if constexpr (UIManager::WINDOW_SPACE) { - projectionMatrix = MakeOrthoMatrix(windowNormalizedSize, 0.0f, 1.f); - } else { - projectionMatrix = MakeOrthoMatrix(renderSize, 0.0f, 1.f); - } - - //auto projectionMatrix = GTSL::Matrix4(); - projectionMatrix[1][1] *= API == GAL::RenderAPI::VULKAN ? -1.0f : 1.0f; - bwk[u8"projection"] = projectionMatrix; - } - - auto root = ui->GetRoot(); - - auto uiData = render_orchestrator->GetBufferWriteKey(render_system, uiDataDataKey); - auto bwk = render_orchestrator->GetBufferWriteKey(render_system, uiInstancesDataKey); - - auto visitUIElement = [&](GTSL::Tree::iterator iterator, GTSL::Matrix3x4 matrix, auto&& self) -> void { - if(!instancesMap.Find(iterator.GetHandle())) { return; } - - const auto& primitive = static_cast(iterator); - - GTSL::Matrix3x4 primitiveMatrix; - - //if(!primitive.isDirty) { return; } - - switch (primitive.Type) { - break; case UIManager::PrimitiveData::PrimitiveType::NONE: - break; case UIManager::PrimitiveData::PrimitiveType::CANVAS: - break; case UIManager::PrimitiveData::PrimitiveType::ORGANIZER: - break; case UIManager::PrimitiveData::PrimitiveType::SQUARE: { - GTSL::Math::Scale(primitiveMatrix, GTSL::Vector3(primitive.RenderSize, 0)); - GTSL::Math::Translate(primitiveMatrix, GTSL::Vector3(primitive.Position, 0)); - - const auto i = render_orchestrator->GetInstanceIndex(uiInstancesDataNodeHandle, iterator.GetHandle()); - - bwk[i][u8"transform"] = primitiveMatrix; - bwk[i][u8"color"] = GTSL::Vector4(primitive.Color); - bwk[i][u8"roundness"] = primitive.Rounding; - } - break; case UIManager::PrimitiveData::PrimitiveType::TEXT: { - uiData[u8"textData"][0][u8"fontIndex"] = 0u; - - auto string = ui->GetString(iterator.GetHandle()); - - float32 x = primitive.Position.X() + primitive.RenderSize.X() * -1.f; - - for(uint32 i = 0; auto c : string) { - if(!charToGlyphMap.Find(c)) { break; } - auto glyphIndex = charToGlyphMap[c]; - auto& character = characters[glyphIndex]; - - uiData[u8"textData"][0][u8"chars"][i] = glyphIndex; - - const auto index = render_orchestrator->GetInstanceIndex(uiInstancesDataNodeHandle, iterator.GetHandle()); - - //GTSL::Math::Scale(primitiveMatrix, GTSL::Vector3(primitive.RenderSize * GTSL::Vector2(character.Bearing.X, character.Bearing.Y) * 0.01f, 0)); - GTSL::Math::Scale(primitiveMatrix, GTSL::Vector3(primitive.RenderSize, 0)); - GTSL::Math::Translate(primitiveMatrix, GTSL::Vector3(x, primitive.Position.Y(), 0)); - - bwk[index][u8"transform"] = primitiveMatrix; - bwk[index][u8"color"] = GTSL::Vector4(primitive.Color); - bwk[index][u8"roundness"] = primitive.Rounding; - bwk[index][u8"derivedTypeIndex"][0] = 0; // Text - bwk[index][u8"derivedTypeIndex"][1] = glyphIndex; // Char - - // now advance cursors for next glyph (note that advance is number of 1/64 pixels) - x += (characters[glyphIndex].Advance >> 6); // bitshift by 6 to get value in pixels (2^6 = 64) - - ++i; - } - - - //float xpos = x + ch.Bearing.X; - //float ypos = y - (ch.Size.Height - ch.Bearing.Y); - } - break; case UIManager::PrimitiveData::PrimitiveType::CURVE: - break; - } - - for (auto e : iterator) { - self(e, primitiveMatrix, self); - } - }; - - visitUIElement(root, GTSL::Matrix3x4(), visitUIElement); - } - - void OnFontLoad(TaskInfo, RenderSystem* render_system, RenderOrchestrator* render_orchestrator, FontResourceManager::FontData font_data, GTSL::Buffer buffer) { - auto fontDataDataKey = render_orchestrator->MakeDataKey(render_system, u8"global.UI", u8"FontData"); - - RenderOrchestrator::BufferWriteKey uiData = render_orchestrator->GetBufferWriteKey(render_system, uiDataDataKey); - uiData[u8"fontData"][loadedFonts++] = fontDataDataKey; - - RenderOrchestrator::BufferWriteKey fontData = render_orchestrator->GetBufferWriteKey(render_system, fontDataDataKey); - - uint32 numberOfGlyphs; buffer >> numberOfGlyphs; - - for(uint32 gi = 0; gi < numberOfGlyphs; ++gi) { - auto glyphReferenceDataKey = render_orchestrator->MakeDataKey(render_system, u8"global.UI", u8"GlyphData"); - - fontData[u8"glyphs"][gi] = glyphReferenceDataKey; - - auto glyphReference = render_orchestrator->GetBufferWriteKey(render_system, glyphReferenceDataKey); - - charToGlyphMap.Emplace(FontResourceManager::ALPHABET[gi], gi); - characters.Emplace(gi, font_data.Characters.array[gi]); - - uint32 contourCount; buffer >> contourCount; - - glyphReference[u8"contourCount"] = contourCount; - - for(uint32 ci = 0; ci < contourCount; ++ci) { - uint32 pointCount; buffer >> pointCount; - - auto contourReference = glyphReference[u8"contours"][ci]; - - uint32 linearSegmentCount = 0, quadraticSegmentCount = 0; - - auto linearSegments = contourReference[u8"linearSegments"]; - auto quadraticSegments = contourReference[u8"quadraticSegments"]; - - for(uint32 pi = 0; pi < pointCount; ++pi) { - uint8 l = 0; buffer >> l; - - if(l == 3) { - GTSL::Vector2 quadraticSegment[3]; - buffer.Read(8 * 3, reinterpret_cast(&quadraticSegment)); - quadraticSegments[quadraticSegmentCount][u8"segments"][0] = quadraticSegment[0]; - quadraticSegments[quadraticSegmentCount][u8"segments"][1] = quadraticSegment[1]; - quadraticSegments[quadraticSegmentCount][u8"segments"][2] = quadraticSegment[2]; - ++quadraticSegmentCount; - } else { - GTSL::Vector2 linearSegment[2]; - buffer.Read(8 * 2, reinterpret_cast(&linearSegment)); - linearSegments[linearSegmentCount][u8"segments"][0] = linearSegment[0]; - linearSegments[linearSegmentCount][u8"segments"][1] = linearSegment[1]; - ++linearSegmentCount; - } - } - - contourReference[u8"linearSegmentCount"] = linearSegmentCount; - contourReference[u8"quadraticSegmentCount"] = quadraticSegmentCount; - } - } - - } - - RenderModelHandle GetUIMaterial() const { return uiMaterial; } - -private: - RenderOrchestrator::MemberHandle matrixUniformBufferMemberHandle, colorHandle; - RenderOrchestrator::MemberHandle uiDataStruct; - - RenderOrchestrator::NodeHandle uiMaterialNodeHandle, meshNodeHandle, textMeshNodeHandle, uiInstancesDataNodeHandle, textMaterialNodeHandle; - - GTSL::HashMap instancesMap; - - uint8 comps = 2; - RenderModelHandle uiMaterial; - - RenderOrchestrator::DataKeyHandle uiDataDataKey, uiInstancesDataKey; - - uint32 loadedFonts = 0; - - GTSL::HashMap charToGlyphMap; - GTSL::HashMap characters; -}; - -//if (textSystem->GetTexts().ElementCount()) -//{ -// int32 atlasIndex = 0; -// -// auto& text = textSystem->GetTexts()[0]; -// auto& imageFont = textSystem->GetFont(); -// -// auto x = text.Position.X; -// auto y = text.Position.Y; -// -// byte* data = static_cast(info.MaterialSystem->GetRenderGroupDataPointer("TextSystem")); -// -// uint32 offset = 0; -// -// GTSL::Matrix4 ortho; -// auto renderExtent = info.RenderSystem->GetRenderExtent(); -// GTSL::Math::MakeOrthoMatrix(ortho, static_cast(renderExtent.Width) * 0.5f, static_cast(renderExtent.Width) * -0.5f, static_cast(renderExtent.Height) * 0.5f, static_cast(renderExtent.Height) * -0.5f, 1, 100); -// GTSL::MemCopy(sizeof(ortho), &ortho, data + offset); offset += sizeof(ortho); -// GTSL::MemCopy(sizeof(uint32), &atlasIndex, data + offset); offset += sizeof(uint32); offset += sizeof(uint32) * 3; -// -// for (auto* c = text.String.begin(); c != text.String.end() - 1; c++) -// { -// auto& ch = imageFont.Characters.at(*c); -// -// float xpos = x + ch.Bearing.X * scale; -// float ypos = y - (ch.Size.Height - ch.Bearing.Y) * scale; -// -// float w = ch.Size.Width * scale; -// float h = ch.Size.Height * scale; -// -// // update VBO for each character -// float vertices[6][4] = { -// { xpos, -(ypos + h), 0.0f, 0.0f }, -// { xpos, -(ypos), 0.0f, 1.0f }, -// { xpos + w, -(ypos), 1.0f, 1.0f }, -// -// { xpos, -(ypos + h), 0.0f, 0.0f }, -// { xpos + w, -(ypos), 1.0f, 1.0f }, -// { xpos + w, -(ypos + h), 1.0f, 0.0f } -// }; -// -// // now advance cursors for next glyph (note that advance is number of 1/64 pixels) -// x += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64) -// -// uint32 val = ch.Position.Width; -// GTSL::MemCopy(sizeof(val), &val, data + offset); offset += sizeof(val); -// val = ch.Position.Height; -// GTSL::MemCopy(sizeof(val), &val, data + offset); offset += sizeof(val); -// -// val = ch.Size.Width; -// GTSL::MemCopy(sizeof(val), &val, data + offset); offset += sizeof(val); -// val = ch.Size.Height; -// GTSL::MemCopy(sizeof(val), &val, data + offset); offset += sizeof(val); -// -// for (uint32 v = 0; v < 6; ++v) -// { -// GTSL::MemCopy(sizeof(GTSL::Vector2), &vertices[v][0], data + offset); offset += sizeof(GTSL::Vector2); //vertices -// GTSL::MemCopy(sizeof(GTSL::Vector2), &vertices[v][2], data + offset); offset += sizeof(GTSL::Vector2); //uv -// } -// -// } -// -//} - -inline auto RenderPassStructToAttachments(const GTSL::Range struct_elements) { - GTSL::StaticVector attachmentReferences; - - for(const auto& e : struct_elements) { - if(e.Type == u8"TextureReference") { - attachmentReferences.EmplaceBack(GTSL::StringView(e.Name), GTSL::StringView(e.Name), GAL::AccessTypes::READ); - } - - if(e.Type == u8"ImageReference") { - attachmentReferences.EmplaceBack(GTSL::StringView(e.Name), GTSL::StringView(e.Name), GAL::AccessTypes::WRITE); - } - } - - return attachmentReferences; -} \ No newline at end of file diff --git a/src/ByteEngine/Render/RenderSystem.cpp b/src/ByteEngine/Render/RenderSystem.cpp deleted file mode 100644 index 4c5478a1..00000000 --- a/src/ByteEngine/Render/RenderSystem.cpp +++ /dev/null @@ -1,450 +0,0 @@ -#include "RenderSystem.h" - -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Application/ThreadPool.h" -#include "ByteEngine/Application/WindowSystem.hpp" -#include "ByteEngine/Application/Templates/GameApplication.h" -#include "ByteEngine/Debug/Assert.h" -#include "ByteEngine/Resources/PipelineCacheResourceManager.h" - -#include - -#undef MemoryBarrier - -class CameraSystem; -class RenderStaticMeshCollection; - -PipelineCache RenderSystem::GetPipelineCache() const { return pipelineCaches[GTSL::Thread::ThisTreadID()]; } - -RenderSystem::RenderSystem(const InitializeInfo& initializeInfo) : System(initializeInfo, u8"RenderSystem"), - accelerationStructures(16, GetPersistentAllocator()), buffers(32, GetPersistentAllocator()), - pipelineCaches(16, decltype(pipelineCaches)::allocator_t()), - textures(16, GetPersistentAllocator()), apiAllocations(128, GetPersistentAllocator()), workloads(16, GetPersistentAllocator()) -{ - { - initializeInfo.AppManager->EnqueueScheduledTask(initializeInfo.AppManager->RegisterTask(this, u8"endCommandLists", DependencyBlock(), &RenderSystem::renderFlush, u8"FrameEnd", u8"FrameEnd")); - resizeHandle = initializeInfo.AppManager->RegisterTask(this, u8"onResize", {}, & RenderSystem::onResize); - } - - RenderDevice::RayTracingCapabilities rayTracingCapabilities; - - auto config = BE::Application::Get()->GetConfig()[u8"Rendering"]; - - useHDR = config[u8"hdr"].GetBool(); - pipelinedFrames = static_cast(GTSL::Math::Clamp(static_cast(config[u8"buffer"].GetUint()), 2u, 3u)); - bool rayTracing = config[u8"rayTracing"].GetBool(); - - { - RenderDevice::CreateInfo createInfo; - createInfo.ApplicationName = GTSL::StaticString<128>(BE::Application::Get()->GetApplicationName()); - createInfo.ApplicationVersion[0] = 0; createInfo.ApplicationVersion[1] = 0; createInfo.ApplicationVersion[2] = 0; - - createInfo.Debug = static_cast(BE::Application::Get()->GetUINTOption(u8"debug")); - - GTSL::StaticVector queue_create_infos; - GTSL::StaticVector queueKeys; - - queue_create_infos.EmplaceBack(GAL::QueueTypes::GRAPHICS); queueKeys.EmplaceBack(); - queue_create_infos.EmplaceBack(GAL::QueueTypes::COMPUTE); queueKeys.EmplaceBack(); - queue_create_infos.EmplaceBack(GAL::QueueTypes::TRANSFER); queueKeys.EmplaceBack(); - - createInfo.Queues = queue_create_infos; - createInfo.QueueKeys = queueKeys; - - GTSL::StaticVector, 8> extensions{ { RenderDevice::Extension::PIPELINE_CACHE_EXTERNAL_SYNC, nullptr } }; - extensions.EmplaceBack(RenderDevice::Extension::SWAPCHAIN_RENDERING, nullptr); - extensions.EmplaceBack(RenderDevice::Extension::SCALAR_LAYOUT, nullptr); - if (rayTracing) { extensions.EmplaceBack(RenderDevice::Extension::RAY_TRACING, &rayTracingCapabilities); } - - createInfo.Extensions = extensions; - createInfo.PerformanceValidation = true; - createInfo.SynchronizationValidation = true; - createInfo.DebugPrintFunction = GTSL::Delegate::Create(this); - createInfo.allocation.UserData = this; - createInfo.allocation.Allocate = GTSL::Delegate::Create(this); - createInfo.allocation.Reallocate = GTSL::Delegate::Create(this); - createInfo.allocation.Deallocate = GTSL::Delegate::Create(this); - - if (auto renderDeviceInitializationResult = renderDevice.Initialize(createInfo, GetTransientAllocator())) { - BE_LOG_SUCCESS(u8"Started RenderDevice\n API: Vulkan\n GPU: ", renderDevice.GetGPUInfo().GPUName, u8"\n Memory: ", 6, u8" GB\n API Version: ", renderDevice.GetGPUInfo().APIVersion); - } else { - BE_LOG_ERROR(u8"Failed to initialize RenderDevice!\n API: Vulkan\n Reason: \"", renderDeviceInitializationResult.Get(), u8"\n"); - return; - } - - graphicsQueue.Initialize(GetRenderDevice(), queueKeys[0]); computeQueue.Initialize(GetRenderDevice(), queueKeys[1]); transferQueue.Initialize(GetRenderDevice(), queueKeys[2]); - - { - needsStagingBuffer = true; - - auto memoryHeaps = renderDevice.GetMemoryHeaps(); GAL::VulkanRenderDevice::MemoryHeap& biggestGPUHeap = memoryHeaps[0]; - - for (auto& e : memoryHeaps) { - if (e.HeapType & GAL::MemoryTypes::GPU) { - if (e.Size > biggestGPUHeap.Size) { - biggestGPUHeap = e; - - for (auto& mt : e.MemoryTypes) { - if (mt & GAL::MemoryTypes::GPU && mt & GAL::MemoryTypes::HOST_COHERENT && mt & GAL::MemoryTypes::HOST_VISIBLE) { - needsStagingBuffer = false; break; - } - } - } - } - } - } - - scratchMemoryAllocator.Initialize(renderDevice, GetPersistentAllocator()); - localMemoryAllocator.Initialize(renderDevice, GetPersistentAllocator()); - - if (rayTracing) { - shaderGroupHandleAlignment = rayTracingCapabilities.ShaderGroupHandleAlignment; - shaderGroupHandleSize = rayTracingCapabilities.ShaderGroupHandleSize; - scratchBufferOffsetAlignment = rayTracingCapabilities.ScratchBuildOffsetAlignment; - shaderGroupBaseAlignment = rayTracingCapabilities.ShaderGroupBaseAlignment; - - accelerationStructureBuildDevice = rayTracingCapabilities.BuildDevice; - } - } - - bool pipelineCacheAvailable; - auto* pipelineCacheManager = initializeInfo.AppManager->GetSystem(u8"PipelineCacheResourceManager"); - pipelineCacheManager->DoesCacheExist(pipelineCacheAvailable); - - if (pipelineCacheAvailable) { - uint32 cacheSize = 0; - pipelineCacheManager->GetCacheSize(cacheSize); - - GTSL::Buffer pipelineCacheBuffer(cacheSize, 32, GetTransientAllocator()); - - pipelineCacheManager->GetCache(pipelineCacheBuffer); - - for (uint8 i = 0; i < BE::Application::Get()->GetNumberOfThreads(); ++i) { - pipelineCaches.EmplaceBack().Initialize(GetRenderDevice(), true, static_cast>(pipelineCacheBuffer)); - } - } else { - for (uint8 i = 0; i < BE::Application::Get()->GetNumberOfThreads(); ++i) { - pipelineCaches.EmplaceBack().Initialize(GetRenderDevice(), true, {}); - } - } - - BE_LOG_MESSAGE(u8"Initialized successfully"); -} - -class PresentKey { - Synchronizer Fence; - uint8 ImageIndex = 0; -}; - -RenderSystem::~RenderSystem() { - renderDevice.Wait(); - - scratchMemoryAllocator.Free(renderDevice, GetPersistentAllocator()); - localMemoryAllocator.Free(renderDevice, GetPersistentAllocator()); - - { - uint32 cacheSize = 0; PipelineCache pipelineCache; - pipelineCache.Initialize(GetRenderDevice(), pipelineCaches); - pipelineCache.GetCacheSize(GetRenderDevice(), cacheSize); - - if (cacheSize) { - //auto* pipelineCacheResourceManager = shutdownInfo.ApplicationManager->GetSystem(u8"PipelineCacheResourceManager"); - // - //GTSL::Buffer pipelineCacheBuffer(cacheSize, 32, GetTransientAllocator()); - //pipelineCache.GetCache(&renderDevice, pipelineCacheBuffer); - //pipelineCacheResourceManager->WriteCache(pipelineCacheBuffer); - } - } -} - -void RenderSystem::renderFlush(TaskInfo taskInfo) { - auto beforeFrame = uint8(currentFrameIndex - uint8(1)) % GetPipelinedFrames(); - - ++currentFrameIndex %= pipelinedFrames; -} - -RenderSystem::TextureHandle RenderSystem::CreateTexture(GTSL::Range name, GAL::FormatDescriptor formatDescriptor, GTSL::Extent3D extent, GAL::TextureUse textureUses, bool updatable, TextureHandle texture_handle) -{ - auto doTexture = [&](TextureComponent& texture) { - const auto textureSize = extent.Width * extent.Height * extent.Depth * formatDescriptor.GetSize(); - - if (updatable && needsStagingBuffer) { - AllocateScratchBufferMemory(textureSize, GAL::BufferUses::TRANSFER_SOURCE, &texture.ScratchBuffer, &texture.ScratchAllocation); - } - - AllocateLocalTextureMemory(&texture.texture, name, texture.Uses, texture.format, extent, GAL::Tiling::OPTIMAL, 1, &texture.Allocation); - texture.textureView.Initialize(GetRenderDevice(), name, texture.texture, texture.format, extent, 1); - }; - - if(texture_handle) { - auto& texture = textures[texture_handle()]; - - if(extent != texture.Extent) { - if(texture.texture.GetVkImage()) { - texture.texture.Destroy(GetRenderDevice()); - DeallocateLocalBufferMemory(texture.Allocation); - - if (texture.ScratchAllocation.Data) { - DeallocateScratchBufferMemory(texture.ScratchAllocation); - } - } - - if(texture.textureView.GetVkImageView()) { - texture.textureView.Destroy(GetRenderDevice()); - } - - doTexture(texture); - } - - return texture_handle; - } - - const auto textureIndex = textures.Emplace(); - - auto& texture = textures[textureIndex]; - - texture.Extent = extent; - texture.format = formatDescriptor; - texture.Uses = textureUses; - if (updatable) { texture.Uses |= GAL::TextureUses::TRANSFER_DESTINATION; } - texture.Layout = GAL::TextureLayout::UNDEFINED; - - doTexture(texture); - - return TextureHandle(textureIndex); -} - -void RenderSystem::UpdateTexture(const CommandListHandle command_list_handle, const TextureHandle textureHandle) -{ - const auto& texture = textures[textureHandle()]; - - TextureCopyData textureCopyData; - textureCopyData.Layout = texture.Layout; - textureCopyData.Extent = texture.Extent; - textureCopyData.Allocation = texture.Allocation; - textureCopyData.DestinationTexture = texture.texture; - textureCopyData.SourceOffset = 0; - textureCopyData.SourceBuffer = texture.ScratchBuffer; - textureCopyData.Format = texture.format; - AddTextureCopy(command_list_handle, textureCopyData); -} - -void RenderSystem::OnRenderEnable(TaskInfo taskInfo, bool oldFocus) -{ - if(!oldFocus) { - BE_LOG_SUCCESS(u8"Enabled rendering") - } - - //OnResize(window->GetFramebufferExtent()); -} - -void RenderSystem::OnRenderDisable(TaskInfo taskInfo, bool oldFocus) -{ - if (oldFocus) { - BE_LOG_SUCCESS(u8"Disabled rendering") - } -} - -GTSL::Result RenderSystem::AcquireImage(const RenderContextHandle render_context_handle, const WorkloadHandle workload_handle, WindowSystem* window_system) -{ - bool result = false; - - auto& renderContext = renderx[render_context_handle()]; - - if(!renderContext.renderContext.GetHandle()) { - resize(window_system,render_context_handle); result = true; - } - - const auto acquireResult = renderContext.renderContext.AcquireNextImage(&renderDevice, &workloads[workload_handle()].Semaphore); - - renderContext.imageIndex = acquireResult.Get(); - - switch (acquireResult.State()) { - case GAL::VulkanRenderContext::AcquireState::OK: break; - case GAL::VulkanRenderContext::AcquireState::SUBOPTIMAL: - case GAL::VulkanRenderContext::AcquireState::BAD: resize(window_system,render_context_handle); result = true; break; - } - - if (renderContext.lastRenderArea != renderContext.renderArea) { renderContext.lastRenderArea = renderContext.renderArea; result = true; } - - return { GTSL::MoveRef(renderContext.renderArea), result }; -} - -void RenderSystem::resize(WindowSystem* window_system, const RenderContextHandle render_context_handle) { - auto& renderContext = renderx[render_context_handle()]; - - if (!renderContext.surface.GetHandle()) { - renderContext.surface.Initialize(GetRenderDevice(), *BE::Application::Get()->GetSystemApplication(), window_system->GetWindow(renderContext.windowHandle)); - } - - Surface::SurfaceCapabilities surfaceCapabilities; - auto isSupported = renderContext.surface.IsSupported(&renderDevice, &surfaceCapabilities); - - renderContext.renderArea = surfaceCapabilities.CurrentExtent; - - if (!isSupported) { - BE::Application::Get()->Close(BE::Application::CloseMode::ERROR, GTSL::StaticString<64>(u8"No supported surface found!")); - } - - auto supportedPresentModes = renderContext.surface.GetSupportedPresentModes(&renderDevice); - swapchainPresentMode = supportedPresentModes[0]; - - auto supportedSurfaceFormats = renderContext.surface.GetSupportedFormatsAndColorSpaces(&renderDevice); - - { - GTSL::Pair bestColorSpaceFormat; - - for (uint8 topScore = 0; const auto & e : supportedSurfaceFormats) { - uint8 score = 0; - - if (useHDR && e.First == GAL::ColorSpaces::HDR10_ST2048) { - score += 5; - } - else { - if (e.Second.ColorSpace == GAL::ColorSpaces::SRGB_NONLINEAR) { - score += 2; - } - else { - score += 3; - } - } - - if (score > topScore) { - bestColorSpaceFormat = e; - topScore = score; - } - } - - swapchainColorSpace = bestColorSpaceFormat.First; swapchainFormat = bestColorSpaceFormat.Second; - } - - renderContext.renderContext.InitializeOrRecreate(GetRenderDevice(), graphicsQueue, &renderContext.surface, renderContext.renderArea, swapchainFormat, swapchainColorSpace, GAL::TextureUses::STORAGE | GAL::TextureUses::TRANSFER_DESTINATION, swapchainPresentMode, pipelinedFrames); - - for (auto& e : renderContext.swapchainTextureViews) { e.Destroy(&renderDevice); } - - //imageIndex = 0; keep index of last acquired image - - { - auto newSwapchainTextures = renderContext.renderContext.GetTextures(GetRenderDevice()); - for (uint8 f = 0; f < pipelinedFrames; ++f) { - renderContext.swapchainTextures[f] = newSwapchainTextures[f]; - renderContext.swapchainTextureViews[f].Destroy(GetRenderDevice()); - - GTSL::StaticString<64> name(u8"Swapchain ImageView "); name += f; - - renderContext.swapchainTextureViews[f].Initialize(GetRenderDevice(), name, renderContext.swapchainTextures[f], swapchainFormat, renderContext.renderArea, 1); - } - } -} - -RenderSystem::BufferHandle RenderSystem::CreateBuffer(uint32 size, GAL::BufferUse flags, bool willWriteFromHost, BufferHandle buffer_handle) { - auto doBuffer = [&] { - auto& buffer = buffers[buffer_handle()]; - - if (size > buffer.Size) { - if (buffer.Buffer.GetVkBuffer()) { - buffer.Buffer.Destroy(GetRenderDevice()); - - if (willWriteFromHost && needsStagingBuffer) { - DeallocateLocalBufferMemory(buffer.Allocation); - } else { - DeallocateLocalBufferMemory(buffer.Allocation); - } - } - - if (willWriteFromHost && needsStagingBuffer) { - flags |= GAL::BufferUses::ADDRESS | GAL::BufferUses::TRANSFER_SOURCE; - AllocateScratchBufferMemory(size, flags, &buffer.Buffer, &buffer.Allocation); - } else { - flags |= GAL::BufferUses::ADDRESS | GAL::BufferUses::TRANSFER_DESTINATION; - AllocateLocalBufferMemory(size, flags, &buffer.Buffer, &buffer.Allocation); - } - - buffer.Addresses = buffer.Buffer.GetAddress(GetRenderDevice()); - - buffer.Size = size; - } - }; - - if(buffer_handle) { - doBuffer(); - return buffer_handle; - } - - GTSL::Max(&size, 1024u); //force buffers to have a minimum size, so we always allocate and have valid data - - uint32 bufferIndex = buffers.Emplace(); auto& buffer = buffers[bufferIndex]; - - buffer_handle = BufferHandle(bufferIndex); - - buffer.Flags = flags; - ++buffer.references; - - doBuffer(); - - return buffer_handle; -} - -void RenderSystem::printError(GTSL::StringView message, const RenderDevice::MessageSeverity messageSeverity) const { - bool breakeablelogLevel = false; - - switch (messageSeverity) { - //case RenderDevice::MessageSeverity::MESSAGE: BE_LOG_MESSAGE(message) break; - case RenderDevice::MessageSeverity::WARNING: BE_LOG_WARNING(message); break; - case RenderDevice::MessageSeverity::ERROR: BE_LOG_ERROR(message); breakeablelogLevel = true; break; - default: break; - } -} - -void* RenderSystem::allocateApiMemory(void* data, const uint64 size, const uint64 alignment) { - void* allocation; uint64 allocated_size; - GetPersistentAllocator().Allocate(size, alignment, &allocation, &allocated_size); - - { - GTSL::Lock lock(allocationsMutex); - apiAllocations.Emplace(reinterpret_cast(allocation), GTSL::Pair(size, alignment)); - } - - return allocation; -} - -void* RenderSystem::reallocateApiMemory(void* data, void* oldAllocation, uint64 size, uint64 alignment) { - void* allocation; uint64 allocated_size; - - GTSL::Pair old_alloc; - - { - GTSL::Lock lock(allocationsMutex); - old_alloc = apiAllocations[reinterpret_cast(oldAllocation)]; - } - - GetPersistentAllocator().Allocate(size, old_alloc.Second, &allocation, &allocated_size); - apiAllocations.Emplace(reinterpret_cast(allocation), GTSL::Pair(size, alignment)); - - GTSL::MemCopy(old_alloc.First, oldAllocation, allocation); - - GetPersistentAllocator().Deallocate(old_alloc.First, old_alloc.Second, oldAllocation); - - { - GTSL::Lock lock(allocationsMutex); - apiAllocations.Remove(reinterpret_cast(oldAllocation)); - } - - return allocation; -} - -void RenderSystem::deallocateApiMemory(void* data, void* allocation) { - GTSL::Pair old_alloc; - - { - GTSL::Lock lock(allocationsMutex); - old_alloc = apiAllocations[reinterpret_cast(allocation)]; - } - - GetPersistentAllocator().Deallocate(old_alloc.First, old_alloc.Second, allocation); - - { - GTSL::Lock lock(allocationsMutex); - apiAllocations.Remove(reinterpret_cast(allocation)); - } -} diff --git a/src/ByteEngine/Render/RenderSystem.h b/src/ByteEngine/Render/RenderSystem.h deleted file mode 100644 index c36e52c5..00000000 --- a/src/ByteEngine/Render/RenderSystem.h +++ /dev/null @@ -1,718 +0,0 @@ -#pragma once - -#include "ByteEngine/Handle.hpp" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Game/System.hpp" - -#include "RendererAllocator.h" -#include "RenderTypes.h" - -#include - -#include -#include - -#include "ByteEngine/Application/WindowSystem.hpp" - -namespace GTSL { - class Window; -} - -class RenderSystem : public BE::System { -public: - MAKE_HANDLE(uint32, Buffer) - MAKE_HANDLE(uint32, Texture); - MAKE_HANDLE(uint32, RenderContext); - - explicit RenderSystem(const InitializeInfo& initializeInfo); - ~RenderSystem(); - [[nodiscard]] uint8 GetCurrentFrame() const { return currentFrameIndex; } - [[nodiscard]] uint8 GetFrameIndex(int32 frameDelta) const { return static_cast(frameDelta % pipelinedFrames); } - uint8 GetPipelinedFrames() const { return pipelinedFrames; } - GAL::FormatDescriptor GetSwapchainFormat() const { return swapchainFormat; } - TaskHandle GetResizeHandle() const { return resizeHandle; } - - GTSL::Range GetBufferRange(BufferHandle buffer_handle) const { - const auto& buffer = buffers[buffer_handle()]; - return { buffer.Size, (byte*)buffer.Allocation.Data }; - } - - MAKE_HANDLE(uint32, CommandList); - MAKE_HANDLE(uint32, Workload); - MAKE_HANDLE(uint32, AccelerationStructure); - MAKE_HANDLE(uint32, BLASInstance); - - struct WorkloadData { - GTSL::StaticVector AssociatedCommandlists; - Synchronizer Fence, Semaphore; - GAL::PipelineStage PipelineStages; - }; - GTSL::FixedVector workloads; - - WorkloadHandle CreateWorkload(GTSL::StringView name, GAL::QueueType type, GAL::PipelineStage pipeline_stages) { - uint32 index = workloads.Emplace(); - auto& workload = workloads[index]; - workload.Fence.Initialize(GetRenderDevice(), name, Synchronizer::Type::FENCE); - workload.Semaphore.Initialize(GetRenderDevice(), name, Synchronizer::Type::SEMAPHORE); - - workload.PipelineStages = pipeline_stages; - - return WorkloadHandle(index); - } - - CommandListHandle CreateCommandList(const GTSL::StringView name, GAL::QueueType type, GAL::PipelineStage pipeline_stages, bool isSingleFrame = true) { - uint32 index = commandLists.GetLength(); - auto& commandList = commandLists.EmplaceBack(GetPersistentAllocator()); - //commandList.Fence.Initialize(GetRenderDevice(), true); - commandList.Semaphore.Initialize(GetRenderDevice(), name, GAL::VulkanSynchronizer::Type::SEMAPHORE); - commandList.Fence.Initialize(GetRenderDevice(), name, GAL::VulkanSynchronizer::Type::FENCE); - commandList.Operations = type; - commandList.PipelineStages = pipeline_stages; - - if (type & GAL::QueueTypes::GRAPHICS) { - commandList.commandList.Initialize(GetRenderDevice(), name, graphicsQueue.GetQueueKey(), !isSingleFrame); - } - - if (type & GAL::QueueTypes::COMPUTE) { - commandList.commandList.Initialize(GetRenderDevice(), name, computeQueue.GetQueueKey(), !isSingleFrame); - } - - if (type & GAL::QueueTypes::TRANSFER) { - commandList.commandList.Initialize(GetRenderDevice(), name, transferQueue.GetQueueKey(), !isSingleFrame); - } - - return CommandListHandle(index); - } - - void StartCommandList(const CommandListHandle command_list_handle) { - auto& commandListData = commandLists[command_list_handle()]; - - if(commandListData.Fence.State()) { - commandListData.Fence.Wait(GetRenderDevice()); - commandListData.Fence.Reset(GetRenderDevice()); - } - - commandListData.commandList.BeginRecording(GetRenderDevice()); - - { - GTSL::Vector barriers(commandListData.bufferCopyDatas.GetLength(), GetTransientAllocator()); - - for (auto& e : commandListData.bufferCopyDatas) { - commandListData.commandList.CopyBuffer(GetRenderDevice(), buffers[e.SourceBufferHandle()].Buffer, e.SourceOffset, buffers[e.DestinationBufferHandle()].Buffer, e.DestinationOffset, buffers[e.SourceBufferHandle()].Size); - - //auto& barrier = barriers.EmplaceBack(GAL::PipelineStages::TRANSFER, GAL::PipelineStages::ACCELERATION_STRUCTURE_BUILD, GAL::AccessTypes::WRITE, GAL::AccessTypes::READ, CommandList::BufferBarrier{ &buffer.Buffer, buffer.Size }); - } - - commandListData.commandList.AddPipelineBarrier(GetRenderDevice(), barriers, GetTransientAllocator()); - - commandListData.bufferCopyDatas.Resize(0); - } - - if (auto& textureCopyData = commandListData.textureCopyDatas; textureCopyData) { - GTSL::Vector sourceTextureBarriers(textureCopyData.GetLength(), GetTransientAllocator()); - GTSL::Vector destinationTextureBarriers(textureCopyData.GetLength(), GetTransientAllocator()); - - for (uint32 i = 0; i < textureCopyData.GetLength(); ++i) { - sourceTextureBarriers.EmplaceBack(GAL::PipelineStages::TRANSFER, commandListData.PipelineStages, GAL::AccessTypes::READ, GAL::AccessTypes::WRITE, CommandList::TextureBarrier{ &textureCopyData[i].DestinationTexture, GAL::TextureLayout::UNDEFINED, GAL::TextureLayout::TRANSFER_DESTINATION, textureCopyData[i].Format }); - destinationTextureBarriers.EmplaceBack(GAL::PipelineStages::TRANSFER, commandListData.PipelineStages, GAL::AccessTypes::WRITE, GAL::AccessTypes::READ, CommandList::TextureBarrier{ &textureCopyData[i].DestinationTexture, GAL::TextureLayout::TRANSFER_DESTINATION, GAL::TextureLayout::SHADER_READ, textureCopyData[i].Format }); - } - - commandListData.commandList.AddPipelineBarrier(GetRenderDevice(), sourceTextureBarriers, GetTransientAllocator()); - - for (uint32 i = 0; i < textureCopyData.GetLength(); ++i) { - commandListData.commandList.CopyBufferToTexture(GetRenderDevice(), textureCopyData[i].SourceBuffer, textureCopyData[i].DestinationTexture, GAL::TextureLayout::TRANSFER_DESTINATION, textureCopyData[i].Format, textureCopyData[i].Extent); - } - - commandListData.commandList.AddPipelineBarrier(GetRenderDevice(), destinationTextureBarriers, GetTransientAllocator()); - } - - commandListData.textureCopyDatas.Resize(0); - } - - void DispatchBuild(const CommandListHandle command_list_handle, const GTSL::Range handles) { - if(!handles.ElementCount()) { return; } - - auto& commandListData = commandLists[command_list_handle()]; - - GTSL::StaticVector buildDatas; - GTSL::StaticVector, 8> geometries; - - for (auto handle : handles) { - auto& buildData = buildDatas.EmplaceBack(); - - if (accelerationStructures[handle()].isTop) { - const auto& as = accelerationStructures[handle()]; - auto& tlas = accelerationStructures[handle()].TopLevel; - - buildData.DestinationAccelerationStructure = tlas.AccelerationStructures; - buildData.ScratchBufferAddress = GetBufferAddress(as.ScratchBuffer); - - commandListData.commandList.CopyBuffer(GetRenderDevice(), buffers[tlas.SourceInstancesBuffer()].Buffer, buffers[tlas.DestinationInstancesBuffer()].Buffer, GetBufferSize(tlas.DestinationInstancesBuffer)); - - geometries.EmplaceBack().EmplaceBack(GAL::GeometryInstances{ GetBufferAddress(tlas.DestinationInstancesBuffer) }, GAL::GeometryFlag(), as.PrimitiveCount, 0); - } else { - const auto& as = accelerationStructures[handle()]; - const auto& blas = accelerationStructures[handle()].BottomLevel; - - buildData.DestinationAccelerationStructure = blas.accelerationStructure; - buildData.ScratchBufferAddress = GetBufferAddress(as.ScratchBuffer); - - geometries.EmplaceBack().EmplaceBack(GAL::Geometry{ GAL::GeometryTriangles{ GAL::ShaderDataType::FLOAT3, GAL::IndexType::UINT16, static_cast(blas.VertexSize), GetBufferAddress(blas.VertexBuffer) + blas.VertexByteOffset, GetBufferAddress(blas.IndexBuffer) + blas.IndexBufferByteOffset, 0, blas.VertexCount }, GAL::GeometryFlags::OPAQUE, as.PrimitiveCount, 0 }); - } - - buildData.Geometries = geometries.back(); - } - - switch (accelerationStructureBuildDevice) { - case GAL::Device::CPU: break; - case GAL::Device::GPU: - case GAL::Device::GPU_OR_CPU: { - commandListData.commandList.BuildAccelerationStructure(GetRenderDevice(), buildDatas, GetTransientAllocator()); - break; - } - default:; - } - - GTSL::StaticVector barriers; - barriers.EmplaceBack(GAL::PipelineStages::ACCELERATION_STRUCTURE_BUILD, GAL::PipelineStages::RAY_TRACING, GAL::AccessTypes::WRITE, GAL::AccessTypes::READ, CommandList::MemoryBarrier{}); - commandListData.commandList.AddPipelineBarrier(GetRenderDevice(), barriers, GetTransientAllocator()); - } - - - void StagingCopy(const CommandListHandle command_list, const BufferHandle handle) { - commandLists[command_list()].commandList.CopyBuffer(GetRenderDevice(), buffers[handle()].Buffer, buffers[handle()].Buffer, buffers[handle()].Size); - } - - void EndCommandList(const CommandListHandle command_list_handle) { - auto& commandListData = commandLists[command_list_handle()]; - commandListData.commandList.EndRecording(GetRenderDevice()); - } - - void Wait(WorkloadHandle workload_handle) { - auto& workloadData = workloads[workload_handle()]; - - if (workloadData.Fence.State()) { - workloadData.Fence.Wait(GetRenderDevice()); - workloadData.Fence.Reset(GetRenderDevice()); - } - } - - struct WorkUnit { - GTSL::Range CommandListHandles; - GTSL::Range WaitWorkloadHandles, SignalWorkloadHandles; - }; - - void Submit(const GAL::QueueType queue_type, const GTSL::Range work_units, const WorkloadHandle workload_handle) { - GTSL::StaticVector, 8> workUnits; - GTSL::StaticVector, 4> command_listses; - GTSL::StaticVector::SynchronizerOperationInfo, 8>, 4> waitOperations, signalOperations; - - for (uint32 wui = 0; wui < work_units.ElementCount(); ++wui) { - auto& wu = work_units[wui]; - auto& workUnit = workUnits.EmplaceBack(); auto& cl = command_listses.EmplaceBack(); auto& wo = waitOperations.EmplaceBack(); auto& so = signalOperations.EmplaceBack(); - - for(auto& e : wu.WaitWorkloadHandles) { - auto& workload = workloads[e()]; - wo.EmplaceBack(&workload.Semaphore, workload.PipelineStages); - } - - for (auto& e : wu.SignalWorkloadHandles) { - auto& workload = workloads[e()]; - so.EmplaceBack(&workload.Semaphore, workload.PipelineStages); - } - - for (auto& e : wu.CommandListHandles) { - auto& c = commandLists[e()]; - cl.EmplaceBack(&c.commandList); - } - - workUnit.CommandLists = cl; - workUnit.Signal = so; - workUnit.Wait = wo; - } - - auto& workload = workloads[workload_handle()]; - - if (queue_type & GAL::QueueTypes::GRAPHICS) { - graphicsQueue.Submit(GetRenderDevice(), workUnits, workload.Fence); - } - - if (queue_type & GAL::QueueTypes::COMPUTE) { - computeQueue.Submit(GetRenderDevice(), workUnits, workload.Fence); - } - - if(queue_type & GAL::QueueTypes::TRANSFER) { - transferQueue.Submit(GetRenderDevice(), workUnits, workload.Fence); - } - } - - void Present(WindowSystem* window_system, GTSL::Range render_context_handles, const GTSL::Range wait_workload_handles) { - GTSL::StaticVector waitSemaphores; - - for(auto e : wait_workload_handles) { - waitSemaphores.EmplaceBack(&workloads[e()].Semaphore); - } - - GTSL::StaticVector renderContexts; - GTSL::StaticVector imageIndices; - - for(auto& e : render_context_handles) { - auto& renderContext = renderx[e()]; - renderContexts.EmplaceBack(&renderContext.renderContext); - imageIndices.EmplaceBack(renderContext.imageIndex); - } - - RenderContext::Present(GetRenderDevice(), waitSemaphores, renderContexts, imageIndices, graphicsQueue); - } - - void AllocateLocalTextureMemory(Texture* texture, const GTSL::StringView name, GAL::TextureUse uses, GAL::FormatDescriptor format, GTSL::Extent3D extent, GAL::Tiling tiling, - GTSL::uint8 mipLevels, RenderAllocation* allocation) - { - GAL::MemoryRequirements memoryRequirements; - texture->GetMemoryRequirements(GetRenderDevice(), &memoryRequirements, uses, format, extent, tiling, mipLevels); - - DeviceMemory memory; uint32 offset = 0; - - localMemoryAllocator.AllocateNonLinearMemory(renderDevice, &memory, allocation, memoryRequirements.Size, &offset); - - texture->Initialize(GetRenderDevice(), name, memory, offset); - } - - void DeallocateLocalTextureMemory(const RenderAllocation allocation) { - localMemoryAllocator.DeallocateNonLinearMemory(renderDevice, allocation); - } - - void AllocateScratchBufferMemory(uint32 size, GAL::BufferUse flags, GPUBuffer* buffer, RenderAllocation* allocation) { - GAL::MemoryRequirements memoryRequirements; - buffer->GetMemoryRequirements(GetRenderDevice(), size, flags, &memoryRequirements); - - DeviceMemory memory; uint32 offset = 0; - - scratchMemoryAllocator.AllocateLinearMemory(renderDevice, &memory, allocation, memoryRequirements.Size, &offset); - - buffer->Initialize(GetRenderDevice(), memoryRequirements, memory, offset); - } - - void DeallocateScratchBufferMemory(const RenderAllocation allocation) { - scratchMemoryAllocator.DeallocateLinearMemory(renderDevice, allocation); - } - - void AllocateLocalBufferMemory(uint32 size, GAL::BufferUse flags, GPUBuffer* buffer, RenderAllocation* allocation) { - GAL::MemoryRequirements memoryRequirements; - buffer->GetMemoryRequirements(GetRenderDevice(), size, flags, &memoryRequirements); - - DeviceMemory memory; uint32 offset = 0; - - localMemoryAllocator.AllocateLinearMemory(renderDevice, &memory, allocation, memoryRequirements.Size, &offset); - - buffer->Initialize(GetRenderDevice(), memoryRequirements, memory, offset); - } - - void DeallocateLocalBufferMemory(const RenderAllocation renderAllocation) { - localMemoryAllocator.DeallocateLinearMemory(renderDevice, renderAllocation); - } - - RenderContextHandle CreateRenderContext(WindowSystem* window_system, WindowSystem::WindowHandle window_handle) { - uint32 renderContextIndex = renderx.GetLength(); - auto& renderContext = renderx.EmplaceBack(); - - renderContext.windowHandle = window_handle; - - return RenderContextHandle(renderContextIndex); - } - - void DestroyRenderContext(const RenderContextHandle render_context_handle) { - auto& renderContext = renderx[render_context_handle()]; - - if (renderContext.renderContext.GetHandle()) - renderContext.renderContext.Destroy(&renderDevice); - - if (renderContext.surface.GetHandle()) - renderContext.surface.Destroy(&renderDevice); - - for (auto& e : renderContext.swapchainTextureViews) { - if (e.GetVkImageView()) - e.Destroy(&renderDevice); - } - } - - RenderDevice* GetRenderDevice() { return &renderDevice; } - const RenderDevice* GetRenderDevice() const { return &renderDevice; } - GPUBuffer GetBuffer(const RenderSystem::BufferHandle buffer_handle) const { - return buffers[buffer_handle()].Buffer; - //TODO: is multi - } - //CommandList* GetTransferCommandBuffer() { return &transferCommandBuffers[currentFrameIndex]; } - - void AddBufferUpdate(CommandListHandle command_list_handle, const BufferHandle source_buffer_handle, const BufferHandle destination_buffer_handle, uint32 source_offset = 0, uint32 destination_offset = 0) { - auto& commandList = commandLists[command_list_handle()]; - if(needsStagingBuffer) - commandList.bufferCopyDatas.EmplaceBack(source_buffer_handle, destination_buffer_handle, source_offset, destination_offset); - } - - struct TextureCopyData { - GPUBuffer SourceBuffer; - Texture DestinationTexture; - - uint32 SourceOffset = 0; - RenderAllocation Allocation; - - GTSL::Extent3D Extent; - - GAL::TextureLayout Layout; - GAL::FormatDescriptor Format; - }; - void AddTextureCopy(CommandListHandle command_list_handle, const TextureCopyData& textureCopyData) { - auto& commandList = commandLists[command_list_handle()]; - commandList.textureCopyDatas.EmplaceBack(textureCopyData); - } - - [[nodiscard]] PipelineCache GetPipelineCache() const; - - [[nodiscard]] const Texture* GetSwapchainTexture(const RenderContextHandle render_context_handle) const { - const auto& renderContext = renderx[render_context_handle()]; - return &renderContext.swapchainTextures[renderContext.imageIndex]; - } - - [[nodiscard]] byte* GetBufferPointer(BufferHandle bufferHandle) const { - return static_cast(buffers[bufferHandle()].Allocation.Data); - } - - [[nodiscard]] GAL::DeviceAddress GetBufferAddress(BufferHandle bufferHandle) const { - return buffers[bufferHandle()].Addresses; - } - - uint32 GetBufferSize(const BufferHandle buffer_handle) const { - return buffers[buffer_handle()].Size; - } - - void DestroyBuffer(const BufferHandle handle) { - --buffers[handle()].references; - } - - CommandList* GetCommandList(const CommandListHandle handle) { return &commandLists[handle()].commandList; } - const CommandList* GetCommandList(const CommandListHandle handle) const { return &commandLists[handle()].commandList; } - - [[nodiscard]] GTSL::Extent2D GetRenderExtent(const RenderContextHandle render_context_handle) const { return renderx[render_context_handle()].renderArea; } - - void onResize(TaskInfo, GTSL::Extent2D extent) {} - - uint32 GetShaderGroupHandleSize() const { return shaderGroupHandleSize; } - uint32 GetShaderGroupBaseAlignment() const { return shaderGroupBaseAlignment; } - uint32 GetShaderGroupHandleAlignment() const { return shaderGroupHandleAlignment; } - - AccelerationStructure GetTopLevelAccelerationStructure(AccelerationStructureHandle topLevelAccelerationStructureIndex) const { - return accelerationStructures[topLevelAccelerationStructureIndex()].TopLevel.AccelerationStructures; - } - - GAL::DeviceAddress GetTopLevelAccelerationStructureAddress(AccelerationStructureHandle topLevelAccelerationStructureIndex) const { - return accelerationStructures[topLevelAccelerationStructureIndex()].TopLevel.AccelerationStructures.GetAddress(GetRenderDevice()); - } - - uint32 GetBufferSubDataAlignment() const { return renderDevice.GetStorageBufferBindingOffsetAlignment(); } - - [[nodiscard]] TextureHandle CreateTexture(GTSL::Range name, GAL::FormatDescriptor formatDescriptor, GTSL::Extent3D extent, GAL::TextureUse textureUses, bool updatable, TextureHandle texture_handle = TextureHandle()); - - void UpdateTexture(const CommandListHandle command_list_handle, const TextureHandle textureHandle); - - //TODO: SELECT DATA POINTER BASED ON STAGING BUFFER NECESSITY - GTSL::Range GetTextureRange(TextureHandle textureHandle) { - const auto& texture = textures[textureHandle()]; - uint32 size = texture.Extent.Width * texture.Extent.Depth * texture.Extent.Height; - size *= texture.format.GetSize(); - return GTSL::Range(size, static_cast(texture.ScratchAllocation.Data)); - } - - GTSL::Range GetTextureRange(TextureHandle textureHandle) const { - const auto& texture = textures[textureHandle()]; - uint32 size = texture.Extent.Width * texture.Extent.Depth * texture.Extent.Height; - size *= texture.format.GetSize(); - return GTSL::Range(size, static_cast(texture.ScratchAllocation.Data)); - } - - const Texture* GetTexture(const TextureHandle textureHandle) const { return &textures[textureHandle()].texture; } - const TextureView* GetTextureView(const TextureHandle textureHandle) const { return &textures[textureHandle()].textureView; } - - void OnRenderEnable(TaskInfo taskInfo, bool oldFocus); - void OnRenderDisable(TaskInfo taskInfo, bool oldFocus); - - GTSL::Result AcquireImage(const RenderContextHandle render_context_handle, const WorkloadHandle workload_handle, WindowSystem* window_system); - - BufferHandle CreateBuffer(uint32 size, GAL::BufferUse flags, bool willWriteFromHost, const BufferHandle buffer_handle); - - AccelerationStructureHandle CreateTopLevelAccelerationStructure(uint32 estimatedMaxInstances) { - uint32 tlasi = accelerationStructures.Emplace(true); - auto& as = accelerationStructures[tlasi]; - auto& t = accelerationStructures[tlasi].TopLevel; - - GAL::Geometry geometry(GAL::GeometryInstances(), GAL::GeometryFlag(), estimatedMaxInstances, 0); - - uint32 size; - - t.AccelerationStructures.GetMemoryRequirements(GetRenderDevice(), GTSL::Range(1, &geometry), accelerationStructureBuildDevice, GAL::AccelerationStructureFlags::PREFER_FAST_TRACE, &size, &as.ScratchSize); - - AllocateLocalBufferMemory(size, GAL::BufferUses::ACCELERATION_STRUCTURE, &t.AccelerationStructureBuffer, &t.AccelerationStructureAllocation); - t.AccelerationStructures.Initialize(&renderDevice, true, t.AccelerationStructureBuffer, size, 0); - - t.SourceInstancesBuffer = CreateBuffer(64 * estimatedMaxInstances, GAL::BufferUses::BUILD_INPUT_READ, true, t.SourceInstancesBuffer); - t.DestinationInstancesBuffer = CreateBuffer(64 * estimatedMaxInstances, GAL::BufferUses::BUILD_INPUT_READ, false, t.DestinationInstancesBuffer); - as.ScratchBuffer = CreateBuffer(1024 * 1204, GAL::BufferUses::BUILD_INPUT_READ | GAL::BufferUses::STORAGE, false, as.ScratchBuffer); - - return AccelerationStructureHandle{ tlasi }; - } - - AccelerationStructureHandle CreateBottomLevelAccelerationStructure(uint32 vertexCount, uint32 vertexSize, uint32 indexCount, GAL::IndexType indexType, BufferHandle vertex_buffer_handle, BufferHandle index_buffer_handle, uint32 vertex_buffer_byte_offset = 0, uint32 index_buffer_byte_offset = 0, bool willUpdate = false, bool willRebuild = false, bool isOpaque = true) { - uint32 blasi = accelerationStructures.Emplace(false); - - auto& as = accelerationStructures[blasi]; - auto& blas = accelerationStructures[blasi].BottomLevel; - - blas.VertexCount = vertexCount; blas.VertexSize = vertexSize; blas.VertexBuffer = vertex_buffer_handle; blas.IndexBuffer = index_buffer_handle; - as.PrimitiveCount = indexCount / 3; blas.VertexByteOffset = vertex_buffer_byte_offset; blas.IndexBufferByteOffset = index_buffer_byte_offset; - - GAL::GeometryTriangles geometryTriangles; //todo: add buffer references, so it can't be deleted while blas build consumes it - geometryTriangles.indexType = indexType; - geometryTriangles.VertexPositionFormat = GAL::ShaderDataType::FLOAT3; - geometryTriangles.MaxVertices = vertexCount; - geometryTriangles.VertexData = GAL::DeviceAddress(); - geometryTriangles.IndexData = GAL::DeviceAddress(); - geometryTriangles.VertexStride = vertexSize; - geometryTriangles.FirstVertex = 0; - - GAL::GeometryFlag geometry_flags; geometry_flags |= isOpaque ? GAL::GeometryFlags::OPAQUE : 0; - GAL::Geometry geometry(geometryTriangles, geometry_flags, indexCount / 3, 0); - - GAL::AccelerationStructureFlag acceleration_structure_flag; - acceleration_structure_flag |= !willRebuild ? GAL::AccelerationStructureFlags::ALLOW_COMPACTION : 0; - acceleration_structure_flag |= !willUpdate ? GAL::AccelerationStructureFlags::ALLOW_COMPACTION : 0; - acceleration_structure_flag |= willUpdate or willRebuild ? GAL::AccelerationStructureFlags::PREFER_FAST_BUILD : 0; - acceleration_structure_flag |= willUpdate ? GAL::AccelerationStructureFlags::ALLOW_UPDATE : 0; - acceleration_structure_flag |= !willUpdate and !willRebuild ? GAL::AccelerationStructureFlags::PREFER_FAST_TRACE : 0; - - uint32 bufferSize; - blas.accelerationStructure.GetMemoryRequirements(GetRenderDevice(), GTSL::Range(1, &geometry), GAL::Device::GPU, acceleration_structure_flag, &bufferSize, &as.ScratchSize); - AllocateLocalBufferMemory(bufferSize, GAL::BufferUses::ACCELERATION_STRUCTURE, &blas.AccelerationStructureBuffer, &blas.AccelerationStructureAllocation); - blas.accelerationStructure.Initialize(GetRenderDevice(), false, blas.AccelerationStructureBuffer, bufferSize, 0); - - as.ScratchBuffer = CreateBuffer(1024 * 1204, GAL::BufferUses::BUILD_INPUT_READ | GAL::BufferUses::STORAGE, true, as.ScratchBuffer); - - return AccelerationStructureHandle{ blasi }; - } - - uint32 CreateAABB(const GTSL::Matrix4& position, const GTSL::Vector3 size) { - //auto volume = CreateBuffer(sizeof(float32) * 6, GAL::BufferUses::BUILD_INPUT_READ, true, false); - //auto bufferDeviceAddress = GetBufferAddress(volume); - //auto bufferPointer = GetBufferPointer(volume); - // - //*(reinterpret_cast(bufferPointer) + 0) = -size; - //*(reinterpret_cast(bufferPointer) + 1) = size; - - //addRayTracingInstance(GAL::Geometry(GAL::GeometryAABB(bufferDeviceAddress, sizeof(float32) * 6), {}, 1, 0), AccelerationStructureBuildData{ 0, {}, {} }); - return 0; - } - - BLASInstanceHandle AddBLASToTLAS(const AccelerationStructureHandle tlash, const AccelerationStructureHandle blash, uint32 instance_custom_index, BLASInstanceHandle instance_handle) { - auto& tlas = accelerationStructures[tlash()].TopLevel; - - uint32 instanceIndex = 0; - - if (instance_handle) { - instanceIndex = instance_handle(); - } else { - if (tlas.freeSlots) { - instanceIndex = tlas.freeSlots.back(); - } - else { - instanceIndex = accelerationStructures[tlash()].PrimitiveCount++; - //TODO: check need resize - } - } - - if (blash) { - const auto& blas = accelerationStructures[blash()].BottomLevel; - GAL::WriteInstance(blas.accelerationStructure, instanceIndex, GAL::GeometryFlags::OPAQUE, GetRenderDevice(), GetBufferPointer(tlas.SourceInstancesBuffer), instance_custom_index, accelerationStructureBuildDevice); - } - - return BLASInstanceHandle(instanceIndex); - } - -#define BE_LOG_IF(cond, text) if(cond) { BE_LOG_WARNING(text); return; } - - void SetInstancePosition(AccelerationStructureHandle topLevel, BLASInstanceHandle instance_handle, const GTSL::Matrix3x4& matrix4) { - BE_LOG_IF(!static_cast(instance_handle), u8"TlAS instance handle is invalid."); - GAL::WriteInstanceMatrix(matrix4, GetBufferPointer(accelerationStructures[topLevel()].TopLevel.SourceInstancesBuffer), instance_handle()); - } - - void SetAccelerationStructureInstanceIndex(AccelerationStructureHandle topLevel, BLASInstanceHandle instance_handle, uint32 custom_index) { - GAL::WriteInstanceIndex(custom_index, GetBufferPointer(accelerationStructures[topLevel()].TopLevel.SourceInstancesBuffer), instance_handle()); - } - - void SetInstanceBindingTableRecordOffset(AccelerationStructureHandle topLevel, BLASInstanceHandle instance_handle, const uint32 offset) { - BE_LOG_IF(instance_handle, u8"TlAS instance handle is invalid."); - GAL::WriteInstanceBindingTableRecordOffset(offset, GetBufferPointer(accelerationStructures[topLevel()].TopLevel.SourceInstancesBuffer), instance_handle()); - } - -private: - bool needsStagingBuffer = true; - - uint8 pipelinedFrames = 0; - - RenderDevice renderDevice; - - bool useHDR = false; - - struct Renderx { - Surface surface; - RenderContext renderContext; - GTSL::Extent2D renderArea, lastRenderArea; - Texture swapchainTextures[MAX_CONCURRENT_FRAMES]; - TextureView swapchainTextureViews[MAX_CONCURRENT_FRAMES]; - WindowSystem::WindowHandle windowHandle; - uint8 imageIndex = 0; - }; - GTSL::StaticVector renderx; - - struct BufferCopyData { - BufferHandle SourceBufferHandle, DestinationBufferHandle; uint32 SourceOffset = 0, DestinationOffset = 0; - }; - - GAL::VulkanQueue graphicsQueue, computeQueue, transferQueue; - - bool breakOnError = false; - TaskHandle resizeHandle; - - struct BufferData { - uint32 Size = 0, Counter = 0; - GAL::BufferUse Flags; - uint32 references = 0; - GPUBuffer Buffer; - RenderAllocation Allocation; - GAL::DeviceAddress Addresses; - }; - GTSL::FixedVector buffers; - - struct AccelerationStructureData { - bool isTop = false; - GTSL::uint32 PrimitiveCount = 0; - BufferHandle ScratchBuffer; - uint32 ScratchSize; - - struct TopLevelAccelerationStructure { - AccelerationStructure AccelerationStructures; - RenderAllocation AccelerationStructureAllocation; - GPUBuffer AccelerationStructureBuffer; - - BufferHandle SourceInstancesBuffer, DestinationInstancesBuffer; - - GTSL::StaticVector freeSlots; - }; - - struct BottomLevelAccelerationStructure { - GPUBuffer AccelerationStructureBuffer; - RenderAllocation AccelerationStructureAllocation; - AccelerationStructure accelerationStructure; - BufferHandle VertexBuffer, IndexBuffer; - GTSL::uint32 VertexCount, VertexSize; - uint32 VertexByteOffset, IndexBufferByteOffset; - }; - - union { - TopLevelAccelerationStructure TopLevel; - BottomLevelAccelerationStructure BottomLevel; - }; - - AccelerationStructureData(bool isTopLevel) : isTop(isTopLevel) { - if (isTop) { - ::new(&TopLevel) TopLevelAccelerationStructure(); - } else { - ::new(&BottomLevel) BottomLevelAccelerationStructure(); - } - } - - AccelerationStructureData(AccelerationStructureData&& other) : isTop(other.isTop), PrimitiveCount(other.PrimitiveCount) { - if(isTop) { - GTSL::Move(&other.TopLevel, &TopLevel); - } else { - GTSL::Move(&other.BottomLevel, &BottomLevel); - } - } - - ~AccelerationStructureData() { - if(isTop) { - GTSL::Destroy(TopLevel); - } else { - GTSL::Destroy(BottomLevel); - } - } - }; - GTSL::FixedVector accelerationStructures; - - struct CommandListData { - CommandListData(const BE::PAR& allocator) : bufferCopyDatas(allocator), textureCopyDatas(allocator) {} - - CommandList commandList; - //Fence Fence; - Synchronizer Semaphore, Fence; - GAL::QueueType Operations; - GAL::PipelineStage PipelineStages; - GTSL::Vector bufferCopyDatas; - GTSL::Vector textureCopyDatas; - }; - GTSL::StaticVector commandLists; - - GAL::Device accelerationStructureBuildDevice; - - uint8 currentFrameIndex = 0; - - GAL::PresentModes swapchainPresentMode; - GAL::FormatDescriptor swapchainFormat; - GAL::ColorSpaces swapchainColorSpace; - - void resize(WindowSystem* window_system, const RenderContextHandle render_context_handle); - - void renderFlush(TaskInfo taskInfo); - - void printError(const GTSL::StringView message, RenderDevice::MessageSeverity messageSeverity) const; - void* allocateApiMemory(void* data, uint64 size, uint64 alignment); - void* reallocateApiMemory(void* data, void* allocation, uint64 size, uint64 alignment); - void deallocateApiMemory(void* data, void* allocation); - - //GTSL::StaticMap, 8> vertexFormats; - - GTSL::Mutex allocationsMutex; - GTSL::HashMap, BE::PersistentAllocatorReference> apiAllocations; - - ScratchMemoryAllocator scratchMemoryAllocator; - LocalMemoryAllocator localMemoryAllocator; - - GTSL::StaticVector pipelineCaches; - - uint32 shaderGroupHandleAlignment = 0, shaderGroupBaseAlignment = 0, shaderGroupHandleSize = 0; - uint32 scratchBufferOffsetAlignment = 0; - - struct TextureComponent { - Texture texture; - TextureView textureView; - RenderAllocation Allocation, ScratchAllocation; - - GAL::FormatDescriptor format; - GAL::TextureUse Uses; - GPUBuffer ScratchBuffer; - GAL::TextureLayout Layout; - GTSL::Extent3D Extent; - }; - GTSL::FixedVector textures; -}; - -class RenderManager : public BE::System -{ -public: - RenderManager(const InitializeInfo& initializeInfo, const char8_t* name) : System(initializeInfo, name) {} - - struct SetupInfo { - ApplicationManager* GameInstance; - RenderSystem* renderSystem; - //RenderState* RenderState; - GTSL::Matrix4 ViewMatrix, ProjectionMatrix; - }; -}; \ No newline at end of file diff --git a/src/ByteEngine/Render/RenderTypes.h b/src/ByteEngine/Render/RenderTypes.h deleted file mode 100644 index af3a83f9..00000000 --- a/src/ByteEngine/Render/RenderTypes.h +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -#include "ByteEngine/Handle.hpp" - -#if (BE_VULKAN) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#elif (BE_DX12) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -MAKE_HANDLE(uint32, RenderModel); - -/** - * \brief Defines the maximum number of frames that can be processed concurrently in the CPU and GPU. - * This might be used to define the number of resources to allocate for those resources that don't allow concurrent use. - * Most of the time the CPU will be working on frame N+1, while the GPU will be working on frame N and each respective unit - * will be modifying and/or reading the resources for the frame they are currently working on. - * - * This number was chosen since we consider that under normal conditions no more than two frames will ever be worked on concurrently. - */ -static constexpr uint8 MAX_CONCURRENT_FRAMES = 3; - -/** - * \brief Handle to a GPU allocation. This handle refers to a GPU local allocation. - */ -struct RenderAllocation -{ - /** - * \brief An opaque ID which MIGHT be used to keep track of some allocator internal data. - */ - uint64 AllocationId = 0; - - /** - * \brief Pointer to a mapped memory section. - */ - void* Data = nullptr; -}; - -#if (BE_VULKAN) -#undef OPAQUE -using Queue = GAL::VulkanQueue; -using Texture = GAL::VulkanTexture; -using Surface = GAL::VulkanSurface; -using GPUBuffer = GAL::VulkanBuffer; -using QueryPool = GAL::VulkanQueryPool; -using GPUPipeline = GAL::VulkanPipeline; -using RenderPass = GAL::VulkanRenderPass; -using TextureSampler = GAL::VulkanSampler; -using TextureView = GAL::VulkanTextureView; -using CommandList = GAL::VulkanCommandList; -using BindingsSet = GAL::VulkanBindingsSet; -using Synchronizer = GAL::VulkanSynchronizer; -using DeviceMemory = GAL::VulkanDeviceMemory; -using RenderDevice = GAL::VulkanRenderDevice; -using BindingsPool = GAL::VulkanBindingsPool; -using RenderContext = GAL::VulkanRenderContext; -using PipelineCache = GAL::VulkanPipelineCache; -using PipelineLayout = GAL::VulkanPipelineLayout; -using BindingsSetLayout = GAL::VulkanBindingsSetLayout; -using AccelerationStructure = GAL::VulkanAccelerationStructure; -#elif (BE_DX12) -using Queue = GAL::DX12Queue; -using Fence = GAL::DX12Fence; -using GPUBuffer = GAL::DX12Buffer; -using Texture = GAL::DX12Texture; -using Surface = GAL::DX12Surface; -using GPUPipeline = GAL::DX12Pipeline; -using GPUSemaphore = GAL::DX12Semaphore; -using QueryPool = GAL::DX12QueryPool; -using RenderPass = GAL::DX12RenderPass; -using TextureSampler = GAL::DX12Sampler; -using TextureView = GAL::DX12TextureView; -using CommandList = GAL::DX12CommandList; -using BindingsSet = GAL::DX12BindingsSet; -using FrameBuffer = GAL::DX12Framebuffer; -using DeviceMemory = GAL::DX12DeviceMemory; -using RenderDevice = GAL::DX12RenderDevice; -using BindingsPool = GAL::DX12BindingsPool; -using RenderContext = GAL::DX12RenderContext; -using PipelineCache = GAL::DX12PipelineCache; -using PipelineLayout = GAL::DX12PipelineLayout; -using BindingsSetLayout = GAL::DX12BindingsSetLayout; -using AccelerationStructure = GAL::DX12AccelerationStructure; -#endif - -constexpr GAL::RenderAPI API = GAL::RenderAPI::VULKAN; - -//inline ShaderStage ConvertShaderStage(const GAL::ShaderStages shaderStage) -//{ -// if constexpr (API == GAL::RenderAPI::VULKAN) -// { -// return GAL::ShaderStageToVulkanShaderStage(shaderStage); -// } -//} \ No newline at end of file diff --git a/src/ByteEngine/Render/RendererAllocator.cpp b/src/ByteEngine/Render/RendererAllocator.cpp deleted file mode 100644 index c01cb778..00000000 --- a/src/ByteEngine/Render/RendererAllocator.cpp +++ /dev/null @@ -1,314 +0,0 @@ -#include "RendererAllocator.h" - -#include "ByteEngine/Debug/Assert.h" - -static constexpr uint8 ALLOC_IS_ISOLATED = 0; -static constexpr uint8 IS_PRE_BLOCK_CONTIGUOUS = 1; -static constexpr uint8 IS_POST_BLOCK_CONTIGUOUS = 2; -static constexpr uint8 IS_PRE_AND_POST_BLOCK_CONTIGUOUS = IS_PRE_BLOCK_CONTIGUOUS | IS_POST_BLOCK_CONTIGUOUS; - -void ScratchMemoryAllocator::Initialize(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference) -{ - bufferMemoryBlocks.EmplaceBack(GetPersistentAllocator()); - //textureMemoryBlocks.EmplaceBack(); - - GPUBuffer scratchBuffer; - - GAL::MemoryRequirements memory_requirements; - scratchBuffer.GetMemoryRequirements(&renderDevice, 1024, - GAL::BufferUses::UNIFORM | GAL::BufferUses::TRANSFER_SOURCE | GAL::BufferUses::INDEX | GAL::BufferUses::VERTEX | GAL::BufferUses::ADDRESS | GAL::BufferUses::SHADER_BINDING_TABLE, - &memory_requirements); - - //bufferMemoryType = memory_requirements.MemoryTypes; - - bufferMemoryBlocks.back().Initialize(renderDevice, ALLOCATION_SIZE, GAL::MemoryTypes::HOST_VISIBLE | GAL::MemoryTypes::HOST_COHERENT, allocatorReference); - - bufferMemoryAlignment = memory_requirements.Alignment; - - scratchBuffer.Destroy(&renderDevice); - - granularity = renderDevice.GetLinearNonLinearGranularity(); -} - -void ScratchMemoryAllocator::AllocateLinearMemory(const RenderDevice& renderDevice, DeviceMemory* deviceMemory, RenderAllocation* renderAllocation, uint32 size, uint32* offset) -{ - BE_ASSERT(GTSL::Byte(size).GetCount() > 0 && GTSL::Byte(size).GetCount() <= ALLOCATION_SIZE.GetCount(), "Invalid size!") - - const auto alignedSize = GTSL::Math::RoundUpByPowerOf2(size, granularity); - - renderAllocation->AllocationId = allocations.GetLength(); - auto& allocation = allocations.EmplaceBack(); - - if constexpr (!SINGLE_ALLOC) - { - for (auto& e : bufferMemoryBlocks) - { - if (e.TryAllocate(deviceMemory, alignedSize, allocation, &renderAllocation->Data)) - { - allocation.Size = alignedSize; - *offset = allocation.Offset; - //BE_LOG_MESSAGE("Allocation. Size: ", renderAllocation->Size, " Offset: ", renderAllocation->Offset); - return; - } - - ++allocation.BlockIndex; - } - - bufferMemoryBlocks.EmplaceBack(GetPersistentAllocator()); - bufferMemoryBlocks.back().Initialize(renderDevice, ALLOCATION_SIZE, GAL::MemoryTypes::HOST_VISIBLE | GAL::MemoryTypes::HOST_COHERENT, GetPersistentAllocator()); - bufferMemoryBlocks.back().Allocate(deviceMemory, alignedSize, allocation, &renderAllocation->Data); - } - else - { - deviceMemory->Initialize(&renderDevice, GAL::AllocationFlags::DEVICE_ADDRESS, alignedSize, renderDevice.FindNearestMemoryType(GAL::MemoryTypes::HOST_VISIBLE | GAL::MemoryTypes::HOST_COHERENT)); - - renderAllocation->Data = deviceMemory->Map(&renderDevice, alignedSize, 0); - } - - allocation.Size = alignedSize; - - //BE_LOG_MESSAGE("Allocation. Size: ", renderAllocation->Size, " Offset: ", renderAllocation->Offset) -} - -void ScratchMemoryAllocator::Free(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference) -{ - for (auto& e : bufferMemoryBlocks) { e.Free(renderDevice, allocatorReference); } -} - -void MemoryBlock::Initialize(const RenderDevice& renderDevice, GTSL::Byte size, GAL::MemoryType memoryType, const BE::PersistentAllocatorReference& allocatorReference) -{ - deviceMemory.Initialize(&renderDevice, GAL::AllocationFlags::DEVICE_ADDRESS, size.GetCount(), renderDevice.FindNearestMemoryType(memoryType)); - - if (static_cast(memoryType & GAL::MemoryTypes::HOST_VISIBLE)) { - mappedMemory = deviceMemory.Map(&renderDevice, size.GetCount(), 0); - } - - freeSpaces.EmplaceBack(size.GetCount(), 0); -} - -void MemoryBlock::Free(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference) -{ - if (mappedMemory) { - deviceMemory.Unmap(&renderDevice); - } - - deviceMemory.Destroy(&renderDevice); -} - -bool MemoryBlock::TryAllocate(DeviceMemory* deviceMemory, const uint32 size, AllocationInfo& allocationInfo, void** data) -{ - uint32 i = 0; - - for (auto& e : freeSpaces) - { - if (e.Size >= size) - { - *data = static_cast(mappedMemory) + e.Offset; - allocationInfo.Offset = e.Offset; - *deviceMemory = this->deviceMemory; - - if (e.Size == size) - { - freeSpaces.Pop(i); - return true; - } - - e.Size -= size; - e.Offset += size; - - return true; - } - - ++i; - } - - return false; -} - -void MemoryBlock::Allocate(DeviceMemory* deviceMemory, const uint32 size, AllocationInfo& allocationInfo, void** data) -{ - *data = static_cast(mappedMemory) + freeSpaces[0].Offset; - allocationInfo.Offset = freeSpaces[0].Offset; - *deviceMemory = this->deviceMemory; - - freeSpaces[0].Size -= size; - freeSpaces[0].Offset += size; -} - -void MemoryBlock::Deallocate(const uint32 size, const uint32 offset, AllocationInfo id) -{ - uint8 info = 0; uint32 i = 0; - - if (freeSpaces[0].Offset > offset) - { - if(size + offset == freeSpaces[0].Offset) //is post block contiguous - { - freeSpaces[i].Size += size; - freeSpaces[i].Offset = offset; - return; - } - - //freeSpaces.Insert(i, Space(size, offset)); - return; - } - - ++i; - - for(; i < freeSpaces.GetLength(); ++i) - { - if (freeSpaces[i].Offset > offset) - { - size + offset == freeSpaces[i].Offset ? info |= IS_POST_BLOCK_CONTIGUOUS : 0; - break; - } - } - - freeSpaces[i - 1].Offset + freeSpaces[i - 1].Size == offset ? info |= IS_PRE_BLOCK_CONTIGUOUS : 0; - - switch (info) - { - case ALLOC_IS_ISOLATED: - //freeSpaces.Insert(i, Space(size, offset)); - return; - - case IS_PRE_BLOCK_CONTIGUOUS: - freeSpaces[i - 1].Size += size; - return; - - case IS_POST_BLOCK_CONTIGUOUS: - freeSpaces[i].Size += size; - freeSpaces[i].Offset = offset; - return; - - case IS_PRE_AND_POST_BLOCK_CONTIGUOUS: - freeSpaces[i - 1].Size += freeSpaces[i].Size + size; - freeSpaces.Pop(i); - return; - - default: BE_ASSERT(false, "Wa happened?") - } -} - - -void LocalMemoryAllocator::Initialize(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference) -{ - bufferMemoryBlocks.EmplaceBack(GetPersistentAllocator()); - textureMemoryBlocks.EmplaceBack(GetPersistentAllocator()); - - Texture dummyTexture; - - GAL::MemoryRequirements imageMemoryRequirements; - dummyTexture.GetMemoryRequirements(&renderDevice, &imageMemoryRequirements, GAL::TextureUses::TRANSFER_DESTINATION, GAL::FORMATS::RGBA_I8, - { 1280, 720, 1 }, GAL::Tiling::OPTIMAL, 1); - - GPUBuffer dummyBuffer; - - GAL::MemoryRequirements bufferMemoryRequirements; - dummyBuffer.GetMemoryRequirements(&renderDevice, 1024, - GAL::BufferUses::UNIFORM | GAL::BufferUses::TRANSFER_DESTINATION | GAL::BufferUses::INDEX | GAL::BufferUses::VERTEX | GAL::BufferUses::ADDRESS | GAL::BufferUses::SHADER_BINDING_TABLE | GAL::BufferUses::ACCELERATION_STRUCTURE | GAL::BufferUses::BUILD_INPUT_READ, - &bufferMemoryRequirements); - - //bufferMemoryType = bufferMemoryRequirements.MemoryTypes; - //textureMemoryType = imageMemoryRequirements.MemoryTypes; - - bufferMemoryBlocks.back().Initialize(renderDevice, ALLOCATION_SIZE, GAL::MemoryTypes::GPU, allocatorReference); - textureMemoryBlocks.back().Initialize(renderDevice, ALLOCATION_SIZE, GAL::MemoryTypes::GPU, allocatorReference); - - dummyBuffer.Destroy(&renderDevice); - dummyTexture.Destroy(&renderDevice); - - bufferMemoryAlignment = bufferMemoryRequirements.Alignment; - textureMemoryAlignment = imageMemoryRequirements.Alignment; - - granularity = renderDevice.GetLinearNonLinearGranularity(); -} - -void LocalMemoryAllocator::Free(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference) -{ - for(auto& e : bufferMemoryBlocks) { e.Free(renderDevice, allocatorReference); } - for(auto& e : textureMemoryBlocks) { e.Free(renderDevice, allocatorReference); } -} - -void LocalMemoryAllocator::AllocateLinearMemory(const RenderDevice& renderDevice, DeviceMemory* deviceMemory, RenderAllocation* renderAllocation, uint32 size, uint32* offset) -{ - BE_ASSERT(size > 0 && size <= ALLOCATION_SIZE.GetCount(), "Invalid size!") - - const auto alignedSize = GTSL::Math::RoundUpByPowerOf2(size, granularity); - - renderAllocation->AllocationId = allocations.GetLength(); - auto& allocation = allocations.EmplaceBack(); - - void* dummy; - - if constexpr (!SINGLE_ALLOC) - { - for (auto& block : bufferMemoryBlocks) - { - //TODO: GET BLOCK INFO - if (block.TryAllocate(deviceMemory, alignedSize, allocation, &dummy)) - { - allocation.Size = alignedSize; - *offset = allocation.Offset; - - //BE_LOG_MESSAGE("Allocation. Size: ", renderAllocation->Size, " Offset: ", renderAllocation->Offset); - - return; - } - - ++allocation.BlockIndex; - } - - bufferMemoryBlocks.EmplaceBack(GetPersistentAllocator()); - bufferMemoryBlocks.back().Initialize(renderDevice, ALLOCATION_SIZE, GAL::MemoryTypes::GPU, GetPersistentAllocator()); - bufferMemoryBlocks.back().Allocate(deviceMemory, alignedSize, allocation, &dummy); - } - else - { - deviceMemory->Initialize(&renderDevice, GAL::AllocationFlags::DEVICE_ADDRESS, alignedSize, renderDevice.FindNearestMemoryType(GAL::MemoryTypes::GPU)); - } - - allocation.Size = alignedSize; - *offset = allocation.Offset; - - //BE_LOG_MESSAGE("Allocation. Size: ", renderAllocation->Size, " Offset: ", renderAllocation->Offset); -} - -void LocalMemoryAllocator::AllocateNonLinearMemory(const RenderDevice& renderDevice, DeviceMemory* deviceMemory, RenderAllocation* renderAllocation, uint32 size, uint32* offset) -{ - const auto alignedSize = GTSL::Math::RoundUpByPowerOf2(size, granularity); - - renderAllocation->AllocationId = allocations.GetLength(); - auto& allocation = allocations.EmplaceBack(); - - void* dummy; - - for (auto& block : textureMemoryBlocks) - { - //TODO: GET BLOCK INFO - if (block.TryAllocate(deviceMemory, alignedSize, allocation, &dummy)) - { - allocation.Size = alignedSize; - *offset = allocation.Offset; - return; - } - - ++allocation.BlockIndex; - } - - textureMemoryBlocks.EmplaceBack(GetPersistentAllocator()); - textureMemoryBlocks.back().Initialize(renderDevice, ALLOCATION_SIZE, GAL::MemoryTypes::GPU, GetPersistentAllocator()); - textureMemoryBlocks.back().Allocate(deviceMemory, alignedSize, allocation, &dummy); - - //{ - // DeviceMemory::CreateInfo memory_create_info; - // memory_create_info.RenderDevice = &renderDevice; - // memory_create_info.Name = "Texture GPU Memory Block"; - // memory_create_info.Size = alignedSize; - // memory_create_info.MemoryType = renderDevice.FindMemoryType(textureMemoryType, MemoryType::GPU); - // *deviceMemory = DeviceMemory(memory_create_info); - //} - - allocation.Size = alignedSize; - *offset = allocation.Offset; -} - diff --git a/src/ByteEngine/Render/RendererAllocator.h b/src/ByteEngine/Render/RendererAllocator.h deleted file mode 100644 index 3498a13e..00000000 --- a/src/ByteEngine/Render/RendererAllocator.h +++ /dev/null @@ -1,132 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" -#include "ByteEngine/Object.h" -#include "ByteEngine/Application/AllocatorReferences.h" - -#include -#include -#include - -#include "RenderTypes.h" - -class ScratchMemoryAllocator; - -struct Space -{ - Space() = default; - - Space(const uint32 size, const uint32 offset) : Size(size), Offset(offset) - { - } - - uint32 Size = 0; - uint32 Offset = 0; -}; - -struct AllocationInfo : Space -{ - uint32 BlockIndex = 0; - uint32 BlockInfo = 0; - - AllocationInfo() = default; -}; - -struct MemoryBlock -{ - MemoryBlock(const BE::PAR& allocator) : freeSpaces(32, allocator) {} - - void Initialize(const RenderDevice& renderDevice, GTSL::Byte size, GAL::MemoryType memoryType, const BE::PersistentAllocatorReference& - allocatorReference); - void Free(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference); - - bool TryAllocate(DeviceMemory* deviceMemory, uint32 size, AllocationInfo& allocationInfo, void** data); - void Allocate(DeviceMemory* deviceMemory, uint32 size, AllocationInfo& allocationInfo, void** data); - void Deallocate(uint32 size, uint32 offset, AllocationInfo id); - -private: - DeviceMemory deviceMemory; - void* mappedMemory = nullptr; - - GTSL::Vector freeSpaces; -}; - -class LocalMemoryAllocator : public Object -{ -public: - LocalMemoryAllocator() : Object(u8"LocalMemoryAllocator") {} - - void Initialize(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference); - - void Free(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference); - - void AllocateLinearMemory(const RenderDevice& renderDevice, DeviceMemory* deviceMemory, RenderAllocation* renderAllocation, uint32 size, uint32* offset); - - void DeallocateLinearMemory(const RenderDevice&, const RenderAllocation renderAllocation) - { - if constexpr (!SINGLE_ALLOC) - { - auto& allocation = allocations[renderAllocation.AllocationId]; - bufferMemoryBlocks[allocation.BlockIndex].Deallocate(GTSL::Math::RoundUpByPowerOf2(allocation.Size, granularity), allocation.Offset, allocation); - } - } - - void AllocateNonLinearMemory(const RenderDevice& renderDevice, DeviceMemory* deviceMemory, RenderAllocation* renderAllocation, uint32 size, uint32* offset); - void DeallocateNonLinearMemory(const RenderDevice&, const RenderAllocation renderAllocation) - { - if constexpr (!SINGLE_ALLOC) - { - auto& allocation = allocations[renderAllocation.AllocationId]; - textureMemoryBlocks[allocation.BlockIndex].Deallocate(GTSL::Math::RoundUpByPowerOf2(allocation.Size, granularity), allocation.Offset, allocation); - } - } - -private: - inline static GTSL::Byte ALLOCATION_SIZE{ GTSL::MegaByte(128) }; - - static constexpr bool SINGLE_ALLOC = true; - - uint32 bufferMemoryType = 0, textureMemoryType = 0; - - - GTSL::StaticVector allocations; - - GTSL::StaticVector bufferMemoryBlocks; - GTSL::StaticVector textureMemoryBlocks; - uint32 bufferMemoryAlignment = 0, textureMemoryAlignment = 0; - GTSL::uint32 granularity; -}; - -class ScratchMemoryAllocator : public Object -{ -public: - ScratchMemoryAllocator() : Object(u8"ScratchMemoryAllocator") {} - - void Initialize(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference); - - void AllocateLinearMemory(const RenderDevice& renderDevice, DeviceMemory* deviceMemory, RenderAllocation* renderAllocation, uint32 size, uint32* offset); - void DeallocateLinearMemory(const RenderDevice&, const RenderAllocation renderAllocation) - { - if constexpr (!SINGLE_ALLOC) - { - auto& allocation = allocations[renderAllocation.AllocationId]; - bufferMemoryBlocks[allocation.BlockIndex].Deallocate(GTSL::Math::RoundUpByPowerOf2(allocation.Size, granularity), allocation.Offset, allocation); - } - } - - void Free(const RenderDevice& renderDevice, const BE::PersistentAllocatorReference& allocatorReference); - -private: - inline static GTSL::Byte ALLOCATION_SIZE{ GTSL::MegaByte(128) }; - - static constexpr bool SINGLE_ALLOC = true; - - uint32 bufferMemoryType = 0; - - uint32 bufferMemoryAlignment = 0; - - GTSL::uint32 granularity; - - GTSL::StaticVector allocations; - GTSL::StaticVector bufferMemoryBlocks; -}; \ No newline at end of file diff --git a/src/ByteEngine/Render/ShaderGenerator.h b/src/ByteEngine/Render/ShaderGenerator.h deleted file mode 100644 index a7c1de0a..00000000 --- a/src/ByteEngine/Render/ShaderGenerator.h +++ /dev/null @@ -1,1467 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "ByteEngine/Application/AllocatorReferences.h" - -//Object types are always stored as the interface types, not the end target's name -struct StructElement { - StructElement() = default; - StructElement(const GTSL::StringView t, const GTSL::StringView n) : Type(t), Name(n) {} - StructElement(const GTSL::StringView t, const GTSL::StringView n, const GTSL::StringView dv) : Type(t), Name(n), DefaultValue(dv) {} - - GTSL::StaticString<86> Type, Name, DefaultValue; -}; - -struct ShaderNode { - enum class Type : uint8 { - NONE, ID, OP, LITERAL, LPAREN, RPAREN, LBRACKET, RBRACKET, LBRACE, RBRACE, DOT, COMMA, COLON, SEMICOLON, HASH, EXCLAMATION, LESS_THAN, GREATER_THAN, AND - } ValueType; - - GTSL::StaticString<64> Name; - - ShaderNode() = default; - ShaderNode(Type t, const GTSL::StringView na) : ValueType(t), Name(na) {} - - auto GetName() const -> GTSL::StringView { - return Name; - } -}; - -bool IsAnyOf(const auto& a, const auto&... elems) { - return ((a == elems) or ...); -} - -enum class Class { VERTEX, SURFACE, COMPUTE, RENDER_PASS, RAY_GEN, CLOSEST_HIT, MISS }; - -/** - * \brief Turns code into a stream of tokens, every first dimension is an statement, all elements in the array's second dimension is a token. Can only parse a functions content, no language constructs (classes, enums, descriptors, etc...) - * \param code String containing code to tokenize. - * \param statements Array container for statements. - */ -void tokenizeCode(const GTSL::StringView code, auto& statements, const auto& allocator) { - tokenizeCode(code, statements); -} - -void tokenizeCode(const GTSL::StringView string, auto& statements) { - auto parseLine = [&](const GTSL::StringView code) { - if(GTSL::IsIn(code, u8"//")) { return; } - - for (uint32 i = 0; i < code.GetCodepoints(); ++i) { - auto c = code[i]; - - ShaderNode::Type type; - - GTSL::StaticString<64> str; - - if (GTSL::IsSymbol(c) and c != U'_') { - if (c == U'(') { - type = ShaderNode::Type::LPAREN; - } - else if (c == U')') { - type = ShaderNode::Type::RPAREN; - } - else if (c == U'[') { - type = ShaderNode::Type::LBRACKET; - } - else if (c == U']') { - type = ShaderNode::Type::RBRACKET; - } - else if (c == U'{') { - type = ShaderNode::Type::LBRACE; - } - else if (c == U'}') { - type = ShaderNode::Type::RBRACE; - } - else if (c == U'.') { - type = ShaderNode::Type::DOT; - } - else if (c == U',') { - type = ShaderNode::Type::COMMA; - } - else if (c == U':') { - type = ShaderNode::Type::COLON; - } - else if (c == U';') { - type = ShaderNode::Type::SEMICOLON; - } - else if (c == U'#') { - type = ShaderNode::Type::HASH; - } - else if (c == U'!') { - type = ShaderNode::Type::EXCLAMATION; - } - else if (c == U'<') { - type = ShaderNode::Type::LESS_THAN; - } - else if (c == U'>') { - type = ShaderNode::Type::GREATER_THAN; - } - else if (IsAnyOf(c, U'=', U'*', U'+', U'-', U'/', U'%', U'^', U'&', U'|', U'~', U'?')) { - type = ShaderNode::Type::OP; - } - - str += c; - } - else if (GTSL::IsNumber(c)) { - while (GTSL::IsLetter(code[i]) or GTSL::IsNumber(code[i]) or code[i] == U'.') { - str += code[i]; - ++i; - } - - type = ShaderNode::Type::LITERAL; - - --i; - } - else if (GTSL::IsLetter(code[i]) or code[i] == u8'_') { - while (GTSL::IsLetter(code[i]) or GTSL::IsNumber(code[i]) or code[i] == U'_') { - str += code[i]; - ++i; - } - - if (code[i] == U'*') { str += U'*'; ++i; } - - type = ShaderNode::Type::ID; - - --i; - } else { - //anything else, new line, null, space, skip - continue; - } - - statements.EmplaceBack(type, str); - } - }; - - GTSL::ForEachLine(string, parseLine); -} - -struct GPipeline : Object { - struct ElementHandle { - constexpr ElementHandle() = default; - - explicit constexpr ElementHandle(const uint32 n) : Handle(n) { - - } - - uint32 Handle = 0xFFFFFFFF; - }; - - inline static const ElementHandle GLOBAL_SCOPE{ 1u }; - - struct FunctionDefinition { - FunctionDefinition(const BE::PAR& allocator) : Tokens(16, allocator) {} - - GTSL::StaticString<64> Return, Name; - GTSL::StaticVector Parameters; - GTSL::Vector Tokens; - bool Inline = false; - - //Every function gets assigned an id which is unique per pipeline - //It aides in identifying functions when dealing with overloads, which share name and thus does not allow to uniquely identify them - //Id can also be used to access the element which represents this function - uint32 Id = 0; - }; - - struct LanguageElement { - LanguageElement(const BE::TAR& allocator) : map(16, allocator), symbols(4, allocator) {} - - ElementHandle Parent; - - enum class ElementType { - NONE, MODEL, SCOPE, KEYWORD, TYPE, STRUCT, MEMBER, FUNCTION, DEDUCTION_GUIDE, DISABLED, SHADER, CONSTANT, SHARED - } Type = ElementType::NONE; - - GTSL::HashMap, BE::TAR> map; - GTSL::Vector symbols; - GTSL::StaticString<64> Name; - uint16 Level = 0; - uint32 Reference = 0xFFFFFFFF; - }; - - - struct StructData { - uint8 GenerationType = 2; - bool IsConst = false; - }; - - GPipeline() : Object(u8"GPipeline"), elements(32, BE::TAR(u8"Shader")), deductionGuides(16, BE::TAR(u8"Shader")), members(32, BE::TAR(u8"Shader")), structs(64, BE::TAR(u8"Shader")), Functions(128, BE::TAR(u8"Shader")) { - auto handle = elements.Emplace(0, BE::TAR(u8"Shader")); - auto& e = elements[handle]; - e.Type = LanguageElement::ElementType::SCOPE; - e.Name = u8"global"; - - add(GLOBAL_SCOPE, u8"=", LanguageElement::ElementType::FUNCTION); - add(GLOBAL_SCOPE, u8"+", LanguageElement::ElementType::FUNCTION); - add(GLOBAL_SCOPE, u8"-", LanguageElement::ElementType::FUNCTION); - add(GLOBAL_SCOPE, u8"*", LanguageElement::ElementType::FUNCTION); - add(GLOBAL_SCOPE, u8"/", LanguageElement::ElementType::FUNCTION); - add(GLOBAL_SCOPE, u8"return", LanguageElement::ElementType::KEYWORD); - add(GLOBAL_SCOPE, u8"float32", LanguageElement::ElementType::TYPE); - //add(ElementHandle(), u8"vec2f", LanguageElement::ElementType::TYPE); - //add(ElementHandle(), u8"vec3f", LanguageElement::ElementType::TYPE); - //add(ElementHandle(), u8"vec4f", LanguageElement::ElementType::TYPE); - //add(ElementHandle(), u8"vec2u", LanguageElement::ElementType::TYPE); - } - - uint32 GetLevel(const ElementHandle element_handle) const { return elements[element_handle.Handle].Level; } - - auto GetElement(const ElementHandle element_handle) -> LanguageElement& { return elements[element_handle.Handle]; } - const LanguageElement& GetElement(const ElementHandle element_handle) const { return elements[element_handle.Handle]; } - - auto& GetFunctionTokens(const ElementHandle element_handle) { - return Functions[GetElement(element_handle).Reference].Tokens; - } - -private: - ElementHandle add(ElementHandle parent, const GTSL::StringView name, LanguageElement::ElementType type) { - auto handle = elements.Emplace(parent.Handle, BE::TAR(u8"Shader")); - elements[parent.Handle].map.Emplace(name).EmplaceBack(handle); - elements[parent.Handle].symbols.EmplaceBack(handle); - auto& e = elements[handle]; - e.Type = type; e.Name = name; - if(parent.Handle != 0xFFFFFFFF) { - e.Level = GetElement(parent).Level + 1; - e.Parent = parent; - } - return ElementHandle(handle); - } - - ElementHandle addConditional(ElementHandle parent, const GTSL::StringView name, LanguageElement::ElementType type) { - auto& parentElement = elements[parent.Handle]; - - if(parentElement.map.Find(name)) { return ElementHandle(parentElement.map[name].back()); } - - return add(parent, name, type); - } - - ElementHandle addMultiple(ElementHandle parent, const GTSL::StringView name, LanguageElement::ElementType type) { - auto handle = elements.Emplace(parent.Handle, BE::TAR(u8"Shader")); - elements[parent.Handle].map.TryEmplace(name).Get().EmplaceBack(handle); - elements[parent.Handle].symbols.EmplaceBack(handle); - auto& e = elements[handle]; - e.Type = type; e.Name = name; - if (parent.Handle != 0xFFFFFFFF) { - e.Level = GetElement(parent).Level + 1; - e.Parent = parent; - } - return ElementHandle(handle); - } - -public: - auto TryGetElement(ElementHandle parent, const GTSL::StringView name) -> GTSL::Result { - if (auto res = elements[parent.Handle].map.TryGet(name)) { - return { elements[res.Get().back()], true }; - } - else { - return { elements[0], false }; - } - } - - auto TryGetElement(ElementHandle parent, const GTSL::StringView name) const -> GTSL::Result { - if (auto res = elements[parent.Handle].map.TryGet(name)) { - return { elements[res.Get().back()], true }; - } - else { - return { elements[0], false }; - } - } - - auto TryGetElementHandle(ElementHandle parent, const GTSL::StringView name) const -> GTSL::Result { - if (auto res = elements[parent.Handle].map.TryGet(name)) { - return { ElementHandle(res.Get().back()), true }; - } - - return { ElementHandle(GLOBAL_SCOPE), false }; - } - - auto TryGetElement(const GTSL::Range parents, const GTSL::StringView name) -> GTSL::Result { - for (uint32 i = parents.ElementCount() - 1, j = 0; j < parents.ElementCount(); --i, ++j) { - if (auto res = TryGetElement(parents[i], name)) { - return res; - } - } - - return { elements[0], false }; - } - - auto TryGetElement(const GTSL::Range parents, const GTSL::StringView name) const -> GTSL::Result { - for (uint32 i = parents.ElementCount() - 1, j = 0; j < parents.ElementCount(); --i, ++j) { - if (auto res = TryGetElement(parents[i], name)) { - return res; - } - } - - return { elements[0], false }; - } - - auto TryGetElementHandle(const GTSL::Range parents, const GTSL::StringView name) const -> GTSL::Result { - for (uint32 i = parents.ElementCount() - 1, j = 0; j < parents.ElementCount(); --i, ++j) { - if (auto res = TryGetElementHandle(parents[i], name)) { - return res; - } - } - - return { ElementHandle(GLOBAL_SCOPE), false }; - } - - auto TryGetElementHandle(const GTSL::Range parents, const ElementHandle current_scope, const GTSL::StringView name) const -> GTSL::Result { - for (uint32 i = parents.ElementCount() - 1, j = 0; j < parents.ElementCount(); --i, ++j) { - if (auto res = TryGetElementHandle(parents[i], name); res && GetLevel(res.Get()) <= GetLevel(current_scope)) { - return res; - } - } - - return { ElementHandle(GLOBAL_SCOPE), false }; - } - - auto GetChildren(const ElementHandle element_handle) const { - GTSL::StaticVector children; - for (auto& e : GetElement(element_handle).symbols) { - children.EmplaceBack(e); - } - - return children; - } - - ElementHandle DeclareFunction(ElementHandle parent, const GTSL::StringView returnType, const GTSL::StringView name, const GTSL::Range parameters) { - auto handle = addMultiple(parent, name, LanguageElement::ElementType::FUNCTION); - auto& element = GetElement(handle); - - element.Reference = Functions.GetLength(); - - auto& function = Functions.EmplaceBack(GetPersistentAllocator()); - function.Name = name; function.Return = returnType; function.Parameters = parameters; - function.Id = handle.Handle; - return handle; - } - - ElementHandle DeclareFunction(ElementHandle parent, const GTSL::StringView returnType, const GTSL::StringView name, const GTSL::Range parameters, const GTSL::StringView code) { - auto handle = addMultiple(parent, name, LanguageElement::ElementType::FUNCTION); - auto& element = GetElement(handle); - - element.Reference = Functions.GetLength(); - - auto& function = Functions.EmplaceBack(GetPersistentAllocator()); - function.Name = name; function.Return = returnType; function.Parameters = parameters; - function.Id = handle.Handle; - tokenizeCode(code, function.Tokens, GetPersistentAllocator()); - return handle; - } - - - auto& GetFunction(ElementHandle element_handle) { - return Functions[elements[element_handle.Handle].Reference]; - } - - auto& GetFunction(ElementHandle element_handle) const { - return Functions[elements[element_handle.Handle].Reference]; - } - - void AddCodeToFunction(const ElementHandle function_handle, const GTSL::StringView code) { - auto& main = Functions[GetElement(function_handle).Reference]; - tokenizeCode(code, main.Tokens); - } - - void AddCodeToFunction(const ElementHandle function_handle, const GTSL::Range tokens) { - auto& function = GetFunction(function_handle); - for(auto& e : tokens) { // TODO: don't - function.Tokens.EmplaceBack(e); - } - } - - auto GetFunctionOverloads(const ElementHandle parent, const GTSL::StringView name) const { - auto& element = GetElement(parent); - - GTSL::StaticVector overloads; - - for (auto& e : element.map[name]) { - overloads.EmplaceBack(elements[e].Reference); - } - - return overloads; - } - - auto GetFunctionOverloads(GTSL::Range parents, const GTSL::StringView name) const { - for (auto& p : parents) { - if (auto res = TryGetElement(p, name)) { - GTSL::StaticVector overloads; - - for (auto e : GetElement(p).map[name]) { - overloads.EmplaceBack(e); - } - - return overloads; - } - } - - return GTSL::StaticVector(); - } - - ElementHandle DeclareStruct(const ElementHandle parent, const GTSL::StringView name, GTSL::Range members) { - auto handle = add(parent, name, LanguageElement::ElementType::STRUCT); - auto& element = GetElement(handle); - - element.Reference = structs.GetLength(); - - auto& strct = structs.EmplaceBack(); - - strct.GenerationType = 2; - - for (auto& e : members) { - DeclareVariable(handle, e); - } - - return handle; - } - - void SetMakeStruct(const ElementHandle element_handle) { - GetStruct(element_handle).GenerationType = 0; - } - - void SetMakeBoth(const ElementHandle element_handle) { - GetStruct(element_handle).GenerationType = 2; - } - - void SetAsConst(const ElementHandle element_handle) { - GetStruct(element_handle).IsConst = true; - } - - void DeclareShared(const ElementHandle parent, const StructElement shared) { - auto handle = add(parent, shared.Name, LanguageElement::ElementType::SHARED); - auto& element = GetElement(handle); - element.Reference = members.GetLength(); - members.EmplaceBack(shared); - } - - void DeclareConstant(const ElementHandle parent, const StructElement constant) { - auto handle = add(parent, constant.Name, LanguageElement::ElementType::CONSTANT); - auto& element = GetElement(handle); - element.Reference = members.GetLength(); - members.EmplaceBack(constant); - } - - ElementHandle DeclareScope(const ElementHandle parentHandle, const GTSL::StringView name) { - return add(parentHandle, name, LanguageElement::ElementType::SCOPE); - } - - ElementHandle TryDeclareScope(const ElementHandle parentHandle, const GTSL::StringView name) { - return addConditional(parentHandle, name, LanguageElement::ElementType::SCOPE); - } - - ElementHandle DeclareShader(const ElementHandle parentHandle, const GTSL::StringView name) { - auto handle = addMultiple(parentHandle, name, LanguageElement::ElementType::SHADER); - auto& element = GetElement(handle); - return handle; - } - - ElementHandle DeclareVariable(const ElementHandle parentHandle, const StructElement member) { - auto handle = add(parentHandle, member.Name, LanguageElement::ElementType::MEMBER); - elements[handle.Handle].Reference = members.GetLength(); - members.EmplaceBack(member); - return { handle }; - } - - void AddMemberDeductionGuide(const ElementHandle start_cope, const GTSL::StringView interface_name, const GTSL::Range access_chain) { - auto& element = GetElement(add(start_cope, interface_name, LanguageElement::ElementType::DEDUCTION_GUIDE)); - element.Reference = deductionGuides.GetLength(); - deductionGuides.EmplaceBack().PushBack(access_chain); - } - - GTSL::Range GetMemberDeductionGuide(const ElementHandle member_deduction_guide) const { - return GTSL::Range(deductionGuides[GetElement(member_deduction_guide).Reference]); - } - - StructElement GetMember(ElementHandle element_handle) const { - return members[GetElement(element_handle).Reference]; - } - - GTSL::StringView GetName(const ElementHandle element_handle) const { - return GetElement(element_handle).Name; - } - - ElementHandle GetElementHandle(ElementHandle parent_handle, const GTSL::StringView name) const { - return ElementHandle(elements[parent_handle.Handle].map.At(name).back()); - } - - StructData& GetStruct(const ElementHandle element_handle) { - return structs[GetElement(element_handle).Reference]; - } - - const StructData& GetStruct(const ElementHandle element_handle) const { - return structs[GetElement(element_handle).Reference]; - } - - GTSL::StaticVector GetAccessChain(const ElementHandle source) const { - GTSL::StaticVector chain; - - auto g = [&](ElementHandle t, auto&& self) -> void { - if(t.Handle == 0xFFFFFFFF) { return; } - self(GetElement(t).Parent, self); - chain.EmplaceBack(t); - }; - - g(source, g); - - return chain; - } - - // Returns an array of elements that match the desired type - // The return order is by scope - auto GetElements(LanguageElement::ElementType element_type, GTSL::Range scopes) const { - GTSL::StaticVector foundElements; - - for(auto& scope : scopes) { - auto& element = elements[scope.Handle]; - for(const auto childIterator : element.symbols) { - auto& child = elements[childIterator]; - - if(child.Type != element_type) { continue; } - - foundElements.EmplaceBack(ElementHandle(childIterator)); - } - } - - return foundElements; - } - - void MakeJSON(auto& string, const GTSL::Range scopes) const { - GTSL::JSONSerializer serializer = GTSL::MakeSerializer(string); - - GTSL::StartArray(serializer, string, u8"structs"); - - for (auto& e : scopes) { - GTSL::StaticString<512> shaderName; - - { - auto g = [&](ElementHandle t, auto&& self) -> void { - if(t.Handle == 0xFFFFFFFF) { return; } - - self(GetElement(t).Parent, self); - - shaderName += GetElement(t).Name; - shaderName += u8"."; - }; - - g(e, g); - } - - for (auto& r : GetElements(LanguageElement::ElementType::STRUCT, { e })) { - auto& element = GetElement(r); - - GTSL::StartObject(serializer, string); - - StructData& structData = GetStruct(r); - - GTSL::Insert(serializer, string, u8"name", shaderName + element.Name); - - GTSL::StartArray(serializer, string, u8"members"); - - for (auto& c : GetChildren(r)) { - GTSL::StartObject(serializer, string); - const auto& structMember = GetMember(c); - GTSL::Insert(serializer, string, u8"type", structMember.Type); - GTSL::Insert(serializer, string, u8"name", structMember.Name); - GTSL::EndObject(serializer, string); - } - - GTSL::EndArray(serializer, string); - - GTSL::EndObject(serializer, string); - } - } - - GTSL::EndArray(serializer, string); - - GTSL::StartObject(serializer, string, u8"pushConstant"); - - auto pushConstantElementHandleSearch = TryGetElementHandle(scopes, u8"pushConstantBlock"); - - GTSL::StartArray(serializer, string, u8"members"); - - for (auto& c : GetChildren(pushConstantElementHandleSearch.Get())) { - GTSL::StartObject(serializer, string); - const auto& structMember = GetMember(c); - - auto typeName = structMember.Type; - RTrimLast(typeName, u8'*'); - - auto typeHandle = TryGetElementHandle(scopes, typeName); - - GTSL::StaticString<512> shaderName; - - for(auto& e : GetAccessChain(typeHandle.Get())) { - shaderName += GetElement(e).Name; - shaderName += u8"."; - } - - shaderName.Drop(shaderName.GetCodepoints() - 1); - - GTSL::Insert(serializer, string, u8"type", shaderName); - GTSL::Insert(serializer, string, u8"name", structMember.Name); - GTSL::EndObject(serializer, string); - } - - GTSL::EndArray(serializer, string); - - GTSL::EndObject(serializer, string); - - GTSL::EndSerializer(string, serializer); - } -private: - GTSL::Tree elements; - GTSL::Vector, BE::TAR> deductionGuides; - GTSL::Vector members; - - GTSL::Vector structs; - GTSL::Vector Functions; -}; - -/** - * \brief Generates a shader string from a token stream to a target shader language. - * \tparam ALLOCATOR Allocator to allocate shader strings. - * \param pipeline Pipeline which contains all elements needed for compilation. - * \param scopes Scopes in which to look for symbols, precedence grows from higher positions to lower, that is if a foo() declaration exists under scope[0] and another at scope[1], scope[1].foo will be used. - * \param targetSemantics Target shader language to generate code for. - * \param allocator Allocator to allocate shader strings from. - * \return Result containing an error code and two strings, one with shader code and one with all the error codes. - */ -template -GTSL::Result, GTSL::StaticString<1024>>> GenerateShader(const GPipeline& pipeline, const GTSL::Range scopes, GAL::ShaderType targetSemantics, const ALLOCATOR& allocator) { - GTSL::String headerBlock(allocator), structBlock(allocator), functionBlock(allocator), declarationBlock(allocator); GTSL::StaticString<1024> errorString; - - auto addErrorCode = [&errorString](const GTSL::StringView string) { - errorString += string; errorString += u8"\n"; - }; - - headerBlock += u8"#version 460 core\n"; //push version - - bool isRayTracing = false, isCompute = false; - - switch (targetSemantics) { - case GAL::ShaderType::RAY_GEN: - case GAL::ShaderType::CLOSEST_HIT: - case GAL::ShaderType::ANY_HIT: - case GAL::ShaderType::INTERSECTION: - case GAL::ShaderType::CALLABLE: - case GAL::ShaderType::MISS: - isRayTracing = true; - break; - case GAL::ShaderType::COMPUTE: - isCompute = true; - break; - } - - headerBlock += u8"#extension GL_EXT_shader_16bit_storage : enable\n"; headerBlock += u8"#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable\n"; - headerBlock += u8"#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable\n"; headerBlock += u8"#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable\n"; - headerBlock += u8"#extension GL_EXT_nonuniform_qualifier : enable\n"; headerBlock += u8"#extension GL_EXT_scalar_block_layout : enable\n"; - headerBlock += u8"#extension GL_EXT_buffer_reference : enable\n"; headerBlock += u8"#extension GL_EXT_buffer_reference2 : enable\n"; - headerBlock += u8"#extension GL_EXT_shader_image_load_formatted : enable\n"; - - if(isCompute) { - headerBlock += u8"#extension GL_KHR_shader_subgroup_basic : enable\n"; - headerBlock += u8"#extension GL_KHR_shader_subgroup_arithmetic : enable\n"; - headerBlock += u8"#extension GL_KHR_shader_subgroup_ballot : enable\n"; - headerBlock += u8"#extension GL_KHR_shader_subgroup_shuffle : enable\n"; - } - - if (isRayTracing) { - headerBlock += u8"#extension GL_EXT_ray_tracing : enable\n"; - } - - headerBlock += u8"layout(row_major) uniform; layout(row_major) buffer;\n"; //matrix order definitions - - auto resolve = [&](const GTSL::StringView name) -> GTSL::StaticString<64> { - GTSL::StaticString<64> result = name; - - switch (GTSL::Hash(name)) { - case GTSL::Hash(u8"float32"): result = u8"float"; break; - case GTSL::Hash(u8"vec2f"): result = u8"vec2"; break; - case GTSL::Hash(u8"vec2i"): result = u8"ivec2"; break; - case GTSL::Hash(u8"vec2u"): result = u8"uvec2"; break; - case GTSL::Hash(u8"vec3u"): result = u8"uvec3"; break; - case GTSL::Hash(u8"vec3f"): result = u8"vec3"; break; - case GTSL::Hash(u8"vec4f"): result = u8"vec4"; break; - case GTSL::Hash(u8"mat2f"): result = u8"mat2"; break; - case GTSL::Hash(u8"mat3f"): result = u8"mat3"; break; - case GTSL::Hash(u8"matrix4f"): result = u8"mat4"; break; - case GTSL::Hash(u8"matrix3x4f"): result = u8"mat4x3"; break; // row-columns to columns-rows - case GTSL::Hash(u8"matrix4x3f"): result = u8"mat3x4"; break; - case GTSL::Hash(u8"uint8"): result = u8"uint8_t"; break; - case GTSL::Hash(u8"uint64"): result = u8"uint64_t"; break; - case GTSL::Hash(u8"int32"): result = u8"int"; break; - case GTSL::Hash(u8"uint32"): result = u8"uint"; break; - case GTSL::Hash(u8"uint16"): result = u8"uint16_t"; break; - case GTSL::Hash(u8"ptr_t"): result = u8"uint64_t"; break; - case GTSL::Hash(u8"return"): result = u8"return "; break; - } - - if (*(name.end() - 1) == u8'*') { - GTSL::StaticString<64> n(name); - RTrimLast(n, u8'*'); - n += u8"Pointer"; - result = n; - } - - return result; - }; - - auto resolveTypeName = [&](const StructElement struct_element) -> StructElement { - StructElement result = struct_element; - - if (auto res = FindFirst(struct_element.Type, U'[')) { - result.Type.Drop(res.Get()); - auto last = FindLast(struct_element.Type, U']'); //TODO: boom no bracket pair - for (uint32 o = res.Get(); o < last.Get() + 1; ++o) { - result.Name += struct_element.Type[o]; - } - } - - result.Type = resolve(result.Type); - - return result; - }; - - { - auto constants = pipeline.GetElements(GPipeline::LanguageElement::ElementType::CONSTANT, scopes); - - uint32 i = 0; - for(auto& c : constants) { - const auto& member = pipeline.GetMember(c); - - headerBlock += u8"layout(constant_id="; GTSL::ToString(headerBlock, i++); headerBlock += u8") const "; - - auto m = resolveTypeName(member); - headerBlock += m.Type; headerBlock &= m.Name; - headerBlock += u8"="; - headerBlock += m.Type; headerBlock += u8"("; headerBlock += m.DefaultValue; headerBlock += u8")"; headerBlock += u8";\n"; - } - } - - auto writeStructElement = [resolveTypeName](auto& string, const StructElement& element) { - auto newName = resolveTypeName(element); - string += newName.Type; string += u8' '; string += newName.Name; string += u8';'; - }; - - [&] { - auto descriptorSetBlockHandle = pipeline.TryGetElementHandle(scopes, u8"descriptorSetBlock"); - if (!descriptorSetBlockHandle) { addErrorCode(u8"Descriptor set block declaration was not found."); return; } - - for (uint32 s = 0; const auto & l : pipeline.GetChildren(descriptorSetBlockHandle.Get())) { - for (uint32 ss = 0; const auto & m : pipeline.GetChildren(l)) { - declarationBlock += u8"layout(set="; ToString(declarationBlock, s); declarationBlock += u8",binding="; ToString(declarationBlock, ss); declarationBlock += u8") uniform "; - writeStructElement(declarationBlock, pipeline.GetMember(m)); declarationBlock += u8"\n"; - ++ss; - } - ++s; - } - }(); - - GTSL::HashMap usedFunctions(16, allocator); - GTSL::HashMap usedStructs(16, allocator); //TODO: try emplace return is a reference which might be invalidated if map is resized during recursive call - - auto addBlockDeclaration = [&](GTSL::String& string, const GTSL::StringView name, const GTSL::StringView type, const GTSL::Range vars, const GTSL::Range struct_elements) { - string += u8"layout("; string += GTSL::Join{ vars, u8"," }; - string += u8") "; string += type; string &= name; string += u8" { "; - - for (const auto& e : struct_elements) { - writeStructElement(string, e); - } - - string += u8"};\n"; - }; - - auto addInterfaceBlockDeclaration = [&](const GTSL::StringView interface_name, const GTSL::StringView type, const GTSL::Range vars) { - auto blockHandle = pipeline.TryGetElementHandle(scopes, interface_name); - if (!blockHandle) { addErrorCode(GTSL::StaticString<64>(interface_name) + u8" interface block declaration was not found."); return; } - - declarationBlock += u8"layout("; declarationBlock += GTSL::Join{ vars, u8"," }; - declarationBlock += u8") "; declarationBlock += type; declarationBlock += u8" _"; declarationBlock += interface_name; declarationBlock += u8" { "; - - for (const auto& e : pipeline.GetChildren(blockHandle.Get())) { - writeStructElement(declarationBlock, pipeline.GetMember(e)); - } - declarationBlock += u8" } "; - declarationBlock += interface_name; - declarationBlock += u8";\n"; - }; - - auto addInterfaceBlockDeclarationWithMembers = [&](const GTSL::StringView interface_name, const GTSL::StringView type, const GTSL::Range vars, const GTSL::Range members) { - auto blockHandle = pipeline.TryGetElementHandle(scopes, interface_name); - if (!blockHandle) { addErrorCode(GTSL::StaticString<64>(interface_name) + u8" interface block declaration was not found."); return; } - - declarationBlock += u8"layout("; declarationBlock += GTSL::Join{ vars, u8"," }; - declarationBlock += u8") "; declarationBlock += type; declarationBlock += u8" _"; declarationBlock += interface_name; declarationBlock += u8" { "; - - for (const auto& e : members) { - writeStructElement(declarationBlock, e); - } - declarationBlock += u8" } "; - declarationBlock += interface_name; - declarationBlock += u8";\n"; - }; - - auto writeStruct = [&](GTSL::StringView ne, const GPipeline::ElementHandle structHandle, bool ref, bool readOnly, auto&& self) { - //if (usedStructs.Find(Id(ne))) { return; } - - GTSL::StaticString<64> name(ne); - - if (ref) { name += u8"Pointer"; } - - usedStructs.Emplace(Id(name), true); - - GTSL::StaticString<128> qualifiers; - - GTSL::StaticVector members; - - for (const auto& e : pipeline.GetChildren(structHandle)) { - members.EmplaceBack(pipeline.GetMember(e)); - } - - if(!members) { - members.EmplaceBack(u8"uint32", u8"dummy"); - } - - if (ref) { - if (readOnly) - qualifiers += u8"readonly"; - - qualifiers += u8"buffer"; - - addBlockDeclaration(structBlock, name, qualifiers, { u8"buffer_reference", u8"scalar", u8"buffer_reference_align=2" }, members); - } else { - structBlock += u8"struct "; structBlock += name; structBlock += u8"{"; - for(auto& e : members) { - writeStructElement(structBlock, e); - } - structBlock += u8"};\n"; - } - }; - - { - auto structs = pipeline.GetElements(GPipeline::LanguageElement::ElementType::STRUCT, scopes); - - for (auto r : structs) { - const auto& element = pipeline.GetElement(r); - const auto& structData = pipeline.GetStruct(r); - - auto genType = structData.GenerationType; bool makeConst = structData.IsConst; - - if (genType == 0) { - writeStruct(element.Name, r, false, makeConst, writeStruct); - } else if(genType == 1) { - writeStruct(element.Name, r, true, makeConst, writeStruct); - } else { - writeStruct(element.Name, r, false, makeConst, writeStruct); - writeStruct(element.Name, r, true, makeConst, writeStruct); - } - } - } - - auto writeFunction = [&pipeline, scopes, &usedFunctions, resolveTypeName, resolve](auto& resultString, const GPipeline::ElementHandle function_handle, auto&& self) -> void { - auto& function = pipeline.GetFunction(function_handle); - - auto functionUsed = usedFunctions.TryEmplace(function.Id, false); - - GTSL::StaticString<4096> string; - - if (!functionUsed.Get()) { - string += resolveTypeName({ function.Return, u8"" }).Type; string += u8' '; string += function.Name; - - string += u8"("; - - uint32 paramCount = function.Parameters.GetLength(); - - for (uint32 i = 0; i < paramCount; ++i) { - auto param = resolveTypeName(function.Parameters[i]); - string += param.Type; string += u8' '; string += param.Name; - if (i != paramCount - 1) { string += u8", "; } - } - - string += u8") { "; - - for (uint32 i = 0; i < function.Tokens;) { - auto makeStatement = [&] { - GTSL::StaticString<4096> statementString; - - while (i < function.Tokens) { - const auto& node = function.Tokens[i++]; - - switch (node.ValueType) { - case ShaderNode::Type::ID: { - if (statementString) { - if (GTSL::IsLetter(*(statementString.end() - 1)) || GTSL::IsNumber(*(statementString.end() - 1))) { statementString += U' '; } - } - - auto elementResult = pipeline.TryGetElementHandle(scopes, function_handle, node.Name); - - if (elementResult.State()) { - auto& element = pipeline.GetElement(elementResult.Get()); - - if (element.Type == GPipeline::LanguageElement::ElementType::MEMBER) { - statementString += node.Name; - } - else if (element.Type == GPipeline::LanguageElement::ElementType::DEDUCTION_GUIDE) { - for (uint32 i = 0; auto f : pipeline.GetMemberDeductionGuide(elementResult.Get())) { - if (i) { statementString += u8"."; } - statementString += resolve(pipeline.GetName(f)); - ++i; - } - } - else if (element.Type == GPipeline::LanguageElement::ElementType::FUNCTION) { - for (auto e : pipeline.GetFunctionOverloads(scopes, node.Name)) { //for every overload, TODO: type deduction? - self(resultString, e, self); //add function - } - - statementString += node.Name; - } - else if(element.Type == GPipeline::LanguageElement::ElementType::DISABLED) { - return GTSL::StaticString<4096>(); //skip statement - } else { - statementString += resolve(node.Name); - } - } - else { - statementString += resolve(node.Name); - } - - break; - } - case ShaderNode::Type::LPAREN: { - statementString += u8"("; - break; - } - case ShaderNode::Type::RPAREN: { - statementString += u8")"; - break; - } - case ShaderNode::Type::LBRACKET: { - statementString += u8"["; - break; - } - case ShaderNode::Type::RBRACKET: { - statementString += u8"]"; - break; - } - case ShaderNode::Type::LBRACE: { - statementString += u8"{"; - break; - } - case ShaderNode::Type::RBRACE: { - statementString += u8"}"; - break; - } - case ShaderNode::Type::DOT: { - statementString += u8"."; - break; - } - case ShaderNode::Type::LITERAL: { - statementString += node.Name; - break; - } - case ShaderNode::Type::OP: { - //statementString += u8' '; statementString += node.Name; statementString += u8' '; - statementString += node.Name; - break; - } - case ShaderNode::Type::COMMA: { - statementString += u8", "; - break; - } - case ShaderNode::Type::COLON: { - statementString += u8':'; - break; - } - case ShaderNode::Type::SEMICOLON: { - statementString += u8";\n"; - break; - } - case ShaderNode::Type::HASH: { - statementString += u8"\n#"; - break; - } - case ShaderNode::Type::EXCLAMATION: { - statementString += u8" !"; - break; - } - case ShaderNode::Type::LESS_THAN: { - statementString += u8"<"; - break; - } - case ShaderNode::Type::GREATER_THAN: { - statementString += u8">"; - break; - } - } - } - - return statementString; - }; - - string += makeStatement(); - } - - string += u8"}\n"; - - functionUsed.Get() = true; - } - - resultString += string; - }; - - auto addLayoutDeclaration = [&](const GTSL::StringView interface_name, const GTSL::StringView type, bool isVertexSurfaceInterface = false) { - auto interfaceBlockHandle = pipeline.TryGetElementHandle(scopes, interface_name); - if (!interfaceBlockHandle) { addErrorCode(GTSL::StaticString<256>(interface_name) + u8" interface block declaration was not found."); return; } - - const auto& arr = pipeline.GetChildren(interfaceBlockHandle.Get()); - - uint32 locationIndex = 0; - - for (uint32 i = 0; i < arr; ++i) { - declarationBlock += u8"layout(location="; ToString(declarationBlock, locationIndex); declarationBlock += u8") "; - declarationBlock += type; - - const auto& member = pipeline.GetMember(arr[i]); - - const auto resolvedMember = resolveTypeName(member); - - if (isVertexSurfaceInterface) { if (resolvedMember.Type == u8"uint") { declarationBlock &= u8"flat"; } } - declarationBlock &= resolvedMember.Type; declarationBlock &= resolvedMember.Name; declarationBlock += u8";\n"; - - locationIndex += member.Type == u8"mat3f" ? 3 : 1; // TODO: add proper support for other types - } - }; - - { - GTSL::StaticVector elements; - - for(auto s : scopes) { - auto r = pipeline.TryGetElementHandle(s, u8"pushConstantBlock"); - - auto& e = pipeline.GetElement(s); - - if(r) { - auto els = pipeline.GetElements(GPipeline::LanguageElement::ElementType::MEMBER, { r.Get() }); - - for(auto m : els) { - elements.EmplaceBack(pipeline.GetMember(m)); - } - } - } - - addInterfaceBlockDeclarationWithMembers(u8"pushConstantBlock", u8"uniform", { u8"push_constant", u8"scalar" }, elements); - } - - if (isRayTracing) { - addLayoutDeclaration(u8"payloadBlock", targetSemantics == GAL::ShaderType::RAY_GEN ? u8"rayPayloadEXT" : u8"rayPayloadInEXT"); - addInterfaceBlockDeclaration(u8"shaderRecordBlock", u8"buffer", { u8"shaderRecordEXT", u8"scalar" }); - } - - switch (targetSemantics) { - case GAL::ShaderType::VERTEX: { - addLayoutDeclaration(u8"vertexSurfaceInterface", u8"out", true); - addLayoutDeclaration(u8"vertex", u8"in"); - break; - } - case GAL::ShaderType::MESH: - declarationBlock += u8"layout(local_size_x="; ToString(declarationBlock, 32); declarationBlock += u8") in;\n"; - declarationBlock += u8"layout(triangles) out;\n"; - declarationBlock += u8"layout(max_vertices=64, max_primitives=126) out;\n"; - break; - case GAL::ShaderType::CLOSEST_HIT: - declarationBlock += u8"hitAttributeEXT vec2 hitBarycenter;\n"; - break; - case GAL::ShaderType::ANY_HIT: - break; - case GAL::ShaderType::INTERSECTION: { - break; - } - case GAL::ShaderType::TESSELLATION_CONTROL: break; - case GAL::ShaderType::TESSELLATION_EVALUATION: break; - case GAL::ShaderType::GEOMETRY: break; - case GAL::ShaderType::FRAGMENT: { - addLayoutDeclaration(u8"vertexSurfaceInterface", u8"in", true); - addLayoutDeclaration(u8"fragmentOutputBlock", u8"out"); - break; - } - case GAL::ShaderType::COMPUTE: { - auto sharedVariables = pipeline.GetElements(GPipeline::LanguageElement::ElementType::SHARED, scopes); - - for(auto sharedVariable : sharedVariables) { - auto resolvedMember = resolveTypeName(pipeline.GetMember(sharedVariable)); - declarationBlock += u8"shared"; declarationBlock &= resolvedMember.Type; declarationBlock &= resolvedMember.Name; declarationBlock += u8";\n"; - } - - auto xSize = pipeline.TryGetElementHandle(scopes, u8"group_size_x"); - auto ySize = pipeline.TryGetElementHandle(scopes, u8"group_size_y"); - auto zSize = pipeline.TryGetElementHandle(scopes, u8"group_size_z"); - declarationBlock += u8"layout(local_size_x="; declarationBlock += pipeline.GetMember(xSize.Get()).DefaultValue; - declarationBlock += u8",local_size_y="; declarationBlock += pipeline.GetMember(ySize.Get()).DefaultValue; - declarationBlock += u8",local_size_z="; declarationBlock += pipeline.GetMember(zSize.Get()).DefaultValue; - declarationBlock += u8") in;\n"; - - break; - } - case GAL::ShaderType::TASK: - break; - case GAL::ShaderType::RAY_GEN: { - break; - } - case GAL::ShaderType::MISS: { - break; - } - case GAL::ShaderType::CALLABLE: - break; - } - - writeFunction(functionBlock, pipeline.TryGetElementHandle(scopes, u8"main").Get(), writeFunction); //add main - - GTSL::String fin(allocator); - - fin += headerBlock; - fin += structBlock; - fin += declarationBlock; - fin += functionBlock; - - return GTSL::Result(GTSL::Pair(MoveRef(fin), MoveRef(errorString)), errorString.IsEmpty()); -} - -inline void AddSurfaceShaderOutDeclaration(GPipeline* pipeline, GPipeline::ElementHandle parent_element_handle, const GTSL::Range elements) { - auto fragmentOutputBlockHandle = pipeline->DeclareScope(parent_element_handle, u8"fragmentOutputBlock"); - for (auto& e : elements) { - pipeline->DeclareVariable(fragmentOutputBlockHandle, e); - } -} - -inline void AddPushConstantDeclaration(GPipeline* pipeline, GPipeline::ElementHandle parent_element_handle, const GTSL::Range elements) { - auto pushConstantBlockHandle = pipeline->DeclareScope(parent_element_handle, u8"pushConstantBlock"); - for (auto& e : elements) { - pipeline->DeclareVariable(pushConstantBlockHandle, e); - } -} - -inline void AddVertexSurfaceInterfaceBlockDeclaration(GPipeline* pipeline, GPipeline::ElementHandle parent_element_handle, const GTSL::Range elements) { - auto vertexSurfaceInterface = pipeline->DeclareScope(parent_element_handle, u8"vertexSurfaceInterface"); - - for (auto& e : elements) { - auto vertexTextureCoordinatesHandle = pipeline->DeclareVariable(vertexSurfaceInterface, e); - //pipeline->AddMemberDeductionGuide(common_permutation->vertexShaderScope, u8"vertexTextureCoordinates", { { vertexSurfaceInterface }, { vertexTextureCoordinatesHandle } }); - } -} - -inline void AddVertexBlockDeclaration(GPipeline* pipeline, GPipeline::ElementHandle parent_element_handle, const GTSL::Range elements) { - auto vertexBlock = pipeline->DeclareScope(parent_element_handle, u8"vertex"); - for (auto& e : elements) { - pipeline->DeclareVariable(vertexBlock, e); - - } -} - -// SHADER DOC -// Class: Could be thought of as shader use, (Surface, Vertex, PostProcess, RayGen, Miss, Etc) -// TargetSemantics: target shader stage, (Vertex, Fragment, ClosestHit, AnyHit, Miss, Compute, Etc) -// GPipeline: defines environment for shader to operate in. Defines how common data is accessed so that the shader generator knows how to -// seamlessly translate Classes to TargetSemantics - -/* #include -#include - -inline void GenSPIRV() { - GTSL::StaticVector spirv; - - const bool debugMode = true; uint32 id = 0; - - //first words - spirv.EmplaceBack(spv::MagicNumber); //SPIR-V magic num - spirv.EmplaceBack(0 << 24 | 1 << 16 | 5 << 8 | 0); //SPIR-V version number - spirv.EmplaceBack(0); //SPIR-V generator number - spirv.EmplaceBack(0); //bound - spirv.EmplaceBack(0); //instruction schema - - auto addInst = [&](uint16 enumerant, ARGS&&... args) { - auto wordCount = uint16(1) + static_cast(sizeof...(ARGS)); - spirv.EmplaceBack(wordCount << 16 | enumerant); - (spirv.EmplaceBack(args), ...); - }; - - auto addInstVar = [&](uint16 enumerant, GTSL::Range words) { - auto wordCount = uint16(1) + static_cast(words.ElementCount()); - spirv.EmplaceBack(wordCount << 16 | enumerant); - spirv.PushBack(words); - }; - - auto packString = [&](const GTSL::StringView string, auto& cont) { - for (uint32 u = 0; u < string.GetBytes(); ++u) { - uint32& ch = cont.EmplaceBack(0u); - - for (uint32 t = 0; t < 4 && u < string.GetBytes(); ++t, ++u) { - ch |= static_cast(string[u + t]) << (t * 8); - } - } - - if (GTSL::ModuloByPowerOf2(string.GetBytes(), 4) == 0) { //if all non null terminator characters are a multiple of 4 bytes that means that all groups of four bytes where put in an int and no free byte was left to represent a null terminator - cont.EmplaceBack(0u); - } - }; - - //capability section - addInst(spv::OpCapability, spv::Capability::CapabilityInt64); - addInst(spv::OpCapability, spv::Capability::CapabilityInt16); - addInst(spv::OpCapability, spv::Capability::CapabilityImageReadWrite); - addInst(spv::OpCapability, spv::Capability::CapabilitySampledImageArrayDynamicIndexing); - addInst(spv::OpCapability, spv::Capability::CapabilitySampledImageArrayNonUniformIndexing); - addInst(spv::OpCapability, spv::Capability::CapabilityStorageImageArrayDynamicIndexing); - addInst(spv::OpCapability, spv::Capability::CapabilityStorageImageArrayNonUniformIndexing); - addInst(spv::OpCapability, spv::Capability::CapabilityVariablePointers); - addInst(spv::OpCapability, spv::Capability::CapabilityVariablePointersStorageBuffer); - addInst(spv::OpCapability, spv::Capability::CapabilityPhysicalStorageBufferAddresses); - - //extension section - //memory model section - addInst(spv::OpMemoryModel, spv::AddressingModel::AddressingModelPhysical64, spv::MemoryModel::MemoryModelVulkan); - //entry points section - - //Interface is a list of of global OpVariable instructions. - //These declare the set of global variables from a module that form the interface of this entry point. - //The set of Interface must be equal to or a superset of the global OpVariable Result referenced by the entry point�s static call tree, - //within the interface�s storage classes. Before version 1.4, the interface�s storage classes are limited to the Input and Output storage classes. - //Starting with version 1.4, the interface�s storage classes are all storage classes used in declaring all global variables - //referenced by the entry point�s call tree. - //Interface are forward references.Before version 1.4, duplication of these is tolerated.Starting with version 1.4, - //an must not appear more than once. - addInst(spv::OpEntryPoint, spv::ExecutionModelVertex, 0, 0); - //execution modes section - - auto declStruct = [&](const GTSL::StringView name, const GTSL::Range params) { - auto structId = id++; - - if (debugMode) { - GTSL::StaticVector chs; - chs.EmplaceBack(structId); - packString(name, chs); - addInstVar(spv::OpName, chs); - } - - uint32 byteOffset = 0; - for (uint32 i = 0; auto & e : params) { - addInst(spv::OpMemberDecorate, structId, i, byteOffset); - - if (debugMode) { //decorate struct members with name if compiling in debug - GTSL::StaticVector chs; - - chs.EmplaceBack(structId); - chs.EmplaceBack(i); - - packString(e.Name, chs); - - addInstVar(spv::OpMemberName, chs); - } - - byteOffset += 1; - i += 1; - } - }; - - auto declFunc = [&](const GTSL::StringView ret, const GTSL::Range params) { - auto functionId = id++; - - addInst(spv::OpFunction); - - for (auto& e : params) { - addInst(spv::OpFunctionParameter); - } - - addInst(spv::OpReturn); - addInst(spv::OpFunctionEnd); - }; -} */ - -//GTSL::StaticVector stack, queue; -// -//auto infixToPostfix = [&] { -// while (true) { -// const auto& token = tokens[i]; const auto tokenType = tokenTypes[i]; -// auto& statement = shader.statements.back(); -// -// uint32 currentIndex = i; -// -// ++i; -// -// switch (tokenType) { -// case TokenTypes::ID: -// queue.EmplaceBack(currentIndex); -// break; -// case TokenTypes::OP: -// -// if (stack) { -// if (PRECEDENCE[Id(tokens[stack.back()])] > PRECEDENCE[Id(token)]) { -// queue.EmplaceBack(stack.back()); -// stack.PopBack(); -// } -// } -// -// stack.EmplaceBack(currentIndex); -// break; -// case TokenTypes::NUM: -// queue.EmplaceBack(currentIndex); -// break; -// case TokenTypes::LPAREN: -// stack.EmplaceBack(currentIndex); -// break; -// case TokenTypes::RPAREN: -// while(tokenTypes[stack.back()] != TokenTypes::LPAREN) { -// queue.EmplaceBack(stack.back()); -// stack.PopBack(); -// } -// -// stack.PopBack(); -// break; -// case TokenTypes::COMMA: -// break; -// case TokenTypes::END: return; -// default: ; -// } -// -// } -//}; -// -//shader.statements.EmplaceBack(BE::PAR(u8"ShaderGenerator")); -//infixToPostfix(); -// -//while(stack) { //transfer all remaining map -// queue.EmplaceBack(stack.back()); -// stack.PopBack(); -//} - -//if (tokenTypes[i] != TokenTypes::END) { continue; } -// -//auto& statement = shader.statements.EmplaceBack(BE::PAR(u8"ShaderGenerator")); -// -//auto evalExpression = [&](uint32 start, uint32 p, uint32 parentHandle, uint32* l, auto&& self) -> uint32 { -// if (tokenTypes[start] == TokenTypes::LPAREN) { ++*l; return p + 1; } -// if (tokenTypes[start] == TokenTypes::RPAREN) { ++*l; return p - 1; } -// if (tokenTypes[start] == TokenTypes::COMMA) { ++*l; return p; } -// -// uint32 minPrecedence = 0xFFFFFFFF, index = 0; -// -// for (uint32 x = start; x < i; ++x) { -// auto currentTokenType = tokenTypes[x]; -// -// if (auto precedence = getPrecedence(tokens[x]); precedence < minPrecedence) { -// minPrecedence = precedence; -// index = x; -// } -// } -// -// bool isOperator = IsAnyOf(tokens[index], u8"="); -// uint32 handle = 0; -// const auto& element = shader.GetElement(Shader::ElementHandle(), tokens[index]); -// -// switch (element.Type) { -// break; case Shader::LanguageElement::ElementType::TYPE: handle = statement.Emplace(parentHandle, ShaderNode::ElementType::RVALUE, tokens[index]); -// break; case Shader::LanguageElement::ElementType::MEMBER: handle = statement.Emplace(parentHandle, ShaderNode::ElementType::VARIABLE, tokens[index]); -// break; case Shader::LanguageElement::ElementType::FUNCTION: -// handle = statement.Emplace(parentHandle, isOperator ? ShaderNode::ElementType::OPERATOR : ShaderNode::ElementType::FUNCTION, tokens[index]); -// break; default:; -// } -// -// if (element.Type == Shader::LanguageElement::ElementType::FUNCTION) { -// if (isOperator) { -// std::swap(tokens[index], tokens[index - 1]); -// std::swap(tokenTypes[index], tokenTypes[index - 1]); -// index -= 1; -// ++p; -// } -// -// uint32 t = 0; -// -// while (true) { -// if (self(index + 1 + t, p + 1, handle, &t, self) == p) { break; } -// } -// } -// -// ++* l; -// -// return p; -//}; -// -//uint32 l = 0; -//evalExpression(lastStatement, 0, 0, &l, evalExpression); -//lastStatement = i; - -//GTSL::StaticMap PRECEDENCE(16); -//PRECEDENCE.Emplace(u8"=", 1); -//PRECEDENCE.Emplace(u8"||", 2); -//PRECEDENCE.Emplace(u8"<", 7); PRECEDENCE.Emplace(u8">", 7); PRECEDENCE.Emplace(u8"<=", 7); PRECEDENCE.Emplace(u8">=", 7); PRECEDENCE.Emplace(u8"==", 7); PRECEDENCE.Emplace(u8"!=", 7); -//PRECEDENCE.Emplace(u8"+", 10); PRECEDENCE.Emplace(u8"-", 10); -//PRECEDENCE.Emplace(u8"*", 20); PRECEDENCE.Emplace(u8"/", 20); PRECEDENCE.Emplace(u8"%", 20); -// -//auto getPrecedence = [&](const GTSL::StringView name) -> uint32 { -// if (auto pre = PRECEDENCE.TryGet(Id(name))) { -// return pre.Get(); -// } -// else { -// return 30; -// } -//}; - -//inline auto parseStatement(GTSL::JSON parent, GTSL::Tree& tree, uint32 parentHandle) -> uint32 { -// auto handle = tree.Emplace(parentHandle); -// auto& node = tree[handle]; -// -// if (auto nameMember = parent[u8"name"]) { //var || var decl || func || operator -// node.Name = GTSL::StringView(nameMember); -// -// if (auto paramsMember = parent[u8"params"]) { //function, var decl -// if (auto typeMember = parent[u8"type"]) { //name ^ params ^ type -> var decl -// //node.ValueType = ShaderNode::ElementType::VAR_DEC; -// //node.TypeName = GTSL::StringView(typeMember); -// } -// else { //name ^ params ^ ~type -> function -// if (GTSL::IsSymbol(nameMember.GetStringView()[0])) { -// node.ValueType = ShaderNode::ElementType::OPERATOR; -// } -// else if (nameMember.GetStringView() == u8"return") { -// node.ValueType = ShaderNode::ElementType::RETURN; -// } -// else { -// node.ValueType = ShaderNode::ElementType::FUNCTION; -// } -// } -// -// for (auto e : parent[u8"params"]) { -// parseStatement(e, tree, handle); -// } -// } -// else { //name and no params -> var -// node.ValueType = ShaderNode::ElementType::VARIABLE; -// } -// } -// else if (auto outputMember = parent[u8"output"]) { -// node.Name = outputMember; -// //node.ValueType = ShaderNode::ElementType::SHADER_RESULT; -// for (auto e : parent[u8"params"]) { -// parseStatement(e, tree, handle); -// } -// } -// else { //no name -> literal -// if (auto valueMember = parent[u8"value"]) { -// node.Name = valueMember; -// node.ValueType = ShaderNode::ElementType::LITERAL; -// } -// else { -// //node.TypeName = parent[u8"type"]; -// node.ValueType = ShaderNode::ElementType::RVALUE; -// for (auto e : parent[u8"params"]) { -// parseStatement(e, tree, handle); -// } -// } -// } -// -// return handle; -//} \ No newline at end of file diff --git a/src/ByteEngine/Render/StaticMeshSystem.cpp b/src/ByteEngine/Render/StaticMeshSystem.cpp deleted file mode 100644 index 7b1fdf0b..00000000 --- a/src/ByteEngine/Render/StaticMeshSystem.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "StaticMeshSystem.h" - -#include "RenderOrchestrator.h" -#include "RenderSystem.h" -#include "ByteEngine/Game/ApplicationManager.h" - -class RenderStaticMeshCollection; - -StaticMeshSystem::StaticMeshSystem(const InitializeInfo& initializeInfo): System(initializeInfo, u8"StaticMeshSystem"), transformations(16, GetPersistentAllocator()), meshes(16, GetPersistentAllocator()), StaticMeshTypeIndentifier(GetApplicationManager()->RegisterType(this, u8"StaticMesh")), OnAddMeshEventHandle(GetApplicationManager()->RegisterEvent>(this, u8"OnAddMesh")), OnUpdateMeshEventHandle(GetApplicationManager()->RegisterEvent(this, u8"OnUpdateMesh")) { - DeleteStaticMesh = GetApplicationManager()->RegisterTask(this, u8"deleteStaticMeshes", {}, &StaticMeshSystem::deleteMesh); - GetApplicationManager()->BindDeletionTaskToType(StaticMeshTypeIndentifier, DeleteStaticMesh); -} - -StaticMeshSystem::StaticMeshHandle StaticMeshSystem::AddStaticMesh(GTSL::StringView mesh_name) { - uint32 index = transformations.Emplace(); - - meshes.Emplace(Mesh{mesh_name}); - - auto handle = GetApplicationManager()->MakeHandle(StaticMeshTypeIndentifier, index); - - GetApplicationManager()->DispatchEvent(this, GetOnAddMeshEventHandle(), GTSL::MoveRef(handle), GTSL::StaticString<64>(mesh_name)); - - return handle; -} - -GTSL::ShortString<64> ToString(const GAL::ShaderDataType type) { - switch (type) { case GAL::ShaderDataType::FLOAT: break; - case GAL::ShaderDataType::FLOAT2: return u8"FLOAT2"; - case GAL::ShaderDataType::FLOAT3: return u8"FLOAT3"; - case GAL::ShaderDataType::FLOAT4: break; - case GAL::ShaderDataType::INT: break; - case GAL::ShaderDataType::INT2: break; - case GAL::ShaderDataType::INT3: break; - case GAL::ShaderDataType::INT4: break; - case GAL::ShaderDataType::BOOL: break; - case GAL::ShaderDataType::MAT3: break; - case GAL::ShaderDataType::MAT4: break; - default: return u8"Uh oh"; - } - - return u8"Uh oh"; -} diff --git a/src/ByteEngine/Render/StaticMeshSystem.h b/src/ByteEngine/Render/StaticMeshSystem.h deleted file mode 100644 index 8695bcf1..00000000 --- a/src/ByteEngine/Render/StaticMeshSystem.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include -#include - -#include "RenderSystem.h" -#include "ByteEngine/Resources/StaticMeshResourceManager.h" - -#include "ByteEngine/Handle.hpp" - -#include - -class WorldRendererPipeline; - -class StaticMeshSystem final : public BE::System { -public: - StaticMeshSystem(const InitializeInfo& initializeInfo); - - DECLARE_BE_TYPE(StaticMesh) - - StaticMeshHandle AddStaticMesh(GTSL::StringView mesh_name); - - GTSL::Matrix4 GetMeshTransform(StaticMeshHandle index) { return transformations[index()]; } - GTSL::Matrix4& GetTransformation(StaticMeshHandle staticMeshHandle) { return transformations[staticMeshHandle()]; } - GTSL::Vector3 GetMeshPosition(StaticMeshHandle staticMeshHandle) const { return GTSL::Math::GetTranslation(transformations[staticMeshHandle()]); } - - GTSL::StaticString<64> GetMeshName(const StaticMeshHandle static_mesh_handle) const { - return meshes[static_mesh_handle()].meshResourceName; - } - - DECLARE_BE_EVENT(OnAddMesh, StaticMeshHandle, GTSL::StaticString<64>); - DECLARE_BE_EVENT(OnUpdateMesh, StaticMeshHandle, GTSL::Matrix3x4); - - void SetPosition(StaticMeshHandle staticMeshHandle, GTSL::Vector3 vector3) { - GTSL::Math::SetTranslation(transformations[staticMeshHandle()], vector3); - GetApplicationManager()->DispatchEvent(this, GetOnUpdateMeshEventHandle(), GTSL::MoveRef(staticMeshHandle), GTSL::Matrix3x4(transformations[staticMeshHandle()])); - } - - void SetRotation(StaticMeshHandle staticMeshHandle, GTSL::Quaternion quaternion) { - GTSL::Math::SetRotation(transformations[staticMeshHandle()], quaternion); - GetApplicationManager()->DispatchEvent(this, GetOnUpdateMeshEventHandle(), GTSL::MoveRef(staticMeshHandle), GTSL::Matrix3x4(transformations[staticMeshHandle()])); - } -private: - GTSL::FixedVector transformations; - TaskHandle DeleteStaticMesh; - - void deleteMesh(const TaskInfo, StaticMeshHandle handle) { - meshes.Pop(handle()); - } - - struct Mesh { - GTSL::StaticString<64> meshResourceName; - }; - GTSL::FixedVector meshes; -}; diff --git a/src/ByteEngine/Render/Types.hpp b/src/ByteEngine/Render/Types.hpp deleted file mode 100644 index 17c65f5d..00000000 --- a/src/ByteEngine/Render/Types.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#define POINT_LIGHT_DATA { { u8"vec3f", u8"position" }, { u8"vec3f", u8"color" }, {u8"float32", u8"intensity"}, {u8"float32", u8"radius"} } -#define LIGHTING_DATA { { u8"uint32", u8"shadowMapCount" }, { u8"uint32", u8"lightCount" }, { u8"uint32[8]", u8"lights" }, { u8"uint32", u8"pointLightsLength" }, { u8"PointLightData[1024]", u8"pointLights" } } -#define INSTANCE_DATA { { u8"matrix3x4f", u8"transform" }, { u8"uint32", u8"vertexBufferOffset" }, { u8"uint32", u8"indexBufferOffset" }, { u8"uint32", u8"shaderGroupIndex" }, {u8"uint32", u8"padding" } } -#define VIEW_DATA { { u8"matrix4f", u8"view" }, { u8"matrix4f", u8"proj" }, { u8"matrix4f", u8"viewInverse" }, { u8"matrix4f", u8"projInverse" }, { u8"matrix4f", u8"vp" }, { u8"matrix4f", u8"vpInverse" }, { u8"vec4f", u8"position" },{ u8"float32", u8"near" }, { u8"float32", u8"far" }, { u8"u16vec2", u8"extent"}, { u8"vec2f", u8"extentReciprocal" }, { u8"float32", u8"aspectRatio" } } -#define CAMERA_DATA { { u8"ViewData[3]", u8"viewHistory" } } -#define GLOBAL_DATA { { u8"uint32", u8"frameIndex" }, { u8"float32", u8"elapsedTime" }, { u8"float32", u8"deltaTime" }, { u8"uint32", u8"framePipelineDepth" }, { u8"uint32[4]", u8"random" }, { u8"TextureReference[8]", u8"blueNoise2D" } } - -#define UI_RES { { u8"float32", u8"bestDistance" }, { u8"vec2f", u8"a" }, { u8"vec2f", u8"b" } } - -#define UI_INSTANCE_DATA { { u8"matrix3x4f", u8"transform" }, { u8"vec4f", u8"color" }, { u8"float32", u8"roundness" }, { u8"uint32[2]", u8"derivedTypeIndex" } } -#define UI_TEXT_DATA { { u8"uint32", u8"fontIndex" }, { u8"uint32[128]", u8"chars" } } -#define UI_LINEAR_SEGMENT { { u8"vec2f[2]", u8"segments" } } -#define UI_QUADRATIC_SEGMENT { { u8"vec2f[3]", u8"segments" } } -#define UI_GLYPH_CONTOUR_DATA { { u8"uint32", u8"linearSegmentCount" }, { u8"uint32", u8"quadraticSegmentCount" }, { u8"LinearSegment[128]", u8"linearSegments" }, { u8"QuadraticSegment[128]", u8"quadraticSegments" } } -#define UI_GLYPH_DATA { { u8"uint32", u8"contourCount" }, { u8"GlyphContourData[4]", u8"contours" } } -#define UI_FONT_DATA { { u8"GlyphData*[128]", u8"glyphs" } } -#define UI_DATA { { u8"matrix4f", u8"projection" }, { u8"FontData*[4]", u8"fontData" }, { u8"TextData[16]", u8"textData" } } - -#define INDIRECT_DISPATCH_COMMAND_DATA { { u8"uint32", u8"x" }, { u8"uint32", u8"y" }, { u8"uint32", u8"z" } } - -#define TRACE_RAY_PARAMETER_DATA { { u8"uint64", u8"accelerationStructure" }, { u8"uint32", u8"rayFlags" }, { u8"uint32", u8"recordOffset"}, { u8"uint32", u8"recordStride"}, { u8"uint32", u8"missIndex"}, { u8"float32", u8"tMin"}, { u8"float32", u8"tMax"} } - -#define FORWARD_RENDERPASS_DATA { { u8"ImageReference", u8"Albedo" }, { u8"ImageReference", u8"WorldSpacePosition" }, { u8"ImageReference", u8"ViewSpacePosition" }, { u8"ImageReference", u8"Normal" }, { u8"ImageReference", u8"Roughness" }, { u8"ImageReference", u8"Depth" } } -#define RT_RENDERPASS_DATA { { u8"TextureReference", u8"Albedo" }, { u8"TextureReference", u8"Depth" }, { u8"ImageReference", u8"Shadow" } } -#define LIGHTING_RENDERPASS_DATA { { u8"TextureReference", u8"Albedo" }, { u8"TextureReference", u8"Normal" }, { u8"TextureReference", u8"Roughness" }, { u8"TextureReference", u8"Shadow" }, { u8"TextureReference", u8"AO" }, { u8"TextureReference", u8"Depth" }, { u8"ImageReference", u8"Lighting" } } -#define AO_RENDERPASS_DATA { { u8"TextureReference", u8"Albedo" }, { u8"TextureReference", u8"WorldSpacePosition" }, { u8"TextureReference", u8"ViewSpacePosition" }, { u8"TextureReference", u8"Normal" }, { u8"TextureReference", u8"Depth" }, { u8"ImageReference", u8"AO" } } \ No newline at end of file diff --git a/src/ByteEngine/Render/UIManager.cpp b/src/ByteEngine/Render/UIManager.cpp deleted file mode 100644 index d482adf0..00000000 --- a/src/ByteEngine/Render/UIManager.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "UIManager.h" - -#include -#include - -UIManager::UIManager(const InitializeInfo& initializeInfo) : System(initializeInfo, u8"UIManager"), -colors(32, GetPersistentAllocator()), canvases(8, GetPersistentAllocator()), primitives(16, GetPersistentAllocator()), textPrimitives(8, GetPersistentAllocator()), curvePrimitives(8, GetPersistentAllocator()), queuedUpdates(8, GetPersistentAllocator()), -UIElementTypeIndentifier(GetApplicationManager()->RegisterType(this, u8"UIElement")), fonts(4, GetPersistentAllocator()) -{ - GetApplicationManager()->AddEvent(u8"UIManager", GetOnCreateUIElementEventHandle()); -} - -uint32 pixels(uint32 points_display_size, uint32 glyph_em_units, uint32 units_per_em, uint32 ppi) { - return glyph_em_units * (points_display_size * ppi / (ppi * units_per_em)); -} - -void UIManager::ProcessUpdates() { - auto screenExtent = GTSL::Extent2D(1920, 1080); - auto screenSize = GTSL::Vector2(screenExtent.Width, screenExtent.Height); - - auto windowSystem = GetApplicationManager()->GetSystem(u8"WindowSystem"); - auto windowExtent = GTSL::Extent2D(1920, 1080); - auto windowSize = GTSL::Vector2(windowExtent.Width, windowExtent.Height); - auto windowRelativeSize = GTSL::Vector2(windowSize.X() / windowSize.Y(), 1.0f); - - if (!(primitives.begin() != primitives.end())) { return; } - - auto screenRelativeSize = GTSL::Vector2(screenSize.X() / screenSize.Y(), 1.0f); - - UpdateData updateData{ screenRelativeSize, windowRelativeSize, screenRelativeSize * (windowSize / screenSize), windowSize / screenSize }; - - primitives.operator[](1).HalfSize = windowRelativeSize; - primitives.operator[](1).RenderSize = windowRelativeSize; - - updateBranch(primitives.begin(), &updateData, GTSL::Vector2(screenSize.X() / screenSize.Y(), 1.0f), GTSL::Vector2(), GTSL::Vector2()); - - //auto result = FindPrimitiveUnderPoint({}); - //if (result) { - // GetApplicationManager()->AddStoredDynamicTask(getPrimitive(result.Get()).OnPress, UIElementHandle(result.Get())); - //} - - //OnFontLoadTaskHandle = GetApplicationManager()->RegisterTask(this, u8"UIOnFontLoad", DependencyBlock(), &UIManager::OnFontLoad); -} - -// ----------------------------------- -// All sizes relative to window size -// ----------------------------------- - -UIManager::PrimitiveData& UIManager::updateBranch(decltype(primitives)::iterator iterator, const UpdateData* update_data, GTSL::Vector2 size, GTSL::Vector2 start_position, GTSL::Vector2 parent_way) { - const uint32 primitiveCount = iterator.GetLength(); - //if (!primitiveCount) { return; } // If this element has no children, do not evaluate. - - auto& primitive = static_cast(iterator); - - //if(!primitive.isDirty) { return; } - - // Distribution axis indicates which axis, (X = 0 || Y = 1) the distribution of the elements will occur in. - uint32 distributionAxis = 0; - - // Distribution mask is used to cancel values in axis' where the calculations for the current distribution axis must not be taken into account. - GTSL::Vector2 distributionMask = 0.0f; - - // Way indicates in which direction elements will be distributed among the different axis'. - GTSL::Vector2 way = 0.0f, side = 0.0f; - - float32 w = 0, p = 1.0f; - - { // Set distribution variables according to alignment policies. - - switch (primitive.Alignment) { - case Alignments::LEFT: distributionAxis = 0; w = -1.0f; break; - case Alignments::RIGHT: distributionAxis = 0; w = 1.0f; break; - case Alignments::TOP: distributionAxis = 1; w = 1.0f; break; - case Alignments::BOTTOM: distributionAxis = 1; w = -1.0f; break; - case Alignments::CENTER: w = 0.0f; p = 0.0f; break; - } - - way[distributionAxis] = -w; - side[distributionAxis] = w; - distributionMask[distributionAxis] = p; - } - - GTSL::Vector2 halfSize; - - for(uint8 a = 0; a < 2; ++a) { - switch (primitive.scalingPolicies[a]) { - case ScalingPolicies::FILL: { - switch (primitive.sizingPolicies[a]) { - case SizingPolicies::FROM_SCREEN: { - if constexpr (WINDOW_SPACE) { - halfSize[a] = update_data->WindowSize[a]; - } else { - - } - break; - } - case SizingPolicies::FROM_OTHER_ELEMENT: { - if constexpr (WINDOW_SPACE) { - halfSize[a] = size[a]; - } else { - - } - break; - } - } - break; - } - case ScalingPolicies::SET_ASPECT_RATIO: { - switch (primitive.sizingPolicies[a]) { - case SizingPolicies::FROM_SCREEN: { - if constexpr (WINDOW_SPACE) { - halfSize[a] = primitive.HalfSize[a] / update_data->ScreenToWindowSize[a]; - } else { - - } - break; - } - case SizingPolicies::FROM_OTHER_ELEMENT: { - uint8 restrictingElementMinDimension = 0, elementMaxDimension = 0; - - if(size[0] < size[1]) { - restrictingElementMinDimension = 0; - } else { - restrictingElementMinDimension = 1; - } - - if(primitive.HalfSize[0] < primitive.HalfSize[1]) { - elementMaxDimension = 0; - } else { - elementMaxDimension = 1; - } - - float32 reductionFactor = size[restrictingElementMinDimension] / primitive.HalfSize[elementMaxDimension]; - - if constexpr (WINDOW_SPACE) { - halfSize[a] = primitive.HalfSize[a] * reductionFactor; - } else { - - } - break; - } - } - break; - } - case ScalingPolicies::AUTO: { - break; - } - } - } - - primitive.RenderSize = halfSize; - - primitive.isDirty = false; - - if constexpr (WINDOW_SPACE) { - primitive.Position = start_position + primitive.RenderSize * parent_way; - } - - { - uint32 i = 0; - - auto pos = primitive.Position + (halfSize - primitive.Padding) * side; - - for (auto e : iterator) { - auto& n = updateBranch(e, update_data, halfSize - primitive.Padding, pos, way); - pos += n.RenderSize * way * 2.0f + distributionMask * primitive.Spacing; - - ++i; - } - } - - return primitive; -} \ No newline at end of file diff --git a/src/ByteEngine/Render/UIManager.h b/src/ByteEngine/Render/UIManager.h deleted file mode 100644 index 6ec4f63b..00000000 --- a/src/ByteEngine/Render/UIManager.h +++ /dev/null @@ -1,494 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "RenderTypes.h" -#include "ByteEngine/Handle.hpp" -#include "ByteEngine/Id.h" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Game/System.hpp" -#include "ByteEngine/Resources/FontResourceManager.h" -#include "GTSL/JSON.hpp" - -enum class Alignments : uint8 { - TOP, - LEFT, CENTER, RIGHT, - BOTTOM -}; - -/** - * \brief Enumerates all ways an element can be sized when resizing occurs. - */ -enum class SizingPolicies : uint8 { - /** - * \brief The size of the object is defined relative to screen size, which means that when a window or a parent element is resized that element will maintain it's size. - */ - FROM_SCREEN, - /** - * \brief The size of the object is defined relative to another element which means that when a parent element is resized that element will change it's size. - */ - FROM_OTHER_ELEMENT, - FROM_PARENT_CONTAINER = FROM_OTHER_ELEMENT -}; - - -/** - * \brief All ways an en element can be scaled to fit inside it's parent. - */ -enum class ScalingPolicies : uint8 { - FILL, - SET_ASPECT_RATIO, - AUTO -}; - -/** - * \brief Enumerates all ways to accomodate elements in a space. This can be further by the alignment. - */ -enum class SpacingPolicy : uint8 { - /** - * \brief Places every object inside the element one next to each other. - */ - PACK, - - /** - * \brief Evenly distributes all objects inside the element. - */ - DISTRIBUTE -}; - -/** - * \brief Manages ui elements. - * All scales are defined and stored as a percentage of screen size. That is all constant size elements maintain the same percentage, and container relative elements have their scale updated every time they are scaled. - */ -class UIManager : public BE::System { -public: - DECLARE_BE_TYPE(UIElement); - - DECLARE_BE_TASK(OnFontLoad, BE_RESOURCES(), FontResourceManager::FontData, GTSL::Buffer); - - explicit UIManager(const InitializeInfo& initializeInfo); - - static constexpr bool WINDOW_SPACE = true; - - struct PrimitiveData { - enum class PrimitiveType { NONE, CANVAS, ORGANIZER, SQUARE, TEXT, CURVE } Type; - GTSL::Vector2 RelativeLocation; - GTSL::Vector2 Bounds; - GTSL::Vector2 HalfSize, RenderSize; - //Relative to parent. - GTSL::Vector2 Position; - Alignments Alignment; - ScalingPolicies scalingPolicies[2/*DIMENSIONS*/]; - SizingPolicies sizingPolicies[2]; - RenderModelHandle Material; - uint32 DerivedTypeIndex; - SpacingPolicy spacingPolicy; - bool isDirty; - TaskHandle OnHover, OnPress; - GTSL::Vector4 Color; - float32 Rounding = 0.0f, Padding, Spacing; - }; - - static EventHandle GetOnCreateUIElementEventHandle() { return { u8"OnCreateUIElement" }; } - - auto& GetCanvases() { return canvases; } - - void AddColor(const GTSL::StringView colorName, const GTSL::RGBA color) { colors.Emplace(Id(colorName), color); } - [[nodiscard]] GTSL::RGBA GetColor(const Id color) const { return colors.At(color); } - - void SetExtent(const GTSL::Extent2D newExtent) { realExtent = newExtent; } - - void SetScale(UIElementHandle element_handle, const uint8 axis, float32 scale) { - getPrimitive(element_handle).HalfSize[axis] = scale; - flagsAsDirty(element_handle); - } - - /** - * \brief Sets the scaling percentage for a UI element. This scale will be calculated based on the sizing policy. - * \param element_handle Element to set scale for. - * \param scale Scaling percentage. - */ - void SetScale(UIElementHandle element_handle, GTSL::Vector2 scale) { - getPrimitive(element_handle).HalfSize = scale; - flagsAsDirty(element_handle); - } - - void SetRounding(const UIElementHandle element_handle, const float32 rounding) { - getPrimitive(element_handle).Rounding = rounding; - flagsAsDirty(element_handle); - } - - void SetPadding(const UIElementHandle element_handle, const float32 padding) { - getPrimitive(element_handle).Padding = padding; - flagsAsDirty(element_handle); - } - - void SetSpacing(const UIElementHandle element_handle, const float32 spacing) { - getPrimitive(element_handle).Spacing = spacing; - flagsAsDirty(element_handle); - } - - UIElementHandle AddCanvas(const UIElementHandle ui_element_handle = UIElementHandle()) { - //canvases.Emplace(system); - auto canvasHandle = add(ui_element_handle, PrimitiveData::PrimitiveType::CANVAS); - SetScalingPolicy(canvasHandle, 0, ScalingPolicies::FILL); - SetScalingPolicy(canvasHandle, 1, ScalingPolicies::FILL); - SetSizingPolicy(canvasHandle, 0, SizingPolicies::FROM_SCREEN); - SetSizingPolicy(canvasHandle, 1, SizingPolicies::FROM_SCREEN); - return canvasHandle; - } - - void SetString(const UIElementHandle ui_element_handle, const GTSL::StringView string) { - auto& primitive = getPrimitive(ui_element_handle); - textPrimitives[primitive.DerivedTypeIndex].Text = string; - flagsAsDirty(ui_element_handle); - } - - void SetFont(const UIElementHandle ui_element_handle, const GTSL::StringView font_name) { - auto& primitive = getPrimitive(ui_element_handle); - textPrimitives[primitive.DerivedTypeIndex].Font = font_name; - flagsAsDirty(ui_element_handle); - - auto* fontResourceManager = GetApplicationManager()->GetSystem(u8"FontResourceManager"); - fontResourceManager->LoadFont(font_name, OnFontLoadTaskHandle); - } - - UIElementHandle AddCanvas(const GTSL::StringView json_ui_text, const UIElementHandle ui_element_handle = UIElementHandle()) { - //canvases.Emplace(system); - auto canvasHandle = add(ui_element_handle, PrimitiveData::PrimitiveType::CANVAS); - SetScalingPolicy(canvasHandle, 0, ScalingPolicies::FILL); - SetScalingPolicy(canvasHandle, 1, ScalingPolicies::FILL); - SetSizingPolicy(canvasHandle, 0, SizingPolicies::FROM_SCREEN); - SetSizingPolicy(canvasHandle, 1, SizingPolicies::FROM_SCREEN); - - auto processElement = [&](UIElementHandle parent_element_handle, const GTSL::StringView name, const GTSL::JSON& element, auto&& self) -> void { - if(const auto e = element[u8"enabled"]; e && !e.GetBool()) { return; } - - PrimitiveData::PrimitiveType type = PrimitiveData::PrimitiveType::NONE; - - switch(GTSL::Hash(element[u8"type"].GetStringView())) { - case GTSL::Hash(u8"Box"): type = PrimitiveData::PrimitiveType::SQUARE; break; - case GTSL::Hash(u8"Organizer"): type = PrimitiveData::PrimitiveType::ORGANIZER; break; - case GTSL::Hash(u8"Text"): type = PrimitiveData::PrimitiveType::TEXT; break; - } - - UIElementHandle elementHandle = add(parent_element_handle, type); - - if(auto sizeL = element[u8"size"]) { - auto processSize = [&](const uint8 axis, GTSL::JSON json_member) { - if(!json_member) { return; } - - if(auto size = json_member[u8"size"]) { - SetScale(elementHandle, axis, size.GetFloat()); - } - - if(auto scaling = json_member[u8"scaling"]) { - ScalingPolicies scalingPolicy = ScalingPolicies::FILL; - - switch(GTSL::Hash(scaling.GetStringView())) { - case GTSL::Hash(u8"fill"): scalingPolicy = ScalingPolicies::FILL; break; - case GTSL::Hash(u8"aspect_ratio"): scalingPolicy = ScalingPolicies::SET_ASPECT_RATIO; break; - } - - SetScalingPolicy(elementHandle, axis, scalingPolicy); - } - - if(auto sizing = json_member[u8"reference"]) { - SizingPolicies sizingPolicy = SizingPolicies::FROM_SCREEN; - - switch(GTSL::Hash(sizing.GetStringView())) { - case GTSL::Hash(u8"parent"): sizingPolicy = SizingPolicies::FROM_PARENT_CONTAINER; break; - case GTSL::Hash(u8"screen"): sizingPolicy = SizingPolicies::FROM_SCREEN; break; - } - - SetSizingPolicy(elementHandle, axis, sizingPolicy); - } - }; - - processSize(0, sizeL[u8"x"]); - processSize(1, sizeL[u8"y"]); - } - - if(auto color = element[u8"color"]) { - SetColor(elementHandle, color.GetStringView()); - } - - if(auto roundness = element[u8"rounding"]) { - SetRounding(elementHandle, roundness.GetFloat()); - } - - if(auto padding = element[u8"padding"]) { - SetPadding(elementHandle, padding.GetFloat()); - } - - if(auto spacing = element[u8"spacing"]) { - SetSpacing(elementHandle, spacing.GetFloat()); - } - - if(auto font = element[u8"font"]) { - SetFont(elementHandle, font.GetStringView()); - } - - if(auto string = element[u8"string"]) { - SetString(elementHandle, string.GetStringView()); - } - - if(auto alignmentData = element[u8"alignment"]) { - Alignments alignment = Alignments::CENTER; - - switch(GTSL::Hash(alignmentData.GetStringView())) { - case GTSL::Hash(u8"center"): alignment = Alignments::CENTER; break; - case GTSL::Hash(u8"left"): alignment = Alignments::LEFT; break; - case GTSL::Hash(u8"right"): alignment = Alignments::RIGHT; break; - case GTSL::Hash(u8"top"): alignment = Alignments::TOP; break; - case GTSL::Hash(u8"bottom"): alignment = Alignments::BOTTOM; break; - } - - SetElementAlignment(elementHandle, alignment); - } - - if(auto children = element[u8"children"]) { - for(auto c : children) { - self(elementHandle, u8"", c, self); - } - } - }; - - GTSL::JSON json = GTSL::JSON(json_ui_text, GetPersistentAllocator()); - - for(auto c : json[u8"children"]) { - processElement(canvasHandle, u8"p", c, processElement); - } - - - return canvasHandle; - } - - UIElementHandle AddOrganizer(const UIElementHandle ui_element_handle = UIElementHandle()) { - auto organizerHandle = add(ui_element_handle, PrimitiveData::PrimitiveType::ORGANIZER); - return organizerHandle; - } - - UIElementHandle AddSquare(const UIElementHandle element_handle = UIElementHandle()) { - auto handle = add(element_handle, PrimitiveData::PrimitiveType::SQUARE); - return handle; - } - - UIElementHandle AddText(const UIElementHandle element_handle, const GTSL::StringView text) { - auto handle = add(element_handle, PrimitiveData::PrimitiveType::TEXT); - return GetApplicationManager()->MakeHandle(UIElementTypeIndentifier, handle()); - } - - UIElementHandle AddCurve(const UIElementHandle element_handle) { - auto handle = add(element_handle, PrimitiveData::PrimitiveType::CURVE); - const auto place = curvePrimitives.Emplace(GetPersistentAllocator()); - auto& primitive = getPrimitive(handle); - primitive.DerivedTypeIndex = place; - auto& curve = curvePrimitives[place]; - return GetApplicationManager()->MakeHandle(UIElementTypeIndentifier, place); - } - - PrimitiveData& getPrimitive(const UIElementHandle element_handle) { - return primitives[element_handle()]; - } - - [[nodiscard]] GTSL::Extent2D GetExtent() const { return realExtent; } - - GTSL::Result FindPrimitiveUnderPoint(const GTSL::Vector2 point) { - auto check = [&](decltype(primitives)::iterator level, auto&& self) -> GTSL::Result { - GTSL::Vector2 rect; - if (GTSL::Math::Abs(rect - point) <= static_cast(level).Bounds) { return GTSL::Result{ UIElementHandle(), true }; } - - for (auto e : level) { - if (auto r = self(e, self)) { return r; } - } - }; - - //check(primitives.begin(), check); - - return GTSL::Result{ false }; - } - - void BindToElement(const UIElementHandle ui_element_handle, const TaskHandle delegate) { - getPrimitive(ui_element_handle).OnPress = delegate; - } - - void SetColor(const UIElementHandle ui_element_handle, const GTSL::StringView color) { - auto& primitive = primitives[ui_element_handle()]; - switch (primitive.Type) { - case PrimitiveData::PrimitiveType::NONE: break; - case PrimitiveData::PrimitiveType::ORGANIZER: break; - //case PrimitiveData::PrimitiveType::SQUARE: squares[primitive.DerivedTypeIndex].SetColor(color); break; - } - - auto colorEntry = colors.TryGet(Id(color)); - - if(!colorEntry) { return; } - - primitive.Color.X() = colorEntry.Get().R(); - primitive.Color.Y() = colorEntry.Get().G(); - primitive.Color.Z() = colorEntry.Get().B(); - primitive.Color.W() = colorEntry.Get().A(); - } - - void SetMaterial(const UIElementHandle ui_element_handle, const RenderModelHandle material) { - getPrimitive(ui_element_handle).Material = material; - flagsAsDirty(ui_element_handle); - } - - void SetPosition(UIElementHandle ui_element_handle, GTSL::Vector2 pos) { - auto& primitive = primitives[ui_element_handle()]; - switch (primitive.Type) { - case PrimitiveData::PrimitiveType::NONE: break; - case PrimitiveData::PrimitiveType::ORGANIZER: break; - case PrimitiveData::PrimitiveType::SQUARE: break; - } - flagsAsDirty(ui_element_handle); - } - - void SetElementAlignment(const UIElementHandle organizer, Alignments alignment) { - getPrimitive(organizer).Alignment = alignment; - flagsAsDirty(organizer); - } - - void SetScalingPolicy(UIElementHandle organizer, ScalingPolicies scaling_policy) { - getPrimitive(organizer).scalingPolicies[0] = scaling_policy; - getPrimitive(organizer).scalingPolicies[1] = scaling_policy; - flagsAsDirty(organizer); - } - - void SetScalingPolicy(UIElementHandle organizer, uint8 axis, ScalingPolicies scaling_policy) { - getPrimitive(organizer).scalingPolicies[axis] = scaling_policy; - flagsAsDirty(organizer); - } - - void SetSizingPolicy(UIElementHandle organizer, SizingPolicies sizing_policy) { - getPrimitive(organizer).sizingPolicies[0] = sizing_policy; - getPrimitive(organizer).sizingPolicies[1] = sizing_policy; - flagsAsDirty(organizer); - } - - void SetSizingPolicy(UIElementHandle organizer, uint8 axis, SizingPolicies sizing_policy) { - getPrimitive(organizer).sizingPolicies[axis] = sizing_policy; - flagsAsDirty(organizer); - } - - void SetElementSpacingPolicy(UIElementHandle organizer, SpacingPolicy spacingPolicy) { - getPrimitive(organizer).spacingPolicy = spacingPolicy; - flagsAsDirty(organizer); - } - - void ProcessUpdates(); - - struct TextPrimitive { - TextPrimitive(const BE::PAR& allocator) : Text(allocator) {} - GTSL::String Text; - GTSL::StaticString<64> Font{ u8"COOPBL" }; - bool IsLocalized = false; - }; - - auto GetRoot() { return primitives.begin(); } - - GTSL::StringView GetString(const uint32 index) { return textPrimitives[primitives[index].DerivedTypeIndex].Text; } - -private: - GTSL::FixedVector canvases; - GTSL::HashMap colors; - - GTSL::Tree primitives; - - GTSL::FixedVector textPrimitives; - - struct CurvePrimitive { - CurvePrimitive(const BE::PAR& allocator) : Points(3, allocator) {} - GTSL::Vector Points; - }; - GTSL::FixedVector curvePrimitives; - - GTSL::Extent2D realExtent; - - GTSL::Vector queuedUpdates; - - UIElementHandle add(const UIElementHandle parent_handle, PrimitiveData::PrimitiveType type) { - uint32 parentNodeKey = 0; - - if (parent_handle) { - parentNodeKey = parent_handle(); - } - - auto primitiveIndex = primitives.Emplace(parentNodeKey); - auto& primitive = primitives[primitiveIndex]; - primitive.Type = type; - primitive.Alignment = Alignments::CENTER; - primitive.HalfSize = 1.0f; - primitive.sizingPolicies[0] = SizingPolicies::FROM_SCREEN; - primitive.sizingPolicies[1] = SizingPolicies::FROM_SCREEN; - primitive.scalingPolicies[0] = ScalingPolicies::FILL; - primitive.scalingPolicies[1] = ScalingPolicies::SET_ASPECT_RATIO; - primitive.spacingPolicy = SpacingPolicy::DISTRIBUTE; - primitive.DerivedTypeIndex = ~0u; - primitive.isDirty = true; - primitive.Color = 0.5f; - primitive.Padding = 0.0f; - - if (parent_handle) { - flagsAsDirty(parent_handle); //if a child is added to an element it has to be re-evaluated - } - - switch (type) { - case PrimitiveData::PrimitiveType::NONE: break; - case PrimitiveData::PrimitiveType::CANVAS: break; - case PrimitiveData::PrimitiveType::ORGANIZER: break; - case PrimitiveData::PrimitiveType::SQUARE: break; - case PrimitiveData::PrimitiveType::TEXT: { - primitive.sizingPolicies[0] = SizingPolicies::FROM_PARENT_CONTAINER; - primitive.sizingPolicies[1] = SizingPolicies::FROM_SCREEN; - primitive.scalingPolicies[0] = ScalingPolicies::FILL; - primitive.scalingPolicies[1] = ScalingPolicies::AUTO; - primitive.DerivedTypeIndex = textPrimitives.Emplace(GetPersistentAllocator()); - break; - } - case PrimitiveData::PrimitiveType::CURVE: break; - } - - auto handle = GetApplicationManager()->MakeHandle(UIElementTypeIndentifier, primitiveIndex); - - GetApplicationManager()->DispatchEvent(this, GetOnCreateUIElementEventHandle(), GTSL::MoveRef(handle), GTSL::MoveRef(primitive.Type)); - - return handle; - } - - struct UpdateData { - GTSL::Vector2 ScreenSize, WindowSize, ScreenToWindowSize, WindowToScreenSize; - }; - - PrimitiveData& updateBranch(GTSL::Tree::iterator iterator, const UpdateData* update_data, GTSL:: - Vector2 size, GTSL::Vector2 start_position, GTSL::Vector2 parent_way); - - void flagsAsDirty(const UIElementHandle element_handle) { - getPrimitive(element_handle).isDirty = true; - } - - struct FontData { - FontData(const BE::PAR& allocator) : Characters(128, allocator) {} - - GTSL::Vector Characters; - }; - GTSL::HashMap fonts; - - void OnFontLoad(TaskInfo, FontResourceManager::FontData font_data, GTSL::Buffer font_buffer); -}; - -inline void UIManager::OnFontLoad(TaskInfo, FontResourceManager::FontData font_data, GTSL::Buffer font_buffer) { - auto& font = fonts.Emplace(Id(font_data.GetName()), GetPersistentAllocator()); - - for(uint32 i = 0; i < font_data.Characters.Length; ++i) { - font.Characters.EmplaceBack(font_data.Characters.array[i]); - } -} diff --git a/src/ByteEngine/Render/WorldRenderPipeline.cpp b/src/ByteEngine/Render/WorldRenderPipeline.cpp deleted file mode 100644 index 4b2485ed..00000000 --- a/src/ByteEngine/Render/WorldRenderPipeline.cpp +++ /dev/null @@ -1,287 +0,0 @@ -#include "WorldRenderPipeline.hpp" - -WorldRendererPipeline::WorldRendererPipeline(const InitializeInfo& initialize_info) : RenderPipeline(initialize_info, u8"WorldRendererPipeline"), spherePositionsAndRadius(16, GetPersistentAllocator()), instances(16, GetPersistentAllocator()), resources(16, GetPersistentAllocator()), meshToInstanceMap(16, GetPersistentAllocator()), InstanceTypeIndentifier(GetApplicationManager()->RegisterType(this, u8"Instance")) { - auto* renderSystem = initialize_info.AppManager->GetSystem(u8"RenderSystem"); - auto* renderOrchestrator = initialize_info.AppManager->GetSystem(u8"RenderOrchestrator"); - - rayTracing = BE::Application::Get()->GetBoolOption(u8"rayTracing"); - - onStaticMeshInfoLoadHandle = initialize_info.AppManager->RegisterTask(this, u8"OnStaticMeshInfoLoad", DependencyBlock(TypedDependency(u8"StaticMeshResourceManager", AccessTypes::READ_WRITE), TypedDependency(u8"RenderSystem", AccessTypes::READ_WRITE), TypedDependency(u8"RenderOrchestrator", AccessTypes::READ_WRITE)), &WorldRendererPipeline::onStaticMeshInfoLoaded); - - onStaticMeshLoadHandle = initialize_info.AppManager->RegisterTask(this, u8"OnStaticMeshLoad", DependencyBlock(TypedDependency(u8"RenderSystem", AccessTypes::READ_WRITE), TypedDependency(u8"StaticMeshSystem"), TypedDependency(u8"RenderOrchestrator")), &WorldRendererPipeline::onStaticMeshLoaded); - - OnAddMeshTaskHandle = initialize_info.AppManager->RegisterTask(this, u8"OnAddMesh", DependencyBlock(TypedDependency(u8"StaticMeshResourceManager"), TypedDependency(u8"RenderOrchestrator"), TypedDependency(u8"RenderSystem")), &WorldRendererPipeline::OnAddMesh); - - OnAddRenderGroupMeshTaskHandle = initialize_info.AppManager->RegisterTask(this, u8"OnAddRenderGroupMesh", DependencyBlock(TypedDependency(u8"StaticMeshResourceManager"), TypedDependency(u8"RenderOrchestrator"), TypedDependency(u8"RenderSystem"), TypedDependency(u8"StaticMeshSystem")), &WorldRendererPipeline::OnAddRenderGroupMesh); - - OnUpdateMeshTaskHandle = initialize_info.AppManager->RegisterTask(this, u8"OnUpdateMesh", DependencyBlock(TypedDependency(u8"RenderSystem"), TypedDependency(u8"RenderOrchestrator")), &WorldRendererPipeline::OnUpdateMesh); - - OnUpdateRenderGroupMeshTaskHandle = initialize_info.AppManager->RegisterTask(this, u8"OnUpdateRenderGroupMesh", DependencyBlock(TypedDependency(u8"RenderSystem"), TypedDependency(u8"RenderOrchestrator")), &WorldRendererPipeline::OnUpdateRenderGroupMesh); - - GetApplicationManager()->SetTaskReceiveOnlyLast(OnUpdateRenderGroupMeshTaskHandle); - - GetApplicationManager()->SubscribeToEvent(u8"SMGR", StaticMeshSystem::GetOnAddMeshEventHandle(), OnAddRenderGroupMeshTaskHandle); - GetApplicationManager()->SubscribeToEvent(u8"SMGR", StaticMeshSystem::GetOnUpdateMeshEventHandle(), OnUpdateRenderGroupMeshTaskHandle); - - initialize_info.AppManager->EnqueueScheduledTask(initialize_info.AppManager->RegisterTask(this, u8"renderSetup", DependencyBlock(TypedDependency(u8"RenderSystem"), TypedDependency(u8"RenderOrchestrator")), &WorldRendererPipeline::preRender, u8"RenderSetup", u8"Render")); - - initialize_info.AppManager->AddEvent(u8"WorldRendererPipeline", EventHandle(u8"OnAddPointLight")); - initialize_info.AppManager->AddEvent(u8"WorldRendererPipeline", EventHandle(u8"OnUpdatePointLight")); - initialize_info.AppManager->AddEvent(u8"WorldRendererPipeline", EventHandle(u8"OnRemovePointLight")); - - GetApplicationManager()->AddTypeSetupDependency(this, InstanceTypeIndentifier, OnAddMeshTaskHandle, true); - GetApplicationManager()->AddTypeSetupDependency(this, InstanceTypeIndentifier, OnUpdateMeshTaskHandle, false); - - GetApplicationManager()->AddTypeSetupDependency(this, GetApplicationManager()->GetSystem(u8"StaticMeshSystem")->GetStaticMeshTypeIdentifier(), OnAddRenderGroupMeshTaskHandle, true); - GetApplicationManager()->AddTypeSetupDependency(this, GetApplicationManager()->GetSystem(u8"StaticMeshSystem")->GetStaticMeshTypeIdentifier(), OnUpdateRenderGroupMeshTaskHandle, false); - - auto addLightTaskHandle = GetApplicationManager()->RegisterTask(this, u8"addPointLight", DependencyBlock(TypedDependency(u8"RenderSystem"), TypedDependency(u8"RenderOrchestrator")), &WorldRendererPipeline::onAddLight); - initialize_info.AppManager->SubscribeToEvent(u8"WorldRendererPipeline", EventHandle(u8"OnAddPointLight"), addLightTaskHandle); - auto updateLightTaskHandle = GetApplicationManager()->RegisterTask(this, u8"updatePointLight", DependencyBlock(TypedDependency(u8"RenderSystem"), TypedDependency(u8"RenderOrchestrator")), & WorldRendererPipeline::updateLight); - initialize_info.AppManager->SubscribeToEvent(u8"WorldRendererPipeline", EventHandle(u8"OnUpdatePointLight"), updateLightTaskHandle); - - sourceVertexBuffer = renderSystem->CreateBuffer(1024 * 1024 * 4, GAL::BufferUses::VERTEX, true, {}); - destinationVertexBuffer = renderSystem->CreateBuffer(1024 * 1024 * 4, GAL::BufferUses::VERTEX | GAL::BufferUses::BUILD_INPUT_READ, false, {}); - sourceIndexBuffer = renderSystem->CreateBuffer(1024 * 1024 * 4, GAL::BufferUses::INDEX, true, {}); - destinationIndexBuffer = renderSystem->CreateBuffer(1024 * 1024 * 4, GAL::BufferUses::INDEX | GAL::BufferUses::BUILD_INPUT_READ, false, {}); - - RenderOrchestrator::NodeHandle renderPassNodeHandle; - - renderOrchestrator->AddNotifyShaderGroupCreated(GTSL::Delegate::Create(this)); - - if (renderTechniqueName == GTSL::ShortString<16>(u8"Forward")) { - RenderOrchestrator::PassData geoRenderPass; - geoRenderPass.type = RenderOrchestrator::PassTypes::RASTER; - geoRenderPass.Attachments = RenderPassStructToAttachments(FORWARD_RENDERPASS_DATA); - renderPassNodeHandle = renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"Geometry Pass", u8"ForwardRenderPass", renderSystem, geoRenderPass); - } - else if (renderTechniqueName == GTSL::ShortString<16>(u8"Visibility")) { - RenderOrchestrator::PassData geoRenderPass; - geoRenderPass.type = RenderOrchestrator::PassTypes::RASTER; - geoRenderPass.Attachments.EmplaceBack(GTSL::StringView(u8"Visibility"),GTSL::StringView(u8"Visibility"), GAL::AccessTypes::WRITE); - geoRenderPass.Attachments.EmplaceBack(GTSL::StringView(u8"Depth"),GTSL::StringView(u8"Depth"), GAL::AccessTypes::WRITE); - renderPassNodeHandle = renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"Geometry Pass", u8"VisibilityRenderPass", renderSystem, geoRenderPass); - - GTSL::StaticVector members; - members.EmplaceBack(nullptr, u8"ptr_t", u8"positionStream"); - members.EmplaceBack(nullptr, u8"ptr_t", u8"normalStream"); - members.EmplaceBack(nullptr, u8"ptr_t", u8"tangentStream"); - members.EmplaceBack(nullptr, u8"ptr_t", u8"bitangentStream"); - members.EmplaceBack(nullptr, u8"ptr_t", u8"textureCoordinatesStream"); - members.EmplaceBack(nullptr, u8"uint32", u8"shaderGroupLength"); - members.EmplaceBack(nullptr, u8"uint32[256]", u8"shaderGroupUseCount"); - members.EmplaceBack(nullptr, u8"uint32[256]", u8"shaderGroupStart"); - members.EmplaceBack(nullptr, u8"IndirectDispatchCommand[256]", u8"indirectBuffer"); - members.EmplaceBack(nullptr, u8"ptr_t", u8"pixelBuffer"); - renderOrchestrator->RegisterType(u8"global", u8"VisibilityData", members); - - visibilityDataKey = renderOrchestrator->MakeDataKey(renderSystem, u8"global", u8"VisibilityData"); - renderPassNodeHandle = renderOrchestrator->AddDataNode(renderPassNodeHandle, u8"VisibilityDataLightingDataNode", visibilityDataKey); - - //pixelXY stores blocks per material that determine which pixels need to be painted with each material - auto pielBuffer = renderOrchestrator->MakeDataKey(renderSystem, u8"global", u8"vec2s[2073600]"); //1920 * 1080 - - { - auto bwk = renderOrchestrator->GetBufferWriteKey(renderSystem, visibilityDataKey); - - const auto vertexElementsThatFitInBuffer = ((1024 * 1024 * 4) / 56u); - - auto bufferAddress = renderSystem->GetBufferAddress(destinationVertexBuffer); - - bwk[u8"positionStream"] = bufferAddress; - bwk[u8"normalStream"] = bufferAddress + 12 * 1 * vertexElementsThatFitInBuffer; //todo: if buffer is updatable only address for current frame will be set - bwk[u8"tangentStream"] = bufferAddress + 12 * 2 * vertexElementsThatFitInBuffer; - bwk[u8"bitangentStream"] = bufferAddress + 12 * 3 * vertexElementsThatFitInBuffer; - bwk[u8"textureCoordinatesStream"] = bufferAddress + 12 * 4 * vertexElementsThatFitInBuffer; - bwk[u8"shaderGroupLength"] = 0u; - bwk[u8"pixelBuffer"] = pielBuffer; - } - - //Counts how many pixels each shader group uses - RenderOrchestrator::PassData countPixelsRenderPassData; - countPixelsRenderPassData.type = RenderOrchestrator::PassTypes::COMPUTE; - countPixelsRenderPassData.Attachments.EmplaceBack(GTSL::StringView(u8"Visibility"), GTSL::StringView(u8"Visibility"), GAL::AccessTypes::READ); - renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"CountPixels", u8"CountPixels", renderSystem, countPixelsRenderPassData); - - ////Performs a prefix to build an indirect buffer defining which pixels each shader group occupies - //RenderOrchestrator::PassData prefixSumRenderPassData; - //prefixSumRenderPassData.PassType = RenderOrchestrator::PassType::COMPUTE; - //renderOrchestrator->AddRenderPassNode(u8"PrefixSum", renderOrchestrator->GetCameraDataLayer(), renderSystem, prefixSumRenderPassData, GetApplicationManager()); - // - ////Scans the whole rendered image and stores which pixels every shader group occupies utilizing the information from the prefix sum pass - //RenderOrchestrator::PassData selectPixelsRenderPass; - //selectPixelsRenderPass.PassType = RenderOrchestrator::PassType::COMPUTE; - //countPixelsRenderPassData.ReadAttachments.EmplaceBack(RenderOrchestrator::PassData::AttachmentReference{ u8"Visibility" }); - //renderOrchestrator->AddRenderPassNode(u8"SelectPixels", renderOrchestrator->GetCameraDataLayer(), renderSystem, selectPixelsRenderPass, GetApplicationManager()); - // - ////Every participating shader group is called to paint every pixel it occupies on screen - //RenderOrchestrator::PassData paintRenderPassData; - //paintRenderPassData.PassType = RenderOrchestrator::PassType::RASTER; - //paintRenderPassData.ReadAttachments.EmplaceBack(RenderOrchestrator::PassData::AttachmentReference{ u8"Visibility" }); - //paintRenderPassData.WriteAttachments.EmplaceBack(RenderOrchestrator::PassData::AttachmentReference{ u8"Color" }); - //renderOrchestrator->AddRenderPassNode(u8"PaintPixels", renderOrchestrator->GetCameraDataLayer(), renderSystem, paintRenderPassData, GetApplicationManager()); - - //renderOrchestrator->SetShaderGroupParameter(renderSystem, ShaderGroupHandle{}, u8"materialCount", 0u); - } - - renderOrchestrator->RegisterType(u8"global", u8"StaticMeshData", INSTANCE_DATA); - meshDataBuffer = renderOrchestrator->MakeDataKey(renderSystem, u8"global", u8"StaticMeshData[8]", meshDataBuffer); - - renderOrchestrator->RegisterType(u8"global", u8"PointLightData", POINT_LIGHT_DATA); - renderOrchestrator->RegisterType(u8"global", u8"LightingData", LIGHTING_DATA); - - renderPassNodeHandle = renderOrchestrator->AddDataNode(renderPassNodeHandle, u8"CameraData", renderOrchestrator->cameraDataKeyHandle); - - lightsDataKey = renderOrchestrator->MakeDataKey(renderSystem, u8"global", u8"LightingData"); - - vertexBufferNodeHandle = renderOrchestrator->AddVertexBufferBind(renderSystem, renderPassNodeHandle, destinationVertexBuffer, { { GAL::ShaderDataType::FLOAT3 }, { GAL::ShaderDataType::FLOAT3 }, { GAL::ShaderDataType::FLOAT3 }, { GAL::ShaderDataType::FLOAT3 }, { GAL::ShaderDataType::FLOAT2 } }); - indexBufferNodeHandle = renderOrchestrator->AddIndexBufferBind(vertexBufferNodeHandle, destinationIndexBuffer); - meshDataNode = renderOrchestrator->AddDataNode(indexBufferNodeHandle, u8"MeshNode", meshDataBuffer, true); - - if (renderTechniqueName == GTSL::ShortString<16>(u8"Visibility")) { - auto shaderGroupHandle = renderOrchestrator->CreateShaderGroup(u8"VisibilityShaderGroup"); - mainVisibilityPipelineNode = renderOrchestrator->AddMaterial(meshDataNode, shaderGroupHandle); - } - - for (uint32 i = 0; i < renderSystem->GetPipelinedFrames(); ++i) { - renderOrchestrator->buildCommandList[i] = renderSystem->CreateCommandList(u8"Acc. Struct. build", GAL::QueueTypes::COMPUTE, GAL::PipelineStages::ACCELERATION_STRUCTURE_BUILD); - renderOrchestrator->buildAccelerationStructuresWorkloadHandle[i] = renderSystem->CreateWorkload(u8"Build Acc. Structs.", GAL::QueueTypes::COMPUTE, GAL::PipelineStages::ACCELERATION_STRUCTURE_BUILD); - } - - if (rayTracing) { - topLevelAccelerationStructure = renderSystem->CreateTopLevelAccelerationStructure(16); - - setupDirectionShadowRenderPass(renderSystem, renderOrchestrator); - } - - { - renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"AO", u8"SSAO", renderSystem, { RenderPassStructToAttachments(AO_RENDERPASS_DATA), RenderOrchestrator::PassTypes::COMPUTE }, { { u8"Camera Data", renderOrchestrator->cameraDataKeyHandle } }); - } - - { - auto l = { - RenderOrchestrator::PassData::AttachmentReference{ GTSL::StringView(u8"AO"), GTSL::StringView(u8"AO"), GAL::AccessTypes::READ }, - RenderOrchestrator::PassData::AttachmentReference{ GTSL::StringView(u8"Mean"), GTSL::StringView(u8"Mean"), GAL::AccessTypes::WRITE }, - RenderOrchestrator::PassData::AttachmentReference{ GTSL::StringView(u8"Variance"), GTSL::StringView(u8"Variance"), GAL::AccessTypes::WRITE } - }; - - renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"Calculate AO Variance", u8"CalculateVariance", renderSystem, { l, RenderOrchestrator::PassTypes::COMPUTE }, { { u8"Camera Data", renderOrchestrator->cameraDataKeyHandle } }); - } - - { - auto s = renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"Lighting", u8"Lighting", renderSystem, { RenderPassStructToAttachments(LIGHTING_RENDERPASS_DATA), RenderOrchestrator::PassTypes::COMPUTE }, { { u8"Camera Data", renderOrchestrator->cameraDataKeyHandle }, { u8"Lighting Data", lightsDataKey } }); - } - - { - RenderOrchestrator::PassData gammaCorrectionPass; - gammaCorrectionPass.type = RenderOrchestrator::PassTypes::COMPUTE; - gammaCorrectionPass.Attachments.EmplaceBack(GTSL::StringView(u8"Lighting"), GTSL::StringView(u8"Lighting"), GAL::AccessTypes::WRITE); //result attachment - auto gcrpnh = renderOrchestrator->AddRenderPassNode(renderOrchestrator->GetGlobalDataLayer(), u8"GammaCorrection", u8"GammaCorrection", renderSystem, gammaCorrectionPass); - } -} - -void WorldRendererPipeline::onStaticMeshInfoLoaded(TaskInfo taskInfo, StaticMeshResourceManager* staticMeshResourceManager, RenderSystem* render_system, RenderOrchestrator* render_orchestrator, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo) { - auto& resource = resources[staticMeshInfo.GetName()]; - - auto verticesSize = staticMeshInfo.GetVertexSize() * staticMeshInfo.GetVertexCount(), indicesSize = staticMeshInfo.GetIndexCount() * staticMeshInfo.GetIndexSize(); - - resource.VertexSize = staticMeshInfo.GetVertexSize(); - resource.VertexCount = staticMeshInfo.VertexCount; - resource.IndexCount = staticMeshInfo.IndexCount; - resource.IndexType = GAL::SizeToIndexType(staticMeshInfo.IndexSize); - resource.Interleaved = staticMeshInfo.Interleaved; - - resource.VertexComponentsInStream = vertexComponentsPerStream; resource.IndicesInStream = indicesInBuffer; - - for (uint32 i = 0; i < staticMeshInfo.GetSubMeshes().Length; ++i) { - auto& sm = staticMeshInfo.GetSubMeshes().array[i]; - auto shaderGroupHandle = render_orchestrator->CreateShaderGroup(sm.ShaderGroupName); - resource.renderModelHandle = shaderGroupHandle; - - if (renderTechniqueName == u8"Forward") { - RenderOrchestrator::NodeHandle materialNodeHandle = render_orchestrator->AddMaterial(meshDataNode, shaderGroupHandle); - - resource.nodeHandle = render_orchestrator->AddMesh(materialNodeHandle, resource.IndexCount, resource.IndexCount, indicesInBuffer, vertexComponentsPerStream); - } else if (renderTechniqueName == u8"Visibility") { - resource.nodeHandle = render_orchestrator->AddMesh(mainVisibilityPipelineNode, 0, resource.IndexCount, indicesInBuffer, vertexComponentsPerStream); - - //TODO: add to selection buffer - //TODO: add pipeline bind to render pixels with this material - - //render_orchestrator->AddIndirectDispatchNode(); - } - } - - //if unorm or snorm is used to specify data, take that into account as some properties (such as positions) may need scaling as XNORM enconding is defined in the 0->1 / -1->1 range - bool usesxNorm = false; - - for (uint32 ai = 0; ai < staticMeshInfo.GetVertexDescriptor().Length; ++ai) { - auto& t = resource.VertexElements.EmplaceBack(); - - auto& a = staticMeshInfo.GetVertexDescriptor().array[ai]; - for (uint32 bi = 0; bi < a.Length; ++bi) { - auto& b = a.array[bi]; - - t.EmplaceBack(b); - - usesxNorm = IsAnyOf(b, GAL::ShaderDataType::U16_UNORM, GAL::ShaderDataType::U16_UNORM2, GAL::ShaderDataType::U16_UNORM3, GAL::ShaderDataType::U16_UNORM4, GAL::ShaderDataType::U16_SNORM, GAL::ShaderDataType::U16_SNORM2, GAL::ShaderDataType::U16_SNORM3, GAL::ShaderDataType::U16_SNORM4); - } - } - - if (usesxNorm) { - //don't always assign bounding box as scaling factor, as even if we didn't need it bounding boxes usually have little errors which would cause the mesh to be scaled incorrectly - //even though we have the correct coordinates to begin with - resource.ScalingFactor = staticMeshInfo.GetBoundingBox(); - } - - staticMeshResourceManager->LoadStaticMesh(taskInfo.AppManager, staticMeshInfo, vertexComponentsPerStream, render_system->GetBufferRange(sourceVertexBuffer), indicesInBuffer, render_system->GetBufferRange(sourceIndexBuffer), onStaticMeshLoadHandle); - - vertexComponentsPerStream += staticMeshInfo.GetVertexCount(); - indicesInBuffer += staticMeshInfo.GetIndexCount(); -} - -void WorldRendererPipeline::onStaticMeshLoaded(TaskInfo taskInfo, RenderSystem* render_system, StaticMeshSystem* render_group, RenderOrchestrator* render_orchestrator, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo) { - auto& res = resources[staticMeshInfo.GetName()]; - - auto commandListHandle = render_orchestrator->buildCommandList[render_system->GetCurrentFrame()]; - - render_system->AddBufferUpdate(commandListHandle, sourceVertexBuffer, destinationVertexBuffer); render_system->AddBufferUpdate(commandListHandle, sourceIndexBuffer, destinationIndexBuffer); - render_orchestrator->AddVertices(vertexBufferNodeHandle, staticMeshInfo.GetVertexCount()); - render_orchestrator->AddIndices(indexBufferNodeHandle, staticMeshInfo.GetIndexCount()); - - if (rayTracing) { - res.BLAS = render_system->CreateBottomLevelAccelerationStructure(staticMeshInfo.VertexCount, 12/*todo: use actual position stride*/, staticMeshInfo.IndexCount, GAL::SizeToIndexType(staticMeshInfo.IndexSize), destinationVertexBuffer, destinationIndexBuffer, res.VertexComponentsInStream * 12/*todo: use actual position coordinate element size*/, res.IndicesInStream * 2); - pendingBlasUpdates.EmplaceBack(res.BLAS); - } - - for (auto e : res.Instances) { - AddMeshInstance(Id(staticMeshInfo.GetName()), e); - *spherePositionsAndRadius.GetPointer<3>(e()) = staticMeshInfo.BoundingRadius; - } - - res.Loaded = true; - - GTSL::StaticVector, 8> r; - - for (auto& e : res.VertexElements) { - r.EmplaceBack(e.GetRange()); - } -} - -void WorldRendererPipeline::OnAddRenderGroupMesh(TaskInfo task_info, StaticMeshResourceManager* static_mesh_resource_manager, RenderOrchestrator* render_orchestrator, RenderSystem* render_system, StaticMeshSystem* static_mesh_render_group, StaticMeshSystem::StaticMeshHandle static_mesh_handle, GTSL::StaticString<64> resourceName) { - auto resource = resources.TryEmplace(GTSL::StringView(resourceName)); - - const auto instanceIndex = instances.Emplace(); - auto instanceHandle = GetApplicationManager()->MakeHandle(InstanceTypeIndentifier, instanceIndex); - meshToInstanceMap.Emplace(static_mesh_handle, instanceHandle); - - if (resource) { // If resource isn't already loaded - static_mesh_resource_manager->LoadStaticMeshInfo(task_info.AppManager, resourceName, onStaticMeshInfoLoadHandle); - } else { - if (resource.Get().Loaded) { - AddMeshInstance(Id(resourceName), instanceHandle); - } - } - - resource.Get().Instances.EmplaceBack(instanceHandle); -} \ No newline at end of file diff --git a/src/ByteEngine/Render/WorldRenderPipeline.hpp b/src/ByteEngine/Render/WorldRenderPipeline.hpp deleted file mode 100644 index 84ae4831..00000000 --- a/src/ByteEngine/Render/WorldRenderPipeline.hpp +++ /dev/null @@ -1,314 +0,0 @@ -#pragma once - -#include "RenderSystem.h" - -#include "ByteEngine/Game/ApplicationManager.h" -#include -#include "ByteEngine/Render/StaticMeshSystem.h" - -#include "LightsRenderGroup.h" - -class StaticMeshResouceManager; - -class WorldRendererPipeline : public RenderPipeline { -public: - DECLARE_BE_TYPE(Instance) - - WorldRendererPipeline(const InitializeInfo& initialize_info); - - void onAddShaderGroup(RenderOrchestrator* render_orchestrator, RenderSystem* render_system) { - ++shaderGroupCount; - - if (render_orchestrator->tag == GTSL::ShortString<16>(u8"Visibility")) { - auto bwk = render_orchestrator->GetBufferWriteKey(render_system, visibilityDataKey); - bwk[u8"shaderGroupLength"] = shaderGroupCount; - } - } - -private: - DECLARE_BE_TASK(OnAddRenderGroupMesh, BE_RESOURCES(StaticMeshResourceManager*, RenderOrchestrator*, RenderSystem*, StaticMeshSystem*), StaticMeshSystem::StaticMeshHandle, GTSL::StaticString<64>); - DECLARE_BE_TASK(OnUpdateRenderGroupMesh, BE_RESOURCES(RenderSystem*, RenderOrchestrator*), StaticMeshSystem::StaticMeshHandle, GTSL::Matrix3x4); - - DECLARE_BE_TASK(OnAddMesh, BE_RESOURCES(StaticMeshResourceManager*, RenderOrchestrator*, RenderSystem*), InstanceHandle, Id); - DECLARE_BE_TASK(OnUpdateMesh, BE_RESOURCES(RenderSystem*, RenderOrchestrator*), InstanceHandle, GTSL::Matrix3x4); - - TaskHandle onStaticMeshLoadHandle; - TaskHandle onStaticMeshInfoLoadHandle; - - TaskHandle OnAddInfiniteLight; - - TaskHandle OnAddBackdrop; - TaskHandle OnAddParticleSystem; - TaskHandle OnAddVolume; - TaskHandle OnAddSkinnedMesh; - - uint32 shaderGroupCount = 0; - RenderOrchestrator::NodeHandle staticMeshRenderGroup; - - GTSL::MultiVector spherePositionsAndRadius; - GTSL::StaticVector aabss; - - bool rayTracing = false; - RenderSystem::AccelerationStructureHandle topLevelAccelerationStructure; - RenderOrchestrator::NodeHandle vertexBufferNodeHandle, indexBufferNodeHandle, meshDataNode; - RenderOrchestrator::NodeHandle mainVisibilityPipelineNode; - RenderOrchestrator::DataKeyHandle visibilityDataKey, lightsDataKey; - - struct Mesh { - RenderModelHandle MaterialHandle; - RenderSystem::BLASInstanceHandle InstanceHandle; - }; - GTSL::FixedVector instances; - - GTSL::HashMap meshToInstanceMap; - - RenderOrchestrator::DataKeyHandle meshDataBuffer; - - struct Resource { - GTSL::StaticVector, 8> VertexElements; - GTSL::StaticVector Instances; - bool Loaded = false; - uint32 VertexComponentsInStream = 0, IndicesInStream = 0; - uint32 VertexSize, VertexCount = 0, IndexCount = 0; - GAL::IndexType IndexType; - RenderSystem::AccelerationStructureHandle BLAS; - GTSL::Vector3 ScalingFactor = GTSL::Vector3(1.0f); - bool Interleaved = true; - RenderOrchestrator::NodeHandle nodeHandle; - RenderModelHandle renderModelHandle; - }; - GTSL::HashMap resources; - - GTSL::StaticVector pendingBlasUpdates; - GTSL::StaticVector pendingAdditions; - - RenderSystem::BufferHandle sourceVertexBuffer, destinationVertexBuffer, sourceIndexBuffer, destinationIndexBuffer; - uint32 vertexComponentsPerStream = 0, indicesInBuffer = 0; - - RenderOrchestrator::NodeHandle visibilityRenderPassNodeHandle; - - GTSL::StaticString<64> renderTechniqueName = GTSL::StaticString<64>(u8"Forward"); - - static uint32 calculateContiguousMeshBytesWithRouding(const uint32 vertexCount, const uint32 vertexSize, const uint32 indexCount, const uint32 indexSize) { - return GTSL::Math::RoundUpByPowerOf2(vertexCount * vertexSize, 16) + indexCount * indexSize; - } - - void onStaticMeshInfoLoaded(TaskInfo taskInfo, StaticMeshResourceManager* staticMeshResourceManager, RenderSystem* render_system, RenderOrchestrator* render_orchestrator, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo); - - void onStaticMeshLoaded(TaskInfo taskInfo, RenderSystem* render_system, StaticMeshSystem* render_group, RenderOrchestrator* render_orchestrator, StaticMeshResourceManager::StaticMeshInfo staticMeshInfo); - - void OnAddRenderGroupMesh(TaskInfo task_info, StaticMeshResourceManager* static_mesh_resource_manager, RenderOrchestrator* render_orchestrator, RenderSystem* render_system, StaticMeshSystem* static_mesh_render_group, StaticMeshSystem::StaticMeshHandle static_mesh_handle, GTSL::StaticString<64> resourceName); - - void OnAddMesh(TaskInfo, StaticMeshResourceManager* static_mesh_resource_manager, RenderOrchestrator* render_orchestrator, RenderSystem* render_system, InstanceHandle instance_handle, Id resourceName) { - auto& instance = instances[instance_handle()]; - auto& resource = resources[GTSL::StringView(resourceName)]; - - render_orchestrator->AddInstance(meshDataNode, resource.nodeHandle, instance_handle); - - auto key = render_orchestrator->GetBufferWriteKey(render_system, meshDataBuffer); - - instance.MaterialHandle = resource.renderModelHandle; - - const uint32 instanceIndex = render_orchestrator->GetInstanceIndex(meshDataNode, instance_handle); - - key[instanceIndex][u8"vertexBufferOffset"] = resource.VertexComponentsInStream; key[instanceIndex][u8"indexBufferOffset"] = resource.IndicesInStream; - render_orchestrator->SubscribeToUpdate(render_orchestrator->GetShaderGroupIndexUpdateKey(instance.MaterialHandle), key[instanceIndex][u8"shaderGroupIndex"], meshDataBuffer); - key[instanceIndex][u8"transform"] = GTSL::Matrix3x4(); - - if(rayTracing) { - instance.InstanceHandle = render_system->AddBLASToTLAS(topLevelAccelerationStructure, resource.BLAS, instanceIndex, instance.InstanceHandle); - } - } - - void AddMeshInstance(Id resource_name, InstanceHandle instance_handle) { - GetApplicationManager()->EnqueueTask(OnAddMeshTaskHandle, GTSL::MoveRef(instance_handle), GTSL::MoveRef(resource_name)); //Signal can update - } - - void OnUpdateRenderGroupMesh(TaskInfo, RenderSystem* renderSystem, RenderOrchestrator* render_orchestrator, StaticMeshSystem::StaticMeshHandle static_mesh_handle, GTSL::Matrix3x4 transform) { - auto instanceHandle = meshToInstanceMap.At(static_mesh_handle); - GetApplicationManager()->EnqueueTask(OnUpdateMeshTaskHandle, GTSL::MoveRef(instanceHandle), GTSL::MoveRef(transform)); - } - - void OnUpdateMesh(TaskInfo, RenderSystem* renderSystem, RenderOrchestrator* render_orchestrator, InstanceHandle instance_handle, GTSL::Matrix3x4 transform) { - auto key = render_orchestrator->GetBufferWriteKey(renderSystem, meshDataBuffer); - - const auto& instance = instances[instance_handle()]; - - const auto instanceIndex = render_orchestrator->GetInstanceIndex(meshDataNode, instance_handle); - - key[instanceIndex][u8"transform"] = transform; - //*spherePositionsAndRadius.GetPointer<0>(instanceIndex) = transform(0, 3); - //*spherePositionsAndRadius.GetPointer<1>(instanceIndex) = transform(1, 3); - //*spherePositionsAndRadius.GetPointer<2>(instanceIndex) = transform(2, 3); - - if (rayTracing) { - renderSystem->SetInstancePosition(topLevelAccelerationStructure, instance.InstanceHandle, transform); - } - } - - uint32 lights = 0; - - void onAddLight(TaskInfo, RenderSystem* render_system, RenderOrchestrator* render_orchestrator, LightsRenderGroup::PointLightHandle light_handle) { - auto bwk = render_orchestrator->GetBufferWriteKey(render_system, lightsDataKey); - bwk[u8"pointLightsLength"] = ++lights; - //bwk[u8"pointLights"][light_handle()][u8"position"] = GTSL::Vector3(0, 0, 0); - //bwk[u8"pointLights"][light_handle()][u8"color"] = GTSL::Vector3(1, 1, 1); - //bwk[u8"pointLights"][light_handle()][u8"intensity"] = 5.f; - } - - void updateLight(const TaskInfo, RenderSystem* render_system, RenderOrchestrator* render_orchestrator, LightsRenderGroup::PointLightHandle light_handle, GTSL::Vector3 position, GTSL::RGB color, float32 intensity, float32 radius) { - auto bwk = render_orchestrator->GetBufferWriteKey(render_system, lightsDataKey); - bwk[u8"pointLights"][light_handle()][u8"position"] = position; - bwk[u8"pointLights"][light_handle()][u8"color"] = color; - bwk[u8"pointLights"][light_handle()][u8"intensity"] = intensity; - bwk[u8"pointLights"][light_handle()][u8"radius"] = radius; - - bwk[u8"lightCount"] = GTSL::Math::Min(lights, 8); - bwk[u8"lights"][0] = light_handle(); - bwk[u8"lights"][1] = 0u; - bwk[u8"lights"][2] = 1u; - bwk[u8"shadowMapCount"] = 0u; - } - - void preRender(TaskInfo, RenderSystem* render_system, RenderOrchestrator* render_orchestrator) { - ////GTSL::Vector results(GetTransientAllocator()); - ////projectSpheres({0}, spherePositionsAndRadius, results); - // - //{ // Add BLAS instances to TLAS only if dependencies were fulfilled - // auto i = 0; - // - // while (i < pendingAdditions) { - // const auto& addition = pendingAdditions[i]; - // auto e = addition.Second; - // auto& mesh = instances[e()]; - // - // mesh.InstanceHandle = render_system->AddBLASToTLAS(topLevelAccelerationStructure, resources[addition.First].BLAS, e(), mesh.InstanceHandle); - // - // pendingAdditions.Pop(i); - // ++i; - // } - //} - - - auto workloadHandle = render_orchestrator->buildAccelerationStructuresWorkloadHandle[render_system->GetCurrentFrame()]; - render_system->Wait(workloadHandle); - render_system->StartCommandList(render_orchestrator->buildCommandList[render_system->GetCurrentFrame()]); - - if (rayTracing) { - render_system->DispatchBuild(render_orchestrator->buildCommandList[render_system->GetCurrentFrame()], pendingBlasUpdates); - pendingBlasUpdates.Resize(0); - render_system->DispatchBuild(render_orchestrator->buildCommandList[render_system->GetCurrentFrame()], { topLevelAccelerationStructure }); //Update TLAS - } - - render_system->EndCommandList(render_orchestrator->buildCommandList[render_system->GetCurrentFrame()]); - render_system->Submit(GAL::QueueTypes::COMPUTE, { { { render_orchestrator->buildCommandList[render_system->GetCurrentFrame()] }, { }, { workloadHandle } } }, workloadHandle); - } - - void terrain() { - struct TerrainVertex { - GTSL::Vector3 position; GTSL::RGBA color; - }; - - GTSL::Extent3D terrainExtent{ 256, 1, 256 }; - - uint32 vertexCount = (terrainExtent.Width - 1) * (terrainExtent.Depth - 1) * 8; - uint32 indexCount = vertexCount; - - TerrainVertex* vertices = nullptr; uint16* indices = nullptr; - - // Initialize the index into the vertex and index arrays. - uint32 index = 0; - - GTSL::RGBA color; uint32 m_terrainWidth; GTSL::Vector3* m_terrainModel = nullptr, * m_heightMap = nullptr; - - // Load the vertex array and index array with data. - for (uint32 j = 0; j < (terrainExtent.Depth - 1); j++) { - for (uint32 i = 0; i < (terrainExtent.Width - 1); i++) { - // Get the indexes to the four points of the quad. - uint32 index1 = (m_terrainWidth * j) + i; // Upper left. - uint32 index2 = (m_terrainWidth * j) + (i + 1); // Upper right. - uint32 index3 = (m_terrainWidth * (j + 1)) + i; // Bottom left. - uint32 index4 = (m_terrainWidth * (j + 1)) + (i + 1); // Bottom right. - - // Now create two triangles for that quad. - // Triangle 1 - Upper left. - m_terrainModel[index].X() = m_heightMap[index1].X(); - m_terrainModel[index].Y() = m_heightMap[index1].Y(); - m_terrainModel[index].Z() = m_heightMap[index1].Z(); - index++; - - // Triangle 1 - Upper right. - m_terrainModel[index].X() = m_heightMap[index2].X(); - m_terrainModel[index].Y() = m_heightMap[index2].Y(); - m_terrainModel[index].Z() = m_heightMap[index2].Z(); - index++; - - // Triangle 1 - Bottom left. - m_terrainModel[index].X() = m_heightMap[index3].X(); - m_terrainModel[index].Y() = m_heightMap[index3].Y(); - m_terrainModel[index].Z() = m_heightMap[index3].Z(); - index++; - - // Triangle 2 - Bottom left. - m_terrainModel[index].X() = m_heightMap[index3].X(); - m_terrainModel[index].Y() = m_heightMap[index3].Y(); - m_terrainModel[index].Z() = m_heightMap[index3].Z(); - index++; - - // Triangle 2 - Upper right. - m_terrainModel[index].X() = m_heightMap[index2].X(); - m_terrainModel[index].Y() = m_heightMap[index2].Y(); - m_terrainModel[index].Z() = m_heightMap[index2].Z(); - index++; - - // Triangle 2 - Bottom right. - m_terrainModel[index].X() = m_heightMap[index4].X(); - m_terrainModel[index].Y() = m_heightMap[index4].Y(); - m_terrainModel[index].Z() = m_heightMap[index4].Z(); - index++; - } - } - } - - void setupDirectionShadowRenderPass(RenderSystem* renderSystem, RenderOrchestrator* renderOrchestrator) { - renderOrchestrator->RegisterType(u8"global", u8"TraceRayParameterData", TRACE_RAY_PARAMETER_DATA); - - // Global Data - // RenderPassData - // CameraData - // StaticMeshesData - // RayTraceData - - // Make render pass - RenderOrchestrator::PassData pass_data; - pass_data.type = RenderOrchestrator::PassTypes::RAY_TRACING; - pass_data.Attachments = RenderPassStructToAttachments(RT_RENDERPASS_DATA); - RenderOrchestrator::NodeHandle chain = renderOrchestrator->GetGlobalDataLayer(); - - chain = renderOrchestrator->AddRenderPassNode(chain, u8"Sun Shadow", u8"DirectionalShadow", renderSystem, pass_data); - - // Create shader group - auto rayTraceShaderGroupHandle = renderOrchestrator->CreateShaderGroup(u8"DirectionalShadow"); - // Add dispatch - chain = renderOrchestrator->AddDataNode(chain, u8"CameraData", renderOrchestrator->cameraDataKeyHandle); - chain = renderOrchestrator->AddDataNode(chain, u8"InstancesData", meshDataBuffer); - chain = renderOrchestrator->AddDataNode(chain, u8"LightingData", lightsDataKey); //lighting data - chain = renderOrchestrator->addPipelineBindNode(chain, rayTraceShaderGroupHandle); - - - auto dataKeyHandle = renderOrchestrator->MakeDataKey(renderSystem, u8"global", u8"TraceRayParameterData"); - - chain = renderOrchestrator->AddDataNode(chain, u8"RayTraceData", dataKeyHandle); - - renderOrchestrator->AddRayTraceNode(chain, rayTraceShaderGroupHandle); - - auto bwk = renderOrchestrator->GetBufferWriteKey(renderSystem, dataKeyHandle); - bwk[u8"accelerationStructure"] = topLevelAccelerationStructure; - bwk[u8"rayFlags"] = 0u; - bwk[u8"recordOffset"] = 0u; - bwk[u8"recordStride"] = 0u; - bwk[u8"missIndex"] = 0u; - bwk[u8"tMin"] = 0.008f; - bwk[u8"tMax"] = 100.0f; - } -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/AnimationResourceManager.cpp b/src/ByteEngine/Resources/AnimationResourceManager.cpp deleted file mode 100644 index 9f1be767..00000000 --- a/src/ByteEngine/Resources/AnimationResourceManager.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include "AnimationResourceManager.h" - -#include -#include -#include - -#include -#include -#include -#include - -static GTSL::Matrix4 assimpMatrixToMatrix(const aiMatrix4x4 assimpMatrix) -{ - return GTSL::Matrix4( - assimpMatrix.a1, assimpMatrix.a2, assimpMatrix.a3, assimpMatrix.a4, - assimpMatrix.b1, assimpMatrix.b2, assimpMatrix.b3, assimpMatrix.b4, - assimpMatrix.c1, assimpMatrix.c2, assimpMatrix.c3, assimpMatrix.c4, - assimpMatrix.d1, assimpMatrix.d2, assimpMatrix.d3, assimpMatrix.d4 - ); -} - -static Id assimpStringToId(const aiString& aiString) { - return Id(GTSL::Range(aiString.length + 1, aiString.length + 1, reinterpret_cast(aiString.data))); -} - -static GTSL::Vector3 aiVector3DToVector(const aiVector3D assimpVector) { - return GTSL::Vector3(assimpVector.x, assimpVector.y, assimpVector.z); -} - -static GTSL::Quaternion aiQuaternionToQuaternion(const aiQuaternion assimpQuaternion) { - return GTSL::Quaternion(assimpQuaternion.x, assimpQuaternion.y, assimpQuaternion.z, assimpQuaternion.w); -} - -AnimationResourceManager::AnimationResourceManager(const InitializeInfo& initialize_info): ResourceManager(initialize_info, u8"AnimationResourceManager"), animations(32, 0.3f, GetPersistentAllocator()) -{ - initializePackageFiles(packageFiles, GetResourcePath(GTSL::StaticString<32>(u8"Animations"), GTSL::ShortString<32>(u8"bepkg"))); - - auto aa = GetResourcePath(GTSL::StaticString<64>(u8"*.fbx")); - - GTSL::File dic; - - switch (dic.Open(GetResourcePath(GTSL::StaticString<32>(u8"Animations"), GTSL::ShortString<32>(u8"beidx")), GTSL::File::READ | GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: break; - case GTSL::File::OpenResult::CREATED: { - GTSL::FileQuery fileQuery(aa); - - GTSL::HashMap animationDataSerializes(8, GetTransientAllocator()); - GTSL::HashMap skeletonDataSerializes(8, GetTransientAllocator()); - - while (auto query = fileQuery()) { - GTSL::File animationFile; animationFile.Open(GetResourcePath(query.Get()), GTSL::File::READ, false); - GTSL::Buffer buffer(animationFile.GetSize(), 16, GetTransientAllocator()); - animationFile.Read(buffer); - - SkeletonDataSerialize skeletonData(GetPersistentAllocator()); - AnimationDataSerialize animationData(GetPersistentAllocator()); - - GTSL::Buffer skeletonDataBuffer(GTSL::Byte(GTSL::KiloByte(8)).GetCount(), 16, GetTransientAllocator()); - GTSL::Buffer animationDataBuffer(GTSL::Byte(GTSL::KiloByte(8)).GetCount(), 16, GetTransientAllocator()); - - loadSkeleton(static_cast>(buffer), skeletonData, skeletonDataBuffer); - loadAnimation(static_cast>(buffer), animationData, animationDataBuffer); - //todo: serialize data offset - //animationDataSerializes.Emplace(Id(fileQuery.GetFileNameWithExtension()), animationData); - //skeletonDataSerializes.Emplace(Id(fileQuery.GetFileNameWithExtension()), skeletonData); //todo: check skeleton existance - } - - GTSL::Buffer b(2048 * 16, 16, GetTransientAllocator()); - - Insert(animationDataSerializes, b); - - dic.Write(b); - - break; - } - case GTSL::File::OpenResult::ERROR: break; - } - - GTSL::Buffer b(2048 * 16, 16, GetTransientAllocator()); - dic.Read(b); - Extract(animations, b); -} - -void AnimationResourceManager::loadSkeleton(const GTSL::Range sourceBuffer, SkeletonData& skeletonData, - GTSL::Buffer& meshDataBuffer) -{ - Assimp::Importer importer; - const auto* const scene = importer.ReadFileFromMemory(sourceBuffer.begin(), sourceBuffer.Bytes(), - aiProcess_Triangulate | aiProcess_FlipUVs | - aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals | - aiProcess_JoinIdenticalVertices, "fbx"); - - if (scene == nullptr || (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { - BE_LOG_ERROR(reinterpret_cast(importer.GetErrorString())) - return; - } - - aiMesh* mesh = scene->mMeshes[0]; - - for (uint32 b = 0; b < mesh->mNumBones; ++b) { - const auto& assimpBone = mesh->mBones[b]; - - skeletonData.BonesMap.Emplace(GTSL::StringView(assimpStringToId(assimpBone->mName)), b); - auto& bone = skeletonData.Bones.EmplaceBack(GetPersistentAllocator()); - - for (uint32 w = 0; w < assimpBone->mNumWeights; ++w) { - bone.AffectedVertices.EmplaceBack(assimpBone->mWeights[w].mVertexId, assimpBone->mWeights[w].mWeight); - } - - bone.Offset = assimpMatrixToMatrix(mesh->mBones[b]->mOffsetMatrix); - } -} - -void AnimationResourceManager::loadAnimation(const GTSL::Range sourceBuffer, AnimationData& animationData, - GTSL::Buffer& meshDataBuffer) -{ - Assimp::Importer importer; - const auto* const scene = importer.ReadFileFromMemory(sourceBuffer.begin(), sourceBuffer.Bytes(), - aiProcess_Triangulate | aiProcess_FlipUVs | - aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals | - aiProcess_JoinIdenticalVertices); - - if (scene == nullptr || (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { return; } - - aiMesh* mesh = scene->mMeshes[0]; - - //animationData.Frames.Initialize(static_cast(scene->mAnimations[0]->mDuration), GetPersistentAllocator()); - - GTSL::Vector boneNames(128, GetTransientAllocator()); - - for (uint32 b = 0; b < mesh->mNumBones; ++b) - { - const auto& assimpBone = mesh->mBones[b]; - auto name = assimpStringToId(assimpBone->mName); - boneNames.EmplaceBack(name); - } - - for (uint32 a = 0; a < scene->mNumAnimations; ++a) - { - auto& assimpAnimation = scene->mAnimations[a]; //a single animation, e.g. "walk", "run", "shoot" - auto animationName = assimpStringToId(assimpAnimation->mName); - - AnimationData animation(GetPersistentAllocator()); - - BE_ASSERT(assimpAnimation->mDuration - ((float64)(uint64)assimpAnimation->mDuration) != 0.0, - "Animation is not round number"); - animation.FrameCount = static_cast(assimpAnimation->mDuration); - - animation.FPS = static_cast(assimpAnimation->mTicksPerSecond == 0.0 - ? 30.0 - : assimpAnimation->mTicksPerSecond); - - for (uint32 c = 0; c < assimpAnimation->mNumChannels; ++c) { - BE_ASSERT(assimpStringToId(assimpAnimation->mChannels[c]->mNodeName) == boneNames[c], "Order doesn't match"); - } - - for (uint32 frameIndex = 0; frameIndex < animation.FrameCount; ++frameIndex) - { - auto& frame = animation.Frames.EmplaceBack(GetPersistentAllocator()); - //frame.Bones.Initialize(assimpAnimation->mNumChannels, GetPersistentAllocator()); - - for (uint32 b = 0; b < assimpAnimation->mNumChannels; ++b) - { - const auto& assimpChannel = assimpAnimation->mChannels[b]; - - auto nodeName = assimpStringToId(assimpChannel->mNodeName); - - if (assimpChannel->mNumPositionKeys != assimpChannel->mNumRotationKeys != assimpChannel->mNumScalingKeys) - { - BE_LOG_WARNING(u8"Number of keys doesn't match"); - } - - auto& bone = frame.Bones.EmplaceBack(); - - BE_ASSERT( - assimpChannel->mPositionKeys[frameIndex].mTime == - assimpChannel->mRotationKeys[frameIndex].mTime == - assimpChannel->mScalingKeys[frameIndex].mTime, "Time doesn't match"); - - bone.Position = aiVector3DToVector(assimpChannel->mPositionKeys[frameIndex].mValue); - bone.Rotation = aiQuaternionToQuaternion(assimpChannel->mRotationKeys[frameIndex].mValue); - bone.Scale = aiVector3DToVector(assimpChannel->mScalingKeys[frameIndex].mValue); - } - } - } -} diff --git a/src/ByteEngine/Resources/AnimationResourceManager.h b/src/ByteEngine/Resources/AnimationResourceManager.h deleted file mode 100644 index cbcfce05..00000000 --- a/src/ByteEngine/Resources/AnimationResourceManager.h +++ /dev/null @@ -1,148 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "ResourceManager.h" -#include "ByteEngine/Core.h" -#include "ByteEngine/Id.h" -#include "ByteEngine/Application/AllocatorReferences.h" - -class AnimationResourceManager : public ResourceManager -{ -public: - AnimationResourceManager(const InitializeInfo&); - - struct Bone - { - GTSL::Matrix4 Offset; - GTSL::Vector, BE::PAR> AffectedVertices; - - INSERT_START(Bone) - { - Insert(insertInfo.Offset, buffer); - Insert(insertInfo.AffectedVertices, buffer); - } - - EXTRACT_START(Bone) - { - Extract(extractInfo.Offset, buffer); - Extract(extractInfo.AffectedVertices, buffer); - } - - Bone(const BE::PAR& allocator) : AffectedVertices(allocator) {} - }; - - struct SkeletonData : Data - { - GTSL::Vector Bones; - GTSL::HashMap BonesMap; - - SkeletonData(const BE::PAR& allocator) : Bones(allocator), BonesMap(256, 0.1f, allocator) {} - }; - - struct SkeletonDataSerialize : SkeletonData - { - SkeletonDataSerialize(const BE::PAR& allocator) : SkeletonData(allocator) {} - - uint32 ByteOffset = 0; - - INSERT_START(SkeletonDataSerialize) { - INSERT_BODY; - Insert(insertInfo.Bones, buffer); - Insert(insertInfo.BonesMap, buffer); - } - - EXTRACT_START(SkeletonDataSerialize) { - EXTRACT_BODY; - Extract(extractInfo.Bones, buffer); - Extract(extractInfo.BonesMap, buffer); - } - }; - - struct SkeletonInfo : Info - { - //DECL_INFO_CONSTRUCTOR(SkeletonInfo, Info); - }; - - struct AnimationData : Data - { - uint32 FrameCount = 0, FPS = 0; - - struct BoneAnimationData - { - GTSL::Vector3 Position; GTSL::Quaternion Rotation; GTSL::Vector3 Scale; - - INSERT_START(BoneAnimationData) - { - Insert(insertInfo.Position, buffer); - Insert(insertInfo.Rotation, buffer); - Insert(insertInfo.Scale, buffer); - } - - EXTRACT_START(BoneAnimationData) - { - Extract(extractInfo.Position, buffer); - Extract(extractInfo.Rotation, buffer); - Extract(extractInfo.Scale, buffer); - } - }; - - struct Frame - { - Frame(const BE::PAR& allocator) : Bones(allocator) {} - - GTSL::Vector Bones; - - INSERT_START(Frame) - { - Insert(insertInfo.Bones, buffer); - } - - EXTRACT_START(Frame) - { - Extract(extractInfo.Bones, buffer); - } - }; - - GTSL::Vector Frames; - - AnimationData(const BE::PAR& allocator) : Frames(allocator) {} - }; - - struct AnimationDataSerialize : AnimationData - { - uint32 ByteOffset = 0; - - INSERT_START(AnimationDataSerialize) - { - INSERT_BODY; - Insert(insertInfo.FrameCount, buffer); - Insert(insertInfo.FPS, buffer); - //Insert(insertInfo.Frames, buffer); - } - - EXTRACT_START(AnimationDataSerialize) - { - EXTRACT_BODY; - Extract(extractInfo.FrameCount, buffer); - Extract(extractInfo.FPS, buffer); - //Extract(extractInfo.Frames, buffer); - } - - AnimationDataSerialize(const BE::PAR& allocator) : AnimationData(allocator) {} - }; - - struct AnimationInfo : Info - { - DECL_INFO_CONSTRUCTOR(AnimationInfo, Info); - }; - -private: - void loadSkeleton(const GTSL::Range sourceBuffer, SkeletonData& skeletonData, GTSL::Buffer& meshDataBuffer); - void loadAnimation(const GTSL::Range sourceBuffer, AnimationData& animationData, GTSL::Buffer& meshDataBuffer); - - GTSL::HashMap animations; - GTSL::StaticVector packageFiles; -}; diff --git a/src/ByteEngine/Resources/AudioResourceManager.cpp b/src/ByteEngine/Resources/AudioResourceManager.cpp deleted file mode 100644 index 231bac54..00000000 --- a/src/ByteEngine/Resources/AudioResourceManager.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "AudioResourceManager.h" - -#include -#include - -#include "ByteEngine/Debug/Assert.h" - -#include "ByteEngine/Application/Application.h" - -AudioResourceManager::AudioResourceManager(const InitializeInfo& initialize_info) : ResourceManager(initialize_info, u8"AudioResourceManager"), audioResourceInfos(8, 0.25, GetPersistentAllocator()) -{ - indexFile.Open(GetResourcePath(u8"Audio.beidx"), GTSL::File::WRITE | GTSL::File::READ, true); - - GTSL::Buffer file_buffer(2048 * 2048, 32, GetTransientAllocator()); - - if(indexFile.Read(file_buffer)) - { - Extract(audioResourceInfos, file_buffer); - } else { - GTSL::File packageFile(GetResourcePath(u8"Audio.bepkg"), GTSL::File::WRITE, true); - - GTSL::FileQuery file_query(GetUserResourcePath(u8"*.wav")); - - while(auto queryResult = file_query()) { - auto fileName = queryResult.Get(); RTrimLast(fileName, u8'.'); - const auto hashed_name = Id(fileName); - - if (!audioResourceInfos.Find(GTSL::StringView(fileName))) { - GTSL::File query_file(GetUserResourcePath(queryResult.Get()), GTSL::File::READ, false); - - GTSL::Buffer wavBuffer(query_file.GetSize(), 8, GetTransientAllocator()); - - query_file.Read(wavBuffer); - - AudioDataSerialize data; - - uint8 riff[4]; // RIFF string - uint32 overall_size = 0; // overall size of file in bytes - uint8 wave[4]; // WAVE string - uint8 fmt_chunk_marker[4]; // fmt string with trailing null char - uint32 length_of_fmt = 0; // length of the format data - uint16 format_type = 0; // format type. 1-PCM, 3- IEEE float, 6 - 8bit A law, 7 - 8bit mu law - uint16 channels = 0; // no.of channels - uint32 sample_rate = 0; // sampling rate (blocks per second) - uint32 byte_rate = 0; // SampleRate * NumChannels * BitsPerSample/8 - uint16 block_align = 0; // NumChannels * BitsPerSample/8 - uint16 bits_per_sample = 0; // bits per sample, 8- 8bits, 16- 16 bits etc - uint8 data_chunk_header[4]; // DATA string or FLLR string - uint32 data_size = 0; // NumSamples * NumChannels * BitsPerSample/8 - size of the next chunk that will be read - - wavBuffer >> riff[0] >> riff[1] >> riff[2] >> riff[3]; - BE_ASSERT(riff[0] == 'R' && riff[1] == 'I' && riff[2] == 'F' && riff[3] == 'F', "No RIFF"); - - Extract(overall_size, wavBuffer); - wavBuffer.Read(4, wave); BE_ASSERT(wave[0] == 'W' && wave[1] == 'A' && wave[2] == 'V' && wave[3] == 'E', "No WAVE"); - wavBuffer.Read(4, fmt_chunk_marker); BE_ASSERT(fmt_chunk_marker[0] == 'f' && fmt_chunk_marker[1] == 'm' && fmt_chunk_marker[2] == 't' && fmt_chunk_marker[3] == 32, "No fmt"); - Extract(length_of_fmt, wavBuffer); BE_ASSERT(length_of_fmt == 16, "Unsupported"); - Extract(format_type, wavBuffer); BE_ASSERT(format_type == 1, "Format is not PCM, unsupported!"); - Extract(channels, wavBuffer); - Extract(sample_rate, wavBuffer); - Extract(byte_rate, wavBuffer); //(Sample Rate * BitsPerSample * Channels) / 8. - Extract(block_align, wavBuffer); - Extract(bits_per_sample, wavBuffer); - - data.ChannelCount = static_cast(channels); - data.SampleRate = sample_rate; - data.BitDepth = static_cast(bits_per_sample); - - wavBuffer.Read(4, data_chunk_header); BE_ASSERT(data_chunk_header[0] == 'd' && data_chunk_header[1] == 'a' && data_chunk_header[2] == 't' && data_chunk_header[3] == 'a', "No data"); - Extract(data_size, wavBuffer); - - data.Frames = data_size / channels / (bits_per_sample / 8); - - data.ByteOffset = (uint32)packageFile.GetSize(); - - packageFile.Write(GTSL::Range(data_size, wavBuffer.GetData() + wavBuffer.GetReadPosition())); - - audioResourceInfos.Emplace(GTSL::StringView(hashed_name), data); - } - } - - file_buffer.Clear(); - Insert(audioResourceInfos, file_buffer); - indexFile.Write(file_buffer); - } - - initializePackageFiles(packageFiles, GetResourcePath(u8"Audio.bepkg")); -} - -AudioResourceManager::~AudioResourceManager() -{ -} diff --git a/src/ByteEngine/Resources/AudioResourceManager.h b/src/ByteEngine/Resources/AudioResourceManager.h deleted file mode 100644 index 2ca043bf..00000000 --- a/src/ByteEngine/Resources/AudioResourceManager.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -#include -#include -#include - -#include "ResourceManager.h" -#include "ByteEngine/Game/ApplicationManager.h" - -class AudioResourceManager final : public ResourceManager -{ -public: - struct AudioData : Data - { - uint32 Frames; - uint32 SampleRate; - uint8 ChannelCount; - uint8 BitDepth; - }; - - struct AudioDataSerialize : DataSerialize - { - INSERT_START(AudioDataSerialize) - { - INSERT_BODY - Insert(insertInfo.Frames, buffer); - Insert(insertInfo.SampleRate, buffer); - Insert(insertInfo.ChannelCount, buffer); - Insert(insertInfo.BitDepth, buffer); - } - - EXTRACT_START(AudioDataSerialize) - { - EXTRACT_BODY - Extract(extractInfo.Frames, buffer); - Extract(extractInfo.SampleRate, buffer); - Extract(extractInfo.ChannelCount, buffer); - Extract(extractInfo.BitDepth, buffer); - } - }; - - struct AudioInfo : Info - { - DECL_INFO_CONSTRUCTOR(AudioInfo, Info) - - uint32 GetAudioSize() - { - return Frames * ChannelCount * (BitDepth / 8); - } - }; - - AudioResourceManager(const InitializeInfo&); - - ~AudioResourceManager(); - - template - void LoadAudioInfo(Id audioName, TaskHandle dynamicTaskHandle, ARGS&&... args) { - GetApplicationManager()->EnqueueTask(GetApplicationManager()->RegisterTask(this, u8"loadAudioInfo", {}, &AudioResourceManager::loadAudioInfo, {}, {}), GTSL::MoveRef(audioName), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - - //Audio data is aligned to 16 bytes - template - void LoadAudio(AudioInfo audioInfo, GTSL::Range buffer, TaskHandle, ARGS...> dynamicTaskHandle, ARGS&&... args) { - GetApplicationManager()->EnqueueTask(GetApplicationManager()->RegisterTask(this, u8"loadAudio", {}, &AudioResourceManager::loadAudio, {}, {}), GTSL::MoveRef(audioInfo), GTSL::MoveRef(buffer), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - -private: - template - auto loadAudioInfo(TaskInfo taskInfo, Id audioName, TaskHandle dynamicTaskHandle, ARGS&&... args) { - auto audioInfoSerialize = audioResourceInfos.At(GTSL::StringView(audioName)); - - AudioInfo audioInfo(audioName, audioInfoSerialize); - - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(audioInfo), GTSL::ForwardRef(args)...); - } - - template - auto loadAudio(TaskInfo taskInfo, AudioInfo audioInfo, GTSL::Range buffer, TaskHandle, ARGS...> dynamicTaskHandle, ARGS&&... args) { - uint32 bytes = audioInfo.GetAudioSize(); - - packageFiles[getThread()].SetPointer(audioInfo.ByteOffset); - packageFiles[getThread()].Read(bytes, buffer.begin()); - - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(audioInfo), GTSL::Range(bytes, buffer.begin()), GTSL::ForwardRef(args)...); - } - - GTSL::File indexFile; - GTSL::HashMap audioResourceInfos; - - GTSL::StaticVector packageFiles; -}; diff --git a/src/ByteEngine/Resources/BC7.cpp b/src/ByteEngine/Resources/BC7.cpp deleted file mode 100644 index 012e1374..00000000 --- a/src/ByteEngine/Resources/BC7.cpp +++ /dev/null @@ -1,2702 +0,0 @@ -// File: bc7enc.h - Richard Geldreich, Jr. - MIT license or public domain (see end of bc7enc.c) -// If you use this software in a product, attribution / credits is requested but not required. -#include -#include -#include -#include - -#include "ByteEngine/Core.h" - -static constexpr uint8 BC7ENC_BLOCK_SIZE = 16; -static constexpr uint8 BC7ENC_MAX_PARTITIONS = 64; -static constexpr uint8 BC7ENC_MAX_UBER_LEVEL = 4; - -struct color_rgba { uint8_t m_c[4]; }; - -struct bc7enc_compress_block_params -{ - uint32_t m_mode_mask; - - // m_max_partitions may range from 0 (disables mode 1) to BC7ENC_MAX_PARTITIONS. The higher this value, the slower the compressor, but the higher the quality. - uint32_t m_max_partitions; - - // Relative RGBA or YCbCrA weights. - uint32_t m_weights[4]; - - // m_uber_level may range from 0 to BC7ENC_MAX_UBER_LEVEL. The higher this value, the slower the compressor, but the higher the quality. - uint32_t m_uber_level; - - // If m_perceptual is true, colorspace error is computed in YCbCr space, otherwise RGB. - bool m_perceptual; - - // Set m_try_least_squares to false for slightly faster/lower quality compression. - bool m_try_least_squares; - - // When m_mode17_partition_estimation_filterbank, the mode1 partition estimator skips lesser used partition patterns unless they are strongly predicted to be potentially useful. - // There's a slight loss in quality with this enabled (around .08 dB RGB PSNR or .05 dB Y PSNR), but up to a 11% gain in speed depending on the other settings. - bool m_mode17_partition_estimation_filterbank; - - bool m_force_alpha; - - bool m_force_selectors; - uint8_t m_selectors[16]; - - bool m_quant_mode6_endpoints; - bool m_bias_mode1_pbits; - - float m_pbit1_weight; - - float m_mode1_error_weight; - float m_mode5_error_weight; - float m_mode6_error_weight; - float m_mode7_error_weight; - - float m_low_frequency_partition_weight; - - void clear() - { - memset(this, 0, sizeof(*this)); - } - - void print() - { - printf("Mode mask: 0x%X\n", m_mode_mask); - printf("Max partitions: %u\n", m_max_partitions); - printf("Weights: %u %u %u %u\n", m_weights[0], m_weights[1], m_weights[2], m_weights[3]); - printf("Uber level: %u\n", m_uber_level); - printf("Perceptual: %u\n", m_perceptual); - printf("Try least squares: %u\n", m_try_least_squares); - printf("Mode 1/7 partition estimation filterbank: %u\n", m_mode17_partition_estimation_filterbank); - printf("Force alpha: %u\n", m_force_alpha); - printf("Quant mode 6 endpoints: %u\n", m_quant_mode6_endpoints); - printf("Bias mode 1 p-bits: %u\n", m_bias_mode1_pbits); - printf("p-bit 1 weight: %f\n", m_pbit1_weight); - printf("Mode error weights: %f %f %f %f\n", m_mode1_error_weight, m_mode5_error_weight, m_mode6_error_weight, m_mode7_error_weight); - printf("Low frequency partition weight: %f\n", m_low_frequency_partition_weight); - } -}; - -inline void bc7enc_compress_block_params_init_linear_weights(bc7enc_compress_block_params* p) -{ - p->m_perceptual = false; - p->m_weights[0] = 1; - p->m_weights[1] = 1; - p->m_weights[2] = 1; - p->m_weights[3] = 1; -} - -inline void bc7enc_compress_block_params_init_perceptual_weights(bc7enc_compress_block_params* p) -{ - p->m_perceptual = true; - p->m_weights[0] = 128; - p->m_weights[1] = 64; - p->m_weights[2] = 16; - p->m_weights[3] = 32; -} - -inline void bc7enc_compress_block_params_init(bc7enc_compress_block_params* p) -{ - p->m_mode_mask = UINT32_MAX; - p->m_max_partitions = BC7ENC_MAX_PARTITIONS; - p->m_try_least_squares = true; - p->m_mode17_partition_estimation_filterbank = true; - p->m_uber_level = 0; - p->m_force_selectors = false; - p->m_force_alpha = false; - p->m_quant_mode6_endpoints = false; - p->m_bias_mode1_pbits = false; - p->m_pbit1_weight = 1.0f; - p->m_mode1_error_weight = 1.0f; - p->m_mode5_error_weight = 1.0f; - p->m_mode6_error_weight = 1.0f; - p->m_mode7_error_weight = 1.0f; - p->m_low_frequency_partition_weight = 1.0f; - bc7enc_compress_block_params_init_perceptual_weights(p); -} - -// bc7enc_compress_block_init() MUST be called before calling bc7enc_compress_block() (or you'll get artifacts). -void bc7enc_compress_block_init(); - -// Packs a single block of 16x16 RGBA pixels (R first in memory) to 128-bit BC7 block pBlock, using either mode 1 and/or 6. -// Alpha blocks will always use mode 6, and by default opaque blocks will use either modes 1 or 6. -// Returns true if the block had any pixels with alpha < 255, otherwise it return false. (This is not an error code - a block is always encoded.) -bool bc7enc_compress_block(void* pBlock, const void* pPixelsRGBA, const bc7enc_compress_block_params* pComp_params); - -// File: bc7enc.c - Richard Geldreich, Jr. 3/31/2020 - MIT license or public domain (see end of file) -// Currently supports modes 1, 6 for RGB blocks, and modes 5, 6, 7 for RGBA blocks. -#include -#include -#include -#include - -// Helpers -static inline int32_t clampi(int32_t value, int32_t low, int32_t high) { if (value < low) value = low; else if (value > high) value = high; return value; } -static inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; } -static inline float saturate(float value) { return clampf(value, 0, 1.0f); } -static inline uint8_t minimumub(uint8_t a, uint8_t b) { return (a < b) ? a : b; } -static inline int32_t minimumi(int32_t a, int32_t b) { return (a < b) ? a : b; } -static inline uint32_t minimumu(uint32_t a, uint32_t b) { return (a < b) ? a : b; } -static inline float minimumf(float a, float b) { return (a < b) ? a : b; } -static inline uint8_t maximumub(uint8_t a, uint8_t b) { return (a > b) ? a : b; } -static inline uint32_t maximumu(uint32_t a, uint32_t b) { return (a > b) ? a : b; } -static inline int32_t maximumi(int32_t a, int32_t b) { return (a > b) ? a : b; } -static inline float maximumf(float a, float b) { return (a > b) ? a : b; } -static inline int squarei(int i) { return i * i; } -static inline float squaref(float i) { return i * i; } -template inline T0 lerp(T0 a, T0 b, T1 c) { return a + (b - a) * c; } - -static inline int32_t iabs32(int32_t v) { uint32_t msk = v >> 31; return (v ^ msk) - msk; } -static inline void swapub(uint8_t* a, uint8_t* b) { uint8_t t = *a; *a = *b; *b = t; } -static inline void swapu(uint32_t* a, uint32_t* b) { uint32_t t = *a; *a = *b; *b = t; } -static inline void swapf(float* a, float* b) { float t = *a; *a = *b; *b = t; } - -struct vec4F { float m_c[4]; }; - -static inline color_rgba* color_quad_u8_set_clamped(color_rgba* pRes, int32_t r, int32_t g, int32_t b, int32_t a) { pRes->m_c[0] = (uint8_t)clampi(r, 0, 255); pRes->m_c[1] = (uint8_t)clampi(g, 0, 255); pRes->m_c[2] = (uint8_t)clampi(b, 0, 255); pRes->m_c[3] = (uint8_t)clampi(a, 0, 255); return pRes; } -static inline color_rgba* color_quad_u8_set(color_rgba* pRes, int32_t r, int32_t g, int32_t b, int32_t a) { assert((uint32_t)(r | g | b | a) <= 255); pRes->m_c[0] = (uint8_t)r; pRes->m_c[1] = (uint8_t)g; pRes->m_c[2] = (uint8_t)b; pRes->m_c[3] = (uint8_t)a; return pRes; } -static inline bool color_quad_u8_notequals(const color_rgba* pLHS, const color_rgba* pRHS) { return (pLHS->m_c[0] != pRHS->m_c[0]) || (pLHS->m_c[1] != pRHS->m_c[1]) || (pLHS->m_c[2] != pRHS->m_c[2]) || (pLHS->m_c[3] != pRHS->m_c[3]); } -static inline vec4F* vec4F_set_scalar(vec4F* pV, float x) { pV->m_c[0] = x; pV->m_c[1] = x; pV->m_c[2] = x; pV->m_c[3] = x; return pV; } -static inline vec4F* vec4F_set(vec4F* pV, float x, float y, float z, float w) { pV->m_c[0] = x; pV->m_c[1] = y; pV->m_c[2] = z; pV->m_c[3] = w; return pV; } -static inline vec4F* vec4F_saturate_in_place(vec4F* pV) { pV->m_c[0] = saturate(pV->m_c[0]); pV->m_c[1] = saturate(pV->m_c[1]); pV->m_c[2] = saturate(pV->m_c[2]); pV->m_c[3] = saturate(pV->m_c[3]); return pV; } -static inline vec4F vec4F_saturate(const vec4F* pV) { vec4F res; res.m_c[0] = saturate(pV->m_c[0]); res.m_c[1] = saturate(pV->m_c[1]); res.m_c[2] = saturate(pV->m_c[2]); res.m_c[3] = saturate(pV->m_c[3]); return res; } -static inline vec4F vec4F_from_color(const color_rgba* pC) { vec4F res; vec4F_set(&res, pC->m_c[0], pC->m_c[1], pC->m_c[2], pC->m_c[3]); return res; } -static inline vec4F vec4F_add(const vec4F* pLHS, const vec4F* pRHS) { vec4F res; vec4F_set(&res, pLHS->m_c[0] + pRHS->m_c[0], pLHS->m_c[1] + pRHS->m_c[1], pLHS->m_c[2] + pRHS->m_c[2], pLHS->m_c[3] + pRHS->m_c[3]); return res; } -static inline vec4F vec4F_sub(const vec4F* pLHS, const vec4F* pRHS) { vec4F res; vec4F_set(&res, pLHS->m_c[0] - pRHS->m_c[0], pLHS->m_c[1] - pRHS->m_c[1], pLHS->m_c[2] - pRHS->m_c[2], pLHS->m_c[3] - pRHS->m_c[3]); return res; } -static inline float vec4F_dot(const vec4F* pLHS, const vec4F* pRHS) { return pLHS->m_c[0] * pRHS->m_c[0] + pLHS->m_c[1] * pRHS->m_c[1] + pLHS->m_c[2] * pRHS->m_c[2] + pLHS->m_c[3] * pRHS->m_c[3]; } -static inline vec4F vec4F_mul(const vec4F* pLHS, float s) { vec4F res; vec4F_set(&res, pLHS->m_c[0] * s, pLHS->m_c[1] * s, pLHS->m_c[2] * s, pLHS->m_c[3] * s); return res; } -static inline vec4F* vec4F_normalize_in_place(vec4F* pV) { float s = pV->m_c[0] * pV->m_c[0] + pV->m_c[1] * pV->m_c[1] + pV->m_c[2] * pV->m_c[2] + pV->m_c[3] * pV->m_c[3]; if (s != 0.0f) { s = 1.0f / sqrtf(s); pV->m_c[0] *= s; pV->m_c[1] *= s; pV->m_c[2] *= s; pV->m_c[3] *= s; } return pV; } - -// Various BC7 tables -static const uint32_t g_bc7_weights2[4] = { 0, 21, 43, 64 }; -static const uint32_t g_bc7_weights3[8] = { 0, 9, 18, 27, 37, 46, 55, 64 }; -static const uint32_t g_bc7_weights4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; -// Precomputed weight constants used during least fit determination. For each entry in g_bc7_weights[]: w * w, (1.0f - w) * w, (1.0f - w) * (1.0f - w), w -static const float g_bc7_weights2x[4 * 4] = { 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.107666f, 0.220459f, 0.451416f, 0.328125f, 0.451416f, 0.220459f, 0.107666f, 0.671875f, 1.000000f, 0.000000f, 0.000000f, 1.000000f }; -static const float g_bc7_weights3x[8 * 4] = { 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.019775f, 0.120850f, 0.738525f, 0.140625f, 0.079102f, 0.202148f, 0.516602f, 0.281250f, 0.177979f, 0.243896f, 0.334229f, 0.421875f, 0.334229f, 0.243896f, 0.177979f, 0.578125f, 0.516602f, 0.202148f, - 0.079102f, 0.718750f, 0.738525f, 0.120850f, 0.019775f, 0.859375f, 1.000000f, 0.000000f, 0.000000f, 1.000000f }; -static const float g_bc7_weights4x[16 * 4] = { 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.003906f, 0.058594f, 0.878906f, 0.062500f, 0.019775f, 0.120850f, 0.738525f, 0.140625f, 0.041260f, 0.161865f, 0.635010f, 0.203125f, 0.070557f, 0.195068f, 0.539307f, 0.265625f, 0.107666f, 0.220459f, - 0.451416f, 0.328125f, 0.165039f, 0.241211f, 0.352539f, 0.406250f, 0.219727f, 0.249023f, 0.282227f, 0.468750f, 0.282227f, 0.249023f, 0.219727f, 0.531250f, 0.352539f, 0.241211f, 0.165039f, 0.593750f, 0.451416f, 0.220459f, 0.107666f, 0.671875f, 0.539307f, 0.195068f, 0.070557f, 0.734375f, - 0.635010f, 0.161865f, 0.041260f, 0.796875f, 0.738525f, 0.120850f, 0.019775f, 0.859375f, 0.878906f, 0.058594f, 0.003906f, 0.937500f, 1.000000f, 0.000000f, 0.000000f, 1.000000f }; - -static const uint8_t g_bc7_partition1[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -static const uint8_t g_bc7_partition2[64 * 16] = -{ - 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1, 0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1, 0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1, - 0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1, 0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, - 0,0,0,0,1,0,0,0,1,1,1,0,1,1,1,1, 0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0, 0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0, 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1, - 0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0, 0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0, 0,0,0,1,0,1,1,1,1,1,1,0,1,0,0,0, 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, 0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0, 0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0, - 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, 0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0, 0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0, 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0, 0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0, 0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1, 0,1,0,1,1,0,1,0,1,0,1,0,0,1,0,1, - 0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,0, 0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0, 0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0, 0,0,1,1,1,0,1,1,1,1,0,1,1,1,0,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1, 0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1, 0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0, - 0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0, 0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0, 0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0, 0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0, 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0, - 0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1, 0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1, 0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,1, 0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1, 0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0, 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0, 0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1 -}; - -static const uint8_t g_bc7_partition3[64 * 16] = -{ - 0,0,1,1,0,0,1,1,0,2,2,1,2,2,2,2, 0,0,0,1,0,0,1,1,2,2,1,1,2,2,2,1, 0,0,0,0,2,0,0,1,2,2,1,1,2,2,1,1, 0,2,2,2,0,0,2,2,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2, 0,0,1,1,0,0,1,1,0,0,2,2,0,0,2,2, 0,0,2,2,0,0,2,2,1,1,1,1,1,1,1,1, 0,0,1,1,0,0,1,1,2,2,1,1,2,2,1,1, - 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2, 0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2, 0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2, 0,1,2,2,0,1,2,2,0,1,2,2,0,1,2,2, 0,0,1,1,0,1,1,2,1,1,2,2,1,2,2,2, 0,0,1,1,2,0,0,1,2,2,0,0,2,2,2,0, - 0,0,0,1,0,0,1,1,0,1,1,2,1,1,2,2, 0,1,1,1,0,0,1,1,2,0,0,1,2,2,0,0, 0,0,0,0,1,1,2,2,1,1,2,2,1,1,2,2, 0,0,2,2,0,0,2,2,0,0,2,2,1,1,1,1, 0,1,1,1,0,1,1,1,0,2,2,2,0,2,2,2, 0,0,0,1,0,0,0,1,2,2,2,1,2,2,2,1, 0,0,0,0,0,0,1,1,0,1,2,2,0,1,2,2, 0,0,0,0,1,1,0,0,2,2,1,0,2,2,1,0, - 0,1,2,2,0,1,2,2,0,0,1,1,0,0,0,0, 0,0,1,2,0,0,1,2,1,1,2,2,2,2,2,2, 0,1,1,0,1,2,2,1,1,2,2,1,0,1,1,0, 0,0,0,0,0,1,1,0,1,2,2,1,1,2,2,1, 0,0,2,2,1,1,0,2,1,1,0,2,0,0,2,2, 0,1,1,0,0,1,1,0,2,0,0,2,2,2,2,2, 0,0,1,1,0,1,2,2,0,1,2,2,0,0,1,1, 0,0,0,0,2,0,0,0,2,2,1,1,2,2,2,1, - 0,0,0,0,0,0,0,2,1,1,2,2,1,2,2,2, 0,2,2,2,0,0,2,2,0,0,1,2,0,0,1,1, 0,0,1,1,0,0,1,2,0,0,2,2,0,2,2,2, 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0, 0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0, 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0, 0,1,2,0,2,0,1,2,1,2,0,1,0,1,2,0, 0,0,1,1,2,2,0,0,1,1,2,2,0,0,1,1, - 0,0,1,1,1,1,2,2,2,2,0,0,0,0,1,1, 0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,2,1,2,1,2,1, 0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2, 0,0,2,2,0,0,1,1,0,0,2,2,0,0,1,1, 0,2,2,0,1,2,2,1,0,2,2,0,1,2,2,1, 0,1,0,1,2,2,2,2,2,2,2,2,0,1,0,1, 0,0,0,0,2,1,2,1,2,1,2,1,2,1,2,1, - 0,1,0,1,0,1,0,1,0,1,0,1,2,2,2,2, 0,2,2,2,0,1,1,1,0,2,2,2,0,1,1,1, 0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,2, 0,0,0,0,2,1,1,2,2,1,1,2,2,1,1,2, 0,2,2,2,0,1,1,1,0,1,1,1,0,2,2,2, 0,0,0,2,1,1,1,2,1,1,1,2,0,0,0,2, 0,1,1,0,0,1,1,0,0,1,1,0,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,1,2,2,1,1,2, - 0,1,1,0,0,1,1,0,2,2,2,2,2,2,2,2, 0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2, 0,0,2,2,1,1,2,2,1,1,2,2,0,0,2,2, 0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,2, 0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,1, 0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2, 0,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2, 0,1,1,1,2,0,1,1,2,2,0,1,2,2,2,0, -}; - -static const uint8_t g_bc7_table_anchor_index_third_subset_1[64] = -{ - 3, 3,15,15, 8, 3,15,15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8,15, 3, 3, 6,10, 5, 8, 8, 6, 8, 5,15,15, 8,15, 3, 5, 6,10, 8,15, 15, 3,15, 5,15,15,15,15, 3,15, 5, 5, 5, 8, 5,10, 5,10, 8,13,15,12, 3, 3 -}; - -static const uint8_t g_bc7_table_anchor_index_third_subset_2[64] = -{ - 15, 8, 8, 3,15,15, 3, 8, 15,15,15,15,15,15,15, 8, 15, 8,15, 3,15, 8,15, 8, 3,15, 6,10,15,15,10, 8, 15, 3,15,10,10, 8, 9,10, 6,15, 8,15, 3, 6, 6, 8, 15, 3,15,15,15,15,15,15, 15,15,15,15, 3,15,15, 8 -}; - -static const uint8_t g_bc7_table_anchor_index_second_subset[64] = { 15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15, 15, 2, 8, 2, 2, 8, 8,15, 2, 8, 2, 2, 8, 8, 2, 2, 15,15, 6, 8, 2, 8,15,15, 2, 8, 2, 2, 2,15,15, 6, 6, 2, 6, 8,15,15, 2, 2, 15,15,15,15,15, 2, 2,15 }; -static const uint8_t g_bc7_num_subsets[8] = { 3, 2, 3, 2, 1, 1, 1, 2 }; -static const uint8_t g_bc7_partition_bits[8] = { 4, 6, 6, 6, 0, 0, 0, 6 }; -static const uint8_t g_bc7_color_index_bitcount[8] = { 3, 3, 2, 2, 2, 2, 4, 2 }; -static int get_bc7_color_index_size(int mode, int index_selection_bit) { return g_bc7_color_index_bitcount[mode] + index_selection_bit; } -static uint8_t g_bc7_alpha_index_bitcount[8] = { 0, 0, 0, 0, 3, 2, 4, 2 }; -static int get_bc7_alpha_index_size(int mode, int index_selection_bit) { return g_bc7_alpha_index_bitcount[mode] - index_selection_bit; } -static const uint8_t g_bc7_mode_has_p_bits[8] = { 1, 1, 0, 1, 0, 0, 1, 1 }; -static const uint8_t g_bc7_mode_has_shared_p_bits[8] = { 0, 1, 0, 0, 0, 0, 0, 0 }; -static const uint8_t g_bc7_color_precision_table[8] = { 4, 6, 5, 7, 5, 7, 7, 5 }; -static const int8_t g_bc7_alpha_precision_table[8] = { 0, 0, 0, 0, 6, 8, 7, 5 }; -static bool get_bc7_mode_has_seperate_alpha_selectors(int mode) { return (mode == 4) || (mode == 5); } - -typedef struct { uint16_t m_error; uint8_t m_lo; uint8_t m_hi; } endpoint_err; - -static endpoint_err g_bc7_mode_1_optimal_endpoints[256][2]; // [c][pbit] -static const uint32_t BC7ENC_MODE_1_OPTIMAL_INDEX = 2; - -static endpoint_err g_bc7_mode_7_optimal_endpoints[256][2][2]; // [c][pbit][hp][lp] -const uint32_t BC7E_MODE_7_OPTIMAL_INDEX = 1; - -static float g_mode1_rgba_midpoints[64][2]; -static float g_mode5_rgba_midpoints[128]; -static float g_mode7_rgba_midpoints[32][2]; - -static uint8_t g_mode6_reduced_quant[2048][2]; - -static bool g_initialized; - -// Initialize the lookup table used for optimal single color compression in mode 1/7. Must be called before encoding. -void bc7enc_compress_block_init() -{ - if (g_initialized) - return; - - // Mode 7 endpoint midpoints - for (uint32_t p = 0; p < 2; p++) - { - for (uint32_t i = 0; i < 32; i++) - { - uint32_t vl = ((i << 1) | p) << 2; - vl |= (vl >> 6); - float lo = vl / 255.0f; - - uint32_t vh = ((minimumi(31, (i + 1)) << 1) | p) << 2; - vh |= (vh >> 6); - float hi = vh / 255.0f; - - //g_mode7_quant_values[i][p] = lo; - if (i == 31) - g_mode7_rgba_midpoints[i][p] = 1.0f; - else - g_mode7_rgba_midpoints[i][p] = (lo + hi) / 2.0f; - } - } - - // Mode 1 endpoint midpoints - for (uint32_t p = 0; p < 2; p++) - { - for (uint32_t i = 0; i < 64; i++) - { - uint32_t vl = ((i << 1) | p) << 1; - vl |= (vl >> 7); - float lo = vl / 255.0f; - - uint32_t vh = ((minimumi(63, (i + 1)) << 1) | p) << 1; - vh |= (vh >> 7); - float hi = vh / 255.0f; - - //g_mode1_quant_values[i][p] = lo; - if (i == 63) - g_mode1_rgba_midpoints[i][p] = 1.0f; - else - g_mode1_rgba_midpoints[i][p] = (lo + hi) / 2.0f; - } - } - - // Mode 5 endpoint midpoints - for (uint32_t i = 0; i < 128; i++) - { - uint32_t vl = (i << 1); - vl |= (vl >> 7); - float lo = vl / 255.0f; - - uint32_t vh = minimumi(127, i + 1) << 1; - vh |= (vh >> 7); - float hi = vh / 255.0f; - - if (i == 127) - g_mode5_rgba_midpoints[i] = 1.0f; - else - g_mode5_rgba_midpoints[i] = (lo + hi) / 2.0f; - } - - for (uint32_t p = 0; p < 2; p++) - { - for (uint32_t i = 0; i < 2048; i++) - { - float f = i / 2047.0f; - - float best_err = 1e+9f; - int best_index = 0; - for (int j = 0; j < 64; j++) - { - int ik = (j * 127 + 31) / 63; - float k = ((ik << 1) + p) / 255.0f; - - float e = fabsf(k - f); - if (e < best_err) - { - best_err = e; - best_index = ik; - } - } - - g_mode6_reduced_quant[i][p] = (uint8_t)best_index; - } - } // p - - // Mode 1 - for (int c = 0; c < 256; c++) - { - for (uint32_t lp = 0; lp < 2; lp++) - { - endpoint_err best; - best.m_error = (uint16_t)UINT16_MAX; - for (uint32_t l = 0; l < 64; l++) - { - uint32_t low = ((l << 1) | lp) << 1; - low |= (low >> 7); - for (uint32_t h = 0; h < 64; h++) - { - uint32_t high = ((h << 1) | lp) << 1; - high |= (high >> 7); - const int k = (low * (64 - g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX]) + high * g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX] + 32) >> 6; - const int err = (k - c) * (k - c); - if (err < best.m_error) - { - best.m_error = (uint16_t)err; - best.m_lo = (uint8_t)l; - best.m_hi = (uint8_t)h; - } - } // h - } // l - g_bc7_mode_1_optimal_endpoints[c][lp] = best; - } // lp - } // c - - // Mode 7: 555.1 2-bit indices - for (int c = 0; c < 256; c++) - { - for (uint32_t hp = 0; hp < 2; hp++) - { - for (uint32_t lp = 0; lp < 2; lp++) - { - endpoint_err best; - best.m_error = (uint16_t)UINT16_MAX; - best.m_lo = 0; - best.m_hi = 0; - - for (uint32_t l = 0; l < 32; l++) - { - uint32_t low = ((l << 1) | lp) << 2; - low |= (low >> 6); - - for (uint32_t h = 0; h < 32; h++) - { - uint32_t high = ((h << 1) | hp) << 2; - high |= (high >> 6); - - const int k = (low * (64 - g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX]) + high * g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX] + 32) >> 6; - - const int err = (k - c) * (k - c); - if (err < best.m_error) - { - best.m_error = (uint16_t)err; - best.m_lo = (uint8_t)l; - best.m_hi = (uint8_t)h; - } - } // h - } // l - - g_bc7_mode_7_optimal_endpoints[c][hp][lp] = best; - - } // hp - - } // lp - - } // c - - g_initialized = true; -} - -static void compute_least_squares_endpoints_rgba(uint32_t N, const uint8_t* pSelectors, const vec4F* pSelector_weights, vec4F* pXl, vec4F* pXh, const color_rgba* pColors) -{ - // Least squares using normal equations: http://www.cs.cornell.edu/~bindel/class/cs3220-s12/notes/lec10.pdf - // I did this in matrix form first, expanded out all the ops, then optimized it a bit. - float z00 = 0.0f, z01 = 0.0f, z10 = 0.0f, z11 = 0.0f; - float q00_r = 0.0f, q10_r = 0.0f, t_r = 0.0f; - float q00_g = 0.0f, q10_g = 0.0f, t_g = 0.0f; - float q00_b = 0.0f, q10_b = 0.0f, t_b = 0.0f; - float q00_a = 0.0f, q10_a = 0.0f, t_a = 0.0f; - for (uint32_t i = 0; i < N; i++) - { - const uint32_t sel = pSelectors[i]; - z00 += pSelector_weights[sel].m_c[0]; - z10 += pSelector_weights[sel].m_c[1]; - z11 += pSelector_weights[sel].m_c[2]; - float w = pSelector_weights[sel].m_c[3]; - q00_r += w * pColors[i].m_c[0]; t_r += pColors[i].m_c[0]; - q00_g += w * pColors[i].m_c[1]; t_g += pColors[i].m_c[1]; - q00_b += w * pColors[i].m_c[2]; t_b += pColors[i].m_c[2]; - q00_a += w * pColors[i].m_c[3]; t_a += pColors[i].m_c[3]; - } - - q10_r = t_r - q00_r; - q10_g = t_g - q00_g; - q10_b = t_b - q00_b; - q10_a = t_a - q00_a; - - z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (det != 0.0f) - det = 1.0f / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - pXl->m_c[0] = (float)(iz00 * q00_r + iz01 * q10_r); pXh->m_c[0] = (float)(iz10 * q00_r + iz11 * q10_r); - pXl->m_c[1] = (float)(iz00 * q00_g + iz01 * q10_g); pXh->m_c[1] = (float)(iz10 * q00_g + iz11 * q10_g); - pXl->m_c[2] = (float)(iz00 * q00_b + iz01 * q10_b); pXh->m_c[2] = (float)(iz10 * q00_b + iz11 * q10_b); - pXl->m_c[3] = (float)(iz00 * q00_a + iz01 * q10_a); pXh->m_c[3] = (float)(iz10 * q00_a + iz11 * q10_a); - - for (uint32_t c = 0; c < 4; c++) - { - if ((pXl->m_c[c] < 0.0f) || (pXh->m_c[c] > 255.0f)) - { - uint32_t lo_v = UINT32_MAX, hi_v = 0; - for (uint32_t i = 0; i < N; i++) - { - lo_v = minimumu(lo_v, pColors[i].m_c[c]); - hi_v = maximumu(hi_v, pColors[i].m_c[c]); - } - - if (lo_v == hi_v) - { - pXl->m_c[c] = (float)lo_v; - pXh->m_c[c] = (float)hi_v; - } - } - } -} - -static void compute_least_squares_endpoints_rgb(uint32_t N, const uint8_t* pSelectors, const vec4F* pSelector_weights, vec4F* pXl, vec4F* pXh, const color_rgba* pColors) -{ - float z00 = 0.0f, z01 = 0.0f, z10 = 0.0f, z11 = 0.0f; - float q00_r = 0.0f, q10_r = 0.0f, t_r = 0.0f; - float q00_g = 0.0f, q10_g = 0.0f, t_g = 0.0f; - float q00_b = 0.0f, q10_b = 0.0f, t_b = 0.0f; - for (uint32_t i = 0; i < N; i++) - { - const uint32_t sel = pSelectors[i]; - z00 += pSelector_weights[sel].m_c[0]; - z10 += pSelector_weights[sel].m_c[1]; - z11 += pSelector_weights[sel].m_c[2]; - float w = pSelector_weights[sel].m_c[3]; - q00_r += w * pColors[i].m_c[0]; t_r += pColors[i].m_c[0]; - q00_g += w * pColors[i].m_c[1]; t_g += pColors[i].m_c[1]; - q00_b += w * pColors[i].m_c[2]; t_b += pColors[i].m_c[2]; - } - - q10_r = t_r - q00_r; - q10_g = t_g - q00_g; - q10_b = t_b - q00_b; - - z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (det != 0.0f) - det = 1.0f / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - pXl->m_c[0] = (float)(iz00 * q00_r + iz01 * q10_r); pXh->m_c[0] = (float)(iz10 * q00_r + iz11 * q10_r); - pXl->m_c[1] = (float)(iz00 * q00_g + iz01 * q10_g); pXh->m_c[1] = (float)(iz10 * q00_g + iz11 * q10_g); - pXl->m_c[2] = (float)(iz00 * q00_b + iz01 * q10_b); pXh->m_c[2] = (float)(iz10 * q00_b + iz11 * q10_b); - pXl->m_c[3] = 255.0f; pXh->m_c[3] = 255.0f; - - for (uint32_t c = 0; c < 3; c++) - { - if ((pXl->m_c[c] < 0.0f) || (pXh->m_c[c] > 255.0f)) - { - uint32_t lo_v = UINT32_MAX, hi_v = 0; - for (uint32_t i = 0; i < N; i++) - { - lo_v = minimumu(lo_v, pColors[i].m_c[c]); - hi_v = maximumu(hi_v, pColors[i].m_c[c]); - } - - if (lo_v == hi_v) - { - pXl->m_c[c] = (float)lo_v; - pXh->m_c[c] = (float)hi_v; - } - } - } -} - -static void compute_least_squares_endpoints_a(uint32_t N, const uint8_t* pSelectors, const vec4F* pSelector_weights, float* pXl, float* pXh, const color_rgba* pColors) -{ - // Least squares using normal equations: http://www.cs.cornell.edu/~bindel/class/cs3220-s12/notes/lec10.pdf - // I did this in matrix form first, expanded out all the ops, then optimized it a bit. - float z00 = 0.0f, z01 = 0.0f, z10 = 0.0f, z11 = 0.0f; - float q00_a = 0.0f, q10_a = 0.0f, t_a = 0.0f; - for (uint32_t i = 0; i < N; i++) - { - const uint32_t sel = pSelectors[i]; - - z00 += pSelector_weights[sel].m_c[0]; - z10 += pSelector_weights[sel].m_c[1]; - z11 += pSelector_weights[sel].m_c[2]; - - float w = pSelector_weights[sel].m_c[3]; - - q00_a += w * pColors[i].m_c[3]; t_a += pColors[i].m_c[3]; - } - - q10_a = t_a - q00_a; - - z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (det != 0.0f) - det = 1.0f / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - *pXl = (float)(iz00 * q00_a + iz01 * q10_a); *pXh = (float)(iz10 * q00_a + iz11 * q10_a); - - if ((*pXl < 0.0f) || (*pXh > 255.0f)) - { - uint32_t lo_v = UINT32_MAX, hi_v = 0; - for (uint32_t i = 0; i < N; i++) - { - lo_v = minimumu(lo_v, pColors[i].m_c[3]); - hi_v = maximumu(hi_v, pColors[i].m_c[3]); - } - - if (lo_v == hi_v) - { - *pXl = (float)lo_v; - *pXh = (float)hi_v; - } - } -} - -struct color_cell_compressor_params -{ - uint32_t m_num_pixels; - const color_rgba* m_pPixels; - uint32_t m_num_selector_weights; - const uint32_t* m_pSelector_weights; - const vec4F* m_pSelector_weightsx; - uint32_t m_comp_bits; - uint32_t m_weights[4]; - bool m_has_alpha; - bool m_has_pbits; - bool m_endpoints_share_pbit; - bool m_perceptual; -}; - -struct color_cell_compressor_results -{ - uint64_t m_best_overall_err; - color_rgba m_low_endpoint; - color_rgba m_high_endpoint; - uint32_t m_pbits[2]; - uint8_t* m_pSelectors; - uint8_t* m_pSelectors_temp; -}; - -static inline color_rgba scale_color(const color_rgba* pC, const color_cell_compressor_params* pParams) -{ - color_rgba results; - - const uint32_t n = pParams->m_comp_bits + (pParams->m_has_pbits ? 1 : 0); - assert((n >= 4) && (n <= 8)); - - for (uint32_t i = 0; i < 4; i++) - { - uint32_t v = pC->m_c[i] << (8 - n); - v |= (v >> n); - assert(v <= 255); - results.m_c[i] = (uint8_t)(v); - } - - return results; -} - -static inline uint64_t compute_color_distance_rgb(const color_rgba* pE1, const color_rgba* pE2, bool perceptual, const uint32_t weights[4]) -{ - int dr, dg, db; - - if (perceptual) - { - const int l1 = pE1->m_c[0] * 109 + pE1->m_c[1] * 366 + pE1->m_c[2] * 37; - const int cr1 = ((int)pE1->m_c[0] << 9) - l1; - const int cb1 = ((int)pE1->m_c[2] << 9) - l1; - const int l2 = pE2->m_c[0] * 109 + pE2->m_c[1] * 366 + pE2->m_c[2] * 37; - const int cr2 = ((int)pE2->m_c[0] << 9) - l2; - const int cb2 = ((int)pE2->m_c[2] << 9) - l2; - dr = (l1 - l2) >> 8; - dg = (cr1 - cr2) >> 8; - db = (cb1 - cb2) >> 8; - } - else - { - dr = (int)pE1->m_c[0] - (int)pE2->m_c[0]; - dg = (int)pE1->m_c[1] - (int)pE2->m_c[1]; - db = (int)pE1->m_c[2] - (int)pE2->m_c[2]; - } - - return weights[0] * (uint32_t)(dr * dr) + weights[1] * (uint32_t)(dg * dg) + weights[2] * (uint32_t)(db * db); -} - -static inline uint64_t compute_color_distance_rgba(const color_rgba* pE1, const color_rgba* pE2, bool perceptual, const uint32_t weights[4]) -{ - int da = (int)pE1->m_c[3] - (int)pE2->m_c[3]; - return compute_color_distance_rgb(pE1, pE2, perceptual, weights) + (weights[3] * (uint32_t)(da * da)); -} - -static uint64_t pack_mode1_to_one_color(const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, uint32_t r, uint32_t g, uint32_t b, uint8_t* pSelectors) -{ - uint32_t best_err = UINT_MAX; - uint32_t best_p = 0; - - for (uint32_t p = 0; p < 2; p++) - { - uint32_t err = g_bc7_mode_1_optimal_endpoints[r][p].m_error + g_bc7_mode_1_optimal_endpoints[g][p].m_error + g_bc7_mode_1_optimal_endpoints[b][p].m_error; - if (err < best_err) - { - best_err = err; - best_p = p; - if (!best_err) - break; - } - } - - const endpoint_err* pEr = &g_bc7_mode_1_optimal_endpoints[r][best_p]; - const endpoint_err* pEg = &g_bc7_mode_1_optimal_endpoints[g][best_p]; - const endpoint_err* pEb = &g_bc7_mode_1_optimal_endpoints[b][best_p]; - - color_quad_u8_set(&pResults->m_low_endpoint, pEr->m_lo, pEg->m_lo, pEb->m_lo, 0); - color_quad_u8_set(&pResults->m_high_endpoint, pEr->m_hi, pEg->m_hi, pEb->m_hi, 0); - pResults->m_pbits[0] = best_p; - pResults->m_pbits[1] = 0; - - memset(pSelectors, BC7ENC_MODE_1_OPTIMAL_INDEX, pParams->m_num_pixels); - - color_rgba p; - for (uint32_t i = 0; i < 3; i++) - { - uint32_t low = ((pResults->m_low_endpoint.m_c[i] << 1) | pResults->m_pbits[0]) << 1; - low |= (low >> 7); - - uint32_t high = ((pResults->m_high_endpoint.m_c[i] << 1) | pResults->m_pbits[0]) << 1; - high |= (high >> 7); - - p.m_c[i] = (uint8_t)((low * (64 - g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX]) + high * g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX] + 32) >> 6); - } - p.m_c[3] = 255; - - uint64_t total_err = 0; - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - total_err += compute_color_distance_rgb(&p, &pParams->m_pPixels[i], pParams->m_perceptual, pParams->m_weights); - - pResults->m_best_overall_err = total_err; - - return total_err; -} - -static uint64_t pack_mode7_to_one_color(const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, uint32_t r, uint32_t g, uint32_t b, uint32_t a, - uint8_t* pSelectors, uint32_t num_pixels, const color_rgba* pPixels) -{ - uint32_t best_err = UINT_MAX; - uint32_t best_p = 0; - - for (uint32_t p = 0; p < 4; p++) - { - uint32_t hi_p = p >> 1; - uint32_t lo_p = p & 1; - uint32_t err = g_bc7_mode_7_optimal_endpoints[r][hi_p][lo_p].m_error + g_bc7_mode_7_optimal_endpoints[g][hi_p][lo_p].m_error + g_bc7_mode_7_optimal_endpoints[b][hi_p][lo_p].m_error + g_bc7_mode_7_optimal_endpoints[a][hi_p][lo_p].m_error; - if (err < best_err) - { - best_err = err; - best_p = p; - if (!best_err) - break; - } - } - - uint32_t best_hi_p = best_p >> 1; - uint32_t best_lo_p = best_p & 1; - - const endpoint_err* pEr = &g_bc7_mode_7_optimal_endpoints[r][best_hi_p][best_lo_p]; - const endpoint_err* pEg = &g_bc7_mode_7_optimal_endpoints[g][best_hi_p][best_lo_p]; - const endpoint_err* pEb = &g_bc7_mode_7_optimal_endpoints[b][best_hi_p][best_lo_p]; - const endpoint_err* pEa = &g_bc7_mode_7_optimal_endpoints[a][best_hi_p][best_lo_p]; - - color_quad_u8_set(&pResults->m_low_endpoint, pEr->m_lo, pEg->m_lo, pEb->m_lo, pEa->m_lo); - color_quad_u8_set(&pResults->m_high_endpoint, pEr->m_hi, pEg->m_hi, pEb->m_hi, pEa->m_hi); - pResults->m_pbits[0] = best_lo_p; - pResults->m_pbits[1] = best_hi_p; - - for (uint32_t i = 0; i < num_pixels; i++) - pSelectors[i] = (uint8_t)BC7E_MODE_7_OPTIMAL_INDEX; - - color_rgba p; - - for (uint32_t i = 0; i < 4; i++) - { - uint32_t low = (pResults->m_low_endpoint.m_c[i] << 1) | pResults->m_pbits[0]; - uint32_t high = (pResults->m_high_endpoint.m_c[i] << 1) | pResults->m_pbits[1]; - - low = (low << 2) | (low >> 6); - high = (high << 2) | (high >> 6); - - p.m_c[i] = (uint8_t)((low * (64 - g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX]) + high * g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX] + 32) >> 6); - } - - uint64_t total_err = 0; - for (uint32_t i = 0; i < num_pixels; i++) - total_err += compute_color_distance_rgba(&p, &pPixels[i], pParams->m_perceptual, pParams->m_weights); - - pResults->m_best_overall_err = total_err; - - return total_err; -} - -static uint64_t evaluate_solution(const color_rgba* pLow, const color_rgba* pHigh, const uint32_t pbits[2], const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, - const bc7enc_compress_block_params* pComp_params) -{ - color_rgba quantMinColor = *pLow; - color_rgba quantMaxColor = *pHigh; - - if (pParams->m_has_pbits) - { - uint32_t minPBit, maxPBit; - - if (pParams->m_endpoints_share_pbit) - maxPBit = minPBit = pbits[0]; - else - { - minPBit = pbits[0]; - maxPBit = pbits[1]; - } - - quantMinColor.m_c[0] = (uint8_t)((pLow->m_c[0] << 1) | minPBit); - quantMinColor.m_c[1] = (uint8_t)((pLow->m_c[1] << 1) | minPBit); - quantMinColor.m_c[2] = (uint8_t)((pLow->m_c[2] << 1) | minPBit); - quantMinColor.m_c[3] = (uint8_t)((pLow->m_c[3] << 1) | minPBit); - - quantMaxColor.m_c[0] = (uint8_t)((pHigh->m_c[0] << 1) | maxPBit); - quantMaxColor.m_c[1] = (uint8_t)((pHigh->m_c[1] << 1) | maxPBit); - quantMaxColor.m_c[2] = (uint8_t)((pHigh->m_c[2] << 1) | maxPBit); - quantMaxColor.m_c[3] = (uint8_t)((pHigh->m_c[3] << 1) | maxPBit); - } - - color_rgba actualMinColor = scale_color(&quantMinColor, pParams); - color_rgba actualMaxColor = scale_color(&quantMaxColor, pParams); - - const uint32_t N = pParams->m_num_selector_weights; - - color_rgba weightedColors[16]; - weightedColors[0] = actualMinColor; - weightedColors[N - 1] = actualMaxColor; - - const uint32_t nc = pParams->m_has_alpha ? 4 : 3; - for (uint32_t i = 1; i < (N - 1); i++) - for (uint32_t j = 0; j < nc; j++) - weightedColors[i].m_c[j] = (uint8_t)((actualMinColor.m_c[j] * (64 - pParams->m_pSelector_weights[i]) + actualMaxColor.m_c[j] * pParams->m_pSelector_weights[i] + 32) >> 6); - - const int lr = actualMinColor.m_c[0]; - const int lg = actualMinColor.m_c[1]; - const int lb = actualMinColor.m_c[2]; - const int dr = actualMaxColor.m_c[0] - lr; - const int dg = actualMaxColor.m_c[1] - lg; - const int db = actualMaxColor.m_c[2] - lb; - - uint64_t total_err = 0; - - if (pComp_params->m_force_selectors) - { - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - const uint32_t best_sel = pComp_params->m_selectors[i]; - - uint64_t best_err; - if (pParams->m_has_alpha) - best_err = compute_color_distance_rgba(&weightedColors[best_sel], &pParams->m_pPixels[i], pParams->m_perceptual, pParams->m_weights); - else - best_err = compute_color_distance_rgb(&weightedColors[best_sel], &pParams->m_pPixels[i], pParams->m_perceptual, pParams->m_weights); - - total_err += best_err; - - pResults->m_pSelectors_temp[i] = (uint8_t)best_sel; - } - } - else if (!pParams->m_perceptual) - { - if (pParams->m_has_alpha) - { - const int la = actualMinColor.m_c[3]; - const int da = actualMaxColor.m_c[3] - la; - - const float f = N / (float)(squarei(dr) + squarei(dg) + squarei(db) + squarei(da) + .00000125f); - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - const color_rgba* pC = &pParams->m_pPixels[i]; - int r = pC->m_c[0]; - int g = pC->m_c[1]; - int b = pC->m_c[2]; - int a = pC->m_c[3]; - - int best_sel = (int)((float)((r - lr) * dr + (g - lg) * dg + (b - lb) * db + (a - la) * da) * f + .5f); - best_sel = clampi(best_sel, 1, N - 1); - - uint64_t err0 = compute_color_distance_rgba(&weightedColors[best_sel - 1], pC, false, pParams->m_weights); - uint64_t err1 = compute_color_distance_rgba(&weightedColors[best_sel], pC, false, pParams->m_weights); - - if (err1 > err0) - { - err1 = err0; - --best_sel; - } - total_err += err1; - - pResults->m_pSelectors_temp[i] = (uint8_t)best_sel; - } - } - else - { - const float f = N / (float)(squarei(dr) + squarei(dg) + squarei(db) + .00000125f); - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - const color_rgba* pC = &pParams->m_pPixels[i]; - int r = pC->m_c[0]; - int g = pC->m_c[1]; - int b = pC->m_c[2]; - - int sel = (int)((float)((r - lr) * dr + (g - lg) * dg + (b - lb) * db) * f + .5f); - sel = clampi(sel, 1, N - 1); - - uint64_t err0 = compute_color_distance_rgb(&weightedColors[sel - 1], pC, false, pParams->m_weights); - uint64_t err1 = compute_color_distance_rgb(&weightedColors[sel], pC, false, pParams->m_weights); - - int best_sel = sel; - uint64_t best_err = err1; - if (err0 < best_err) - { - best_err = err0; - best_sel = sel - 1; - } - - total_err += best_err; - - pResults->m_pSelectors_temp[i] = (uint8_t)best_sel; - } - } - } - else - { - // TODO: This could be improved. - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint64_t best_err = UINT64_MAX; - uint32_t best_sel = 0; - - if (pParams->m_has_alpha) - { - for (uint32_t j = 0; j < N; j++) - { - uint64_t err = compute_color_distance_rgba(&weightedColors[j], &pParams->m_pPixels[i], true, pParams->m_weights); - if (err < best_err) - { - best_err = err; - best_sel = j; - } - } - } - else - { - for (uint32_t j = 0; j < N; j++) - { - uint64_t err = compute_color_distance_rgb(&weightedColors[j], &pParams->m_pPixels[i], true, pParams->m_weights); - if (err < best_err) - { - best_err = err; - best_sel = j; - } - } - } - - total_err += best_err; - - pResults->m_pSelectors_temp[i] = (uint8_t)best_sel; - } - } - - if (total_err < pResults->m_best_overall_err) - { - pResults->m_best_overall_err = total_err; - - pResults->m_low_endpoint = *pLow; - pResults->m_high_endpoint = *pHigh; - - pResults->m_pbits[0] = pbits[0]; - pResults->m_pbits[1] = pbits[1]; - - memcpy(pResults->m_pSelectors, pResults->m_pSelectors_temp, sizeof(pResults->m_pSelectors[0]) * pParams->m_num_pixels); - } - - return total_err; -} - -static void fixDegenerateEndpoints(uint32_t mode, color_rgba* pTrialMinColor, color_rgba* pTrialMaxColor, const vec4F* pXl, const vec4F* pXh, uint32_t iscale, - const bc7enc_compress_block_params* pComp_params) -{ - //if ((mode == 1) || (mode == 7)) - //if (mode == 1) - if ((mode == 1) || ((mode == 6) && (pComp_params->m_quant_mode6_endpoints))) - { - // fix degenerate case where the input collapses to a single colorspace voxel, and we loose all freedom (test with grayscale ramps) - for (uint32_t i = 0; i < 3; i++) - { - if (pTrialMinColor->m_c[i] == pTrialMaxColor->m_c[i]) - { - if (fabs(pXl->m_c[i] - pXh->m_c[i]) > 0.0f) - { - if (pTrialMinColor->m_c[i] > (iscale >> 1)) - { - if (pTrialMinColor->m_c[i] > 0) - pTrialMinColor->m_c[i]--; - else - if (pTrialMaxColor->m_c[i] < iscale) - pTrialMaxColor->m_c[i]++; - } - else - { - if (pTrialMaxColor->m_c[i] < iscale) - pTrialMaxColor->m_c[i]++; - else if (pTrialMinColor->m_c[i] > 0) - pTrialMinColor->m_c[i]--; - } - } - } - } - } -} - -static uint64_t find_optimal_solution(uint32_t mode, vec4F xl, vec4F xh, const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, - const bc7enc_compress_block_params* pComp_params) -{ - vec4F_saturate_in_place(&xl); vec4F_saturate_in_place(&xh); - - if (pParams->m_has_pbits) - { - const int iscalep = (1 << (pParams->m_comp_bits + 1)) - 1; - const float scalep = (float)iscalep; - - const int32_t totalComps = pParams->m_has_alpha ? 4 : 3; - - uint32_t best_pbits[2]; - color_rgba bestMinColor, bestMaxColor; - - if (!pParams->m_endpoints_share_pbit) - { - if ((pParams->m_comp_bits == 7) && (pComp_params->m_quant_mode6_endpoints)) - { - best_pbits[0] = 0; - bestMinColor.m_c[0] = g_mode6_reduced_quant[(int)((xl.m_c[0] * 2047.0f) + .5f)][0]; - bestMinColor.m_c[1] = g_mode6_reduced_quant[(int)((xl.m_c[1] * 2047.0f) + .5f)][0]; - bestMinColor.m_c[2] = g_mode6_reduced_quant[(int)((xl.m_c[2] * 2047.0f) + .5f)][0]; - bestMinColor.m_c[3] = g_mode6_reduced_quant[(int)((xl.m_c[3] * 2047.0f) + .5f)][0]; - - best_pbits[1] = 1; - bestMaxColor.m_c[0] = g_mode6_reduced_quant[(int)((xh.m_c[0] * 2047.0f) + .5f)][1]; - bestMaxColor.m_c[1] = g_mode6_reduced_quant[(int)((xh.m_c[1] * 2047.0f) + .5f)][1]; - bestMaxColor.m_c[2] = g_mode6_reduced_quant[(int)((xh.m_c[2] * 2047.0f) + .5f)][1]; - bestMaxColor.m_c[3] = g_mode6_reduced_quant[(int)((xh.m_c[3] * 2047.0f) + .5f)][1]; - } - else - { - float best_err0 = 1e+9; - float best_err1 = 1e+9; - - for (int p = 0; p < 2; p++) - { - color_rgba xMinColor, xMaxColor; - - // Notes: The pbit controls which quantization intervals are selected. - // total_levels=2^(comp_bits+1), where comp_bits=4 for mode 0, etc. - // pbit 0: v=(b*2)/(total_levels-1), pbit 1: v=(b*2+1)/(total_levels-1) where b is the component bin from [0,total_levels/2-1] and v is the [0,1] component value - // rearranging you get for pbit 0: b=floor(v*(total_levels-1)/2+.5) - // rearranging you get for pbit 1: b=floor((v*(total_levels-1)-1)/2+.5) - if (pParams->m_comp_bits == 5) - { - for (uint32_t c = 0; c < 4; c++) - { - int vl = (int)(xl.m_c[c] * 31.0f); - vl += (xl.m_c[c] > g_mode7_rgba_midpoints[vl][p]); - xMinColor.m_c[c] = (uint8_t)clampi(vl * 2 + p, p, 63 - 1 + p); - - int vh = (int)(xh.m_c[c] * 31.0f); - vh += (xh.m_c[c] > g_mode7_rgba_midpoints[vh][p]); - xMaxColor.m_c[c] = (uint8_t)clampi(vh * 2 + p, p, 63 - 1 + p); - } - } - else - { - for (uint32_t c = 0; c < 4; c++) - { - xMinColor.m_c[c] = (uint8_t)(clampi(((int)((xl.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - xMaxColor.m_c[c] = (uint8_t)(clampi(((int)((xh.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - } - } - - color_rgba scaledLow = scale_color(&xMinColor, pParams); - color_rgba scaledHigh = scale_color(&xMaxColor, pParams); - - float err0 = 0, err1 = 0; - for (int i = 0; i < totalComps; i++) - { - err0 += squaref(scaledLow.m_c[i] - xl.m_c[i] * 255.0f); - err1 += squaref(scaledHigh.m_c[i] - xh.m_c[i] * 255.0f); - } - - if (p == 1) - { - err0 *= pComp_params->m_pbit1_weight; - err1 *= pComp_params->m_pbit1_weight; - } - - if (err0 < best_err0) - { - best_err0 = err0; - best_pbits[0] = p; - - bestMinColor.m_c[0] = xMinColor.m_c[0] >> 1; - bestMinColor.m_c[1] = xMinColor.m_c[1] >> 1; - bestMinColor.m_c[2] = xMinColor.m_c[2] >> 1; - bestMinColor.m_c[3] = xMinColor.m_c[3] >> 1; - } - - if (err1 < best_err1) - { - best_err1 = err1; - best_pbits[1] = p; - - bestMaxColor.m_c[0] = xMaxColor.m_c[0] >> 1; - bestMaxColor.m_c[1] = xMaxColor.m_c[1] >> 1; - bestMaxColor.m_c[2] = xMaxColor.m_c[2] >> 1; - bestMaxColor.m_c[3] = xMaxColor.m_c[3] >> 1; - } - } - } - } - else - { - if ((mode == 1) && (pComp_params->m_bias_mode1_pbits)) - { - float x = 0.0f; - for (uint32_t c = 0; c < 3; c++) - x = std::max(std::max(x, xl.m_c[c]), xh.m_c[c]); - - int p = 0; - if (x > (253.0f / 255.0f)) - p = 1; - - color_rgba xMinColor, xMaxColor; - for (uint32_t c = 0; c < 4; c++) - { - int vl = (int)(xl.m_c[c] * 63.0f); - vl += (xl.m_c[c] > g_mode1_rgba_midpoints[vl][p]); - xMinColor.m_c[c] = (uint8_t)clampi(vl * 2 + p, p, 127 - 1 + p); - - int vh = (int)(xh.m_c[c] * 63.0f); - vh += (xh.m_c[c] > g_mode1_rgba_midpoints[vh][p]); - xMaxColor.m_c[c] = (uint8_t)clampi(vh * 2 + p, p, 127 - 1 + p); - } - - best_pbits[0] = p; - best_pbits[1] = p; - for (uint32_t j = 0; j < 4; j++) - { - bestMinColor.m_c[j] = xMinColor.m_c[j] >> 1; - bestMaxColor.m_c[j] = xMaxColor.m_c[j] >> 1; - } - } - else - { - // Endpoints share pbits - float best_err = 1e+9; - - for (int p = 0; p < 2; p++) - { - color_rgba xMinColor, xMaxColor; - if (pParams->m_comp_bits == 6) - { - for (uint32_t c = 0; c < 4; c++) - { - int vl = (int)(xl.m_c[c] * 63.0f); - vl += (xl.m_c[c] > g_mode1_rgba_midpoints[vl][p]); - xMinColor.m_c[c] = (uint8_t)clampi(vl * 2 + p, p, 127 - 1 + p); - - int vh = (int)(xh.m_c[c] * 63.0f); - vh += (xh.m_c[c] > g_mode1_rgba_midpoints[vh][p]); - xMaxColor.m_c[c] = (uint8_t)clampi(vh * 2 + p, p, 127 - 1 + p); - } - } - else - { - for (uint32_t c = 0; c < 4; c++) - { - xMinColor.m_c[c] = (uint8_t)(clampi(((int)((xl.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - xMaxColor.m_c[c] = (uint8_t)(clampi(((int)((xh.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - } - } - - color_rgba scaledLow = scale_color(&xMinColor, pParams); - color_rgba scaledHigh = scale_color(&xMaxColor, pParams); - - float err = 0; - for (int i = 0; i < totalComps; i++) - err += squaref((scaledLow.m_c[i] / 255.0f) - xl.m_c[i]) + squaref((scaledHigh.m_c[i] / 255.0f) - xh.m_c[i]); - - if (p == 1) - err *= pComp_params->m_pbit1_weight; - - if (err < best_err) - { - best_err = err; - best_pbits[0] = p; - best_pbits[1] = p; - for (uint32_t j = 0; j < 4; j++) - { - bestMinColor.m_c[j] = xMinColor.m_c[j] >> 1; - bestMaxColor.m_c[j] = xMaxColor.m_c[j] >> 1; - } - } - } - } - } - - fixDegenerateEndpoints(mode, &bestMinColor, &bestMaxColor, &xl, &xh, iscalep >> 1, pComp_params); - - if ((pResults->m_best_overall_err == UINT64_MAX) || color_quad_u8_notequals(&bestMinColor, &pResults->m_low_endpoint) || color_quad_u8_notequals(&bestMaxColor, &pResults->m_high_endpoint) || (best_pbits[0] != pResults->m_pbits[0]) || (best_pbits[1] != pResults->m_pbits[1])) - evaluate_solution(&bestMinColor, &bestMaxColor, best_pbits, pParams, pResults, pComp_params); - } - else - { - const int iscale = (1 << pParams->m_comp_bits) - 1; - const float scale = (float)iscale; - - color_rgba trialMinColor, trialMaxColor; - if (pParams->m_comp_bits == 7) - { - for (uint32_t c = 0; c < 4; c++) - { - int vl = (int)(xl.m_c[c] * 127.0f); - vl += (xl.m_c[c] > g_mode5_rgba_midpoints[vl]); - trialMinColor.m_c[c] = (uint8_t)clampi(vl, 0, 127); - - int vh = (int)(xh.m_c[c] * 127.0f); - vh += (xh.m_c[c] > g_mode5_rgba_midpoints[vh]); - trialMaxColor.m_c[c] = (uint8_t)clampi(vh, 0, 127); - } - } - else - { - color_quad_u8_set_clamped(&trialMinColor, (int)(xl.m_c[0] * scale + .5f), (int)(xl.m_c[1] * scale + .5f), (int)(xl.m_c[2] * scale + .5f), (int)(xl.m_c[3] * scale + .5f)); - color_quad_u8_set_clamped(&trialMaxColor, (int)(xh.m_c[0] * scale + .5f), (int)(xh.m_c[1] * scale + .5f), (int)(xh.m_c[2] * scale + .5f), (int)(xh.m_c[3] * scale + .5f)); - } - - fixDegenerateEndpoints(mode, &trialMinColor, &trialMaxColor, &xl, &xh, iscale, pComp_params); - - if ((pResults->m_best_overall_err == UINT64_MAX) || color_quad_u8_notequals(&trialMinColor, &pResults->m_low_endpoint) || color_quad_u8_notequals(&trialMaxColor, &pResults->m_high_endpoint)) - evaluate_solution(&trialMinColor, &trialMaxColor, pResults->m_pbits, pParams, pResults, pComp_params); - } - - return pResults->m_best_overall_err; -} - -static uint64_t color_cell_compression(uint32_t mode, const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, const bc7enc_compress_block_params* pComp_params) -{ - assert((mode == 6) || (mode == 7) || (!pParams->m_has_alpha)); - - pResults->m_best_overall_err = UINT64_MAX; - - // If the partition's colors are all the same in mode 1, then just pack them as a single color. - if (mode == 1) - { - const uint32_t cr = pParams->m_pPixels[0].m_c[0], cg = pParams->m_pPixels[0].m_c[1], cb = pParams->m_pPixels[0].m_c[2]; - - bool allSame = true; - for (uint32_t i = 1; i < pParams->m_num_pixels; i++) - { - if ((cr != pParams->m_pPixels[i].m_c[0]) || (cg != pParams->m_pPixels[i].m_c[1]) || (cb != pParams->m_pPixels[i].m_c[2])) - { - allSame = false; - break; - } - } - - if (allSame) - return pack_mode1_to_one_color(pParams, pResults, cr, cg, cb, pResults->m_pSelectors); - } - else if (mode == 7) - { - const uint32_t cr = pParams->m_pPixels[0].m_c[0], cg = pParams->m_pPixels[0].m_c[1], cb = pParams->m_pPixels[0].m_c[2], ca = pParams->m_pPixels[0].m_c[3]; - - bool allSame = true; - for (uint32_t i = 1; i < pParams->m_num_pixels; i++) - { - if ((cr != pParams->m_pPixels[i].m_c[0]) || (cg != pParams->m_pPixels[i].m_c[1]) || (cb != pParams->m_pPixels[i].m_c[2]) || (ca != pParams->m_pPixels[i].m_c[3])) - { - allSame = false; - break; - } - } - - if (allSame) - return pack_mode7_to_one_color(pParams, pResults, cr, cg, cb, ca, pResults->m_pSelectors, pParams->m_num_pixels, pParams->m_pPixels); - } - - // Compute partition's mean color and principle axis. - vec4F meanColor, axis; - vec4F_set_scalar(&meanColor, 0.0f); - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - vec4F color = vec4F_from_color(&pParams->m_pPixels[i]); - meanColor = vec4F_add(&meanColor, &color); - } - - vec4F meanColorScaled = vec4F_mul(&meanColor, 1.0f / (float)(pParams->m_num_pixels)); - - meanColor = vec4F_mul(&meanColor, 1.0f / (float)(pParams->m_num_pixels * 255.0f)); - vec4F_saturate_in_place(&meanColor); - - if (pParams->m_has_alpha) - { - // Use incremental PCA for RGBA PCA, because it's simple. - vec4F_set_scalar(&axis, 0.0f); - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - vec4F color = vec4F_from_color(&pParams->m_pPixels[i]); - color = vec4F_sub(&color, &meanColorScaled); - vec4F a = vec4F_mul(&color, color.m_c[0]); - vec4F b = vec4F_mul(&color, color.m_c[1]); - vec4F c = vec4F_mul(&color, color.m_c[2]); - vec4F d = vec4F_mul(&color, color.m_c[3]); - vec4F n = i ? axis : color; - vec4F_normalize_in_place(&n); - axis.m_c[0] += vec4F_dot(&a, &n); - axis.m_c[1] += vec4F_dot(&b, &n); - axis.m_c[2] += vec4F_dot(&c, &n); - axis.m_c[3] += vec4F_dot(&d, &n); - } - vec4F_normalize_in_place(&axis); - } - else - { - // Use covar technique for RGB PCA, because it doesn't require per-pixel normalization. - float cov[6] = { 0, 0, 0, 0, 0, 0 }; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - const color_rgba* pV = &pParams->m_pPixels[i]; - float r = pV->m_c[0] - meanColorScaled.m_c[0]; - float g = pV->m_c[1] - meanColorScaled.m_c[1]; - float b = pV->m_c[2] - meanColorScaled.m_c[2]; - cov[0] += r * r; cov[1] += r * g; cov[2] += r * b; cov[3] += g * g; cov[4] += g * b; cov[5] += b * b; - } - - float vfr = .9f, vfg = 1.0f, vfb = .7f; - for (uint32_t iter = 0; iter < 3; iter++) - { - float r = vfr * cov[0] + vfg * cov[1] + vfb * cov[2]; - float g = vfr * cov[1] + vfg * cov[3] + vfb * cov[4]; - float b = vfr * cov[2] + vfg * cov[4] + vfb * cov[5]; - - float m = maximumf(maximumf(fabsf(r), fabsf(g)), fabsf(b)); - if (m > 1e-10f) - { - m = 1.0f / m; - r *= m; g *= m; b *= m; - } - - vfr = r; vfg = g; vfb = b; - } - - float len = vfr * vfr + vfg * vfg + vfb * vfb; - if (len < 1e-10f) - vec4F_set_scalar(&axis, 0.0f); - else - { - len = 1.0f / sqrtf(len); - vfr *= len; vfg *= len; vfb *= len; - vec4F_set(&axis, vfr, vfg, vfb, 0); - } - } - - // TODO: Try picking the 2 colors with the largest projection onto the axis, instead of computing new colors along the axis. - - if (vec4F_dot(&axis, &axis) < .5f) - { - if (pParams->m_perceptual) - vec4F_set(&axis, .213f, .715f, .072f, pParams->m_has_alpha ? .715f : 0); - else - vec4F_set(&axis, 1.0f, 1.0f, 1.0f, pParams->m_has_alpha ? 1.0f : 0); - vec4F_normalize_in_place(&axis); - } - - float l = 1e+9f, h = -1e+9f; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - vec4F color = vec4F_from_color(&pParams->m_pPixels[i]); - - vec4F q = vec4F_sub(&color, &meanColorScaled); - float d = vec4F_dot(&q, &axis); - - l = minimumf(l, d); - h = maximumf(h, d); - } - - l *= (1.0f / 255.0f); - h *= (1.0f / 255.0f); - - vec4F b0 = vec4F_mul(&axis, l); - vec4F b1 = vec4F_mul(&axis, h); - vec4F c0 = vec4F_add(&meanColor, &b0); - vec4F c1 = vec4F_add(&meanColor, &b1); - vec4F minColor = vec4F_saturate(&c0); - vec4F maxColor = vec4F_saturate(&c1); - - vec4F whiteVec; - vec4F_set_scalar(&whiteVec, 1.0f); - - if (vec4F_dot(&minColor, &whiteVec) > vec4F_dot(&maxColor, &whiteVec)) - { -#if 0 - // Don't compile correctly with VC 2019 in release. - vec4F temp = minColor; - minColor = maxColor; - maxColor = temp; -#else - float a = minColor.m_c[0], b = minColor.m_c[1], c = minColor.m_c[2], d = minColor.m_c[3]; - minColor.m_c[0] = maxColor.m_c[0]; - minColor.m_c[1] = maxColor.m_c[1]; - minColor.m_c[2] = maxColor.m_c[2]; - minColor.m_c[3] = maxColor.m_c[3]; - maxColor.m_c[0] = a; - maxColor.m_c[1] = b; - maxColor.m_c[2] = c; - maxColor.m_c[3] = d; -#endif - } - - // First find a solution using the block's PCA. - if (!find_optimal_solution(mode, minColor, maxColor, pParams, pResults, pComp_params)) - return 0; - - if (pComp_params->m_try_least_squares) - { - // Now try to refine the solution using least squares by computing the optimal endpoints from the current selectors. - vec4F xl, xh; - vec4F_set_scalar(&xl, 0.0f); - vec4F_set_scalar(&xh, 0.0f); - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, pResults->m_pSelectors, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, pResults->m_pSelectors, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults, pComp_params)) - return 0; - } - - if (pComp_params->m_uber_level > 0) - { - // In uber level 1, try varying the selectors a little, somewhat like cluster fit would. First try incrementing the minimum selectors, - // then try decrementing the selectrors, then try both. - uint8_t selectors_temp[16], selectors_temp1[16]; - memcpy(selectors_temp, pResults->m_pSelectors, pParams->m_num_pixels); - - const int max_selector = pParams->m_num_selector_weights - 1; - - uint32_t min_sel = 16; - uint32_t max_sel = 0; - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - min_sel = minimumu(min_sel, sel); - max_sel = maximumu(max_sel, sel); - } - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - if ((sel == min_sel) && (sel < (pParams->m_num_selector_weights - 1))) - sel++; - selectors_temp1[i] = (uint8_t)sel; - } - - vec4F xl, xh; - vec4F_set_scalar(&xl, 0.0f); - vec4F_set_scalar(&xh, 0.0f); - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults, pComp_params)) - return 0; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - if ((sel == max_sel) && (sel > 0)) - sel--; - selectors_temp1[i] = (uint8_t)sel; - } - - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults, pComp_params)) - return 0; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - if ((sel == min_sel) && (sel < (pParams->m_num_selector_weights - 1))) - sel++; - else if ((sel == max_sel) && (sel > 0)) - sel--; - selectors_temp1[i] = (uint8_t)sel; - } - - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults, pComp_params)) - return 0; - - // In uber levels 2+, try taking more advantage of endpoint extrapolation by scaling the selectors in one direction or another. - const uint32_t uber_err_thresh = (pParams->m_num_pixels * 56) >> 4; - if ((pComp_params->m_uber_level >= 2) && (pResults->m_best_overall_err > uber_err_thresh)) - { - const int Q = (pComp_params->m_uber_level >= 4) ? (pComp_params->m_uber_level - 2) : 1; - for (int ly = -Q; ly <= 1; ly++) - { - for (int hy = max_selector - 1; hy <= (max_selector + Q); hy++) - { - if ((ly == 0) && (hy == max_selector)) - continue; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - selectors_temp1[i] = (uint8_t)clampf(floorf((float)max_selector * ((float)selectors_temp[i] - (float)ly) / ((float)hy - (float)ly) + .5f), 0, (float)max_selector); - - //vec4F xl, xh; - vec4F_set_scalar(&xl, 0.0f); - vec4F_set_scalar(&xh, 0.0f); - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults, pComp_params)) - return 0; - } - } - } - } - - if (mode == 1) - { - // Try encoding the partition as a single color by using the optimal singe colors tables to encode the block to its mean. - color_cell_compressor_results avg_results = *pResults; - const uint32_t r = (int)(.5f + meanColor.m_c[0] * 255.0f), g = (int)(.5f + meanColor.m_c[1] * 255.0f), b = (int)(.5f + meanColor.m_c[2] * 255.0f); - uint64_t avg_err = pack_mode1_to_one_color(pParams, &avg_results, r, g, b, pResults->m_pSelectors_temp); - if (avg_err < pResults->m_best_overall_err) - { - *pResults = avg_results; - memcpy(pResults->m_pSelectors, pResults->m_pSelectors_temp, sizeof(pResults->m_pSelectors[0]) * pParams->m_num_pixels); - pResults->m_best_overall_err = avg_err; - } - } - else if (mode == 7) - { - // Try encoding the partition as a single color by using the optimal singe colors tables to encode the block to its mean. - color_cell_compressor_results avg_results = *pResults; - const uint32_t r = (int)(.5f + meanColor.m_c[0] * 255.0f), g = (int)(.5f + meanColor.m_c[1] * 255.0f), b = (int)(.5f + meanColor.m_c[2] * 255.0f), a = (int)(.5f + meanColor.m_c[3] * 255.0f); - uint64_t avg_err = pack_mode7_to_one_color(pParams, &avg_results, r, g, b, a, pResults->m_pSelectors_temp, pParams->m_num_pixels, pParams->m_pPixels); - if (avg_err < pResults->m_best_overall_err) - { - *pResults = avg_results; - memcpy(pResults->m_pSelectors, pResults->m_pSelectors_temp, sizeof(pResults->m_pSelectors[0]) * pParams->m_num_pixels); - pResults->m_best_overall_err = avg_err; - } - } - - return pResults->m_best_overall_err; -} - -static uint64_t color_cell_compression_est_mode1(uint32_t num_pixels, const color_rgba* pPixels, bool perceptual, uint32_t pweights[4], uint64_t best_err_so_far) -{ - // Find RGB bounds as an approximation of the block's principle axis - uint32_t lr = 255, lg = 255, lb = 255; - uint32_t hr = 0, hg = 0, hb = 0; - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_rgba* pC = &pPixels[i]; - if (pC->m_c[0] < lr) lr = pC->m_c[0]; - if (pC->m_c[1] < lg) lg = pC->m_c[1]; - if (pC->m_c[2] < lb) lb = pC->m_c[2]; - if (pC->m_c[0] > hr) hr = pC->m_c[0]; - if (pC->m_c[1] > hg) hg = pC->m_c[1]; - if (pC->m_c[2] > hb) hb = pC->m_c[2]; - } - - color_rgba lowColor; color_quad_u8_set(&lowColor, lr, lg, lb, 0); - color_rgba highColor; color_quad_u8_set(&highColor, hr, hg, hb, 0); - - // Place endpoints at bbox diagonals and compute interpolated colors - const uint32_t N = 8; - color_rgba weightedColors[8]; - - weightedColors[0] = lowColor; - weightedColors[N - 1] = highColor; - for (uint32_t i = 1; i < (N - 1); i++) - { - weightedColors[i].m_c[0] = (uint8_t)((lowColor.m_c[0] * (64 - g_bc7_weights3[i]) + highColor.m_c[0] * g_bc7_weights3[i] + 32) >> 6); - weightedColors[i].m_c[1] = (uint8_t)((lowColor.m_c[1] * (64 - g_bc7_weights3[i]) + highColor.m_c[1] * g_bc7_weights3[i] + 32) >> 6); - weightedColors[i].m_c[2] = (uint8_t)((lowColor.m_c[2] * (64 - g_bc7_weights3[i]) + highColor.m_c[2] * g_bc7_weights3[i] + 32) >> 6); - } - - // Compute dots and thresholds - const int ar = highColor.m_c[0] - lowColor.m_c[0]; - const int ag = highColor.m_c[1] - lowColor.m_c[1]; - const int ab = highColor.m_c[2] - lowColor.m_c[2]; - - int dots[8]; - for (uint32_t i = 0; i < N; i++) - dots[i] = weightedColors[i].m_c[0] * ar + weightedColors[i].m_c[1] * ag + weightedColors[i].m_c[2] * ab; - - int thresh[8 - 1]; - for (uint32_t i = 0; i < (N - 1); i++) - thresh[i] = (dots[i] + dots[i + 1] + 1) >> 1; - - uint64_t total_err = 0; - if (perceptual) - { - // Transform block's interpolated colors to YCbCr - int l1[8], cr1[8], cb1[8]; - for (int j = 0; j < 8; j++) - { - const color_rgba* pE1 = &weightedColors[j]; - l1[j] = pE1->m_c[0] * 109 + pE1->m_c[1] * 366 + pE1->m_c[2] * 37; - cr1[j] = ((int)pE1->m_c[0] << 9) - l1[j]; - cb1[j] = ((int)pE1->m_c[2] << 9) - l1[j]; - } - - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_rgba* pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[6]) - s = 7; - else if (d >= thresh[5]) - s = 6; - else if (d >= thresh[4]) - s = 5; - else if (d >= thresh[3]) - s = 4; - else if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const int l2 = pC->m_c[0] * 109 + pC->m_c[1] * 366 + pC->m_c[2] * 37; - const int cr2 = ((int)pC->m_c[0] << 9) - l2; - const int cb2 = ((int)pC->m_c[2] << 9) - l2; - - const int dl = (l1[s] - l2) >> 8; - const int dcr = (cr1[s] - cr2) >> 8; - const int dcb = (cb1[s] - cb2) >> 8; - - int ie = (pweights[0] * dl * dl) + (pweights[1] * dcr * dcr) + (pweights[2] * dcb * dcb); - - total_err += ie; - if (total_err > best_err_so_far) - break; - } - } - else - { - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_rgba* pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[6]) - s = 7; - else if (d >= thresh[5]) - s = 6; - else if (d >= thresh[4]) - s = 5; - else if (d >= thresh[3]) - s = 4; - else if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const color_rgba* pE1 = &weightedColors[s]; - - int dr = (int)pE1->m_c[0] - (int)pC->m_c[0]; - int dg = (int)pE1->m_c[1] - (int)pC->m_c[1]; - int db = (int)pE1->m_c[2] - (int)pC->m_c[2]; - - total_err += pweights[0] * (dr * dr) + pweights[1] * (dg * dg) + pweights[2] * (db * db); - if (total_err > best_err_so_far) - break; - } - } - - return total_err; -} - -static uint64_t color_cell_compression_est_mode7(uint32_t num_pixels, const color_rgba* pPixels, bool perceptual, uint32_t pweights[4], uint64_t best_err_so_far) -{ - // Find RGB bounds as an approximation of the block's principle axis - uint32_t lr = 255, lg = 255, lb = 255, la = 255; - uint32_t hr = 0, hg = 0, hb = 0, ha = 0; - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_rgba* pC = &pPixels[i]; - if (pC->m_c[0] < lr) lr = pC->m_c[0]; - if (pC->m_c[1] < lg) lg = pC->m_c[1]; - if (pC->m_c[2] < lb) lb = pC->m_c[2]; - if (pC->m_c[3] < la) la = pC->m_c[3]; - - if (pC->m_c[0] > hr) hr = pC->m_c[0]; - if (pC->m_c[1] > hg) hg = pC->m_c[1]; - if (pC->m_c[2] > hb) hb = pC->m_c[2]; - if (pC->m_c[3] > ha) ha = pC->m_c[3]; - } - - color_rgba lowColor; color_quad_u8_set(&lowColor, lr, lg, lb, la); - color_rgba highColor; color_quad_u8_set(&highColor, hr, hg, hb, ha); - - // Place endpoints at bbox diagonals and compute interpolated colors - const uint32_t N = 4; - color_rgba weightedColors[4]; - - weightedColors[0] = lowColor; - weightedColors[N - 1] = highColor; - for (uint32_t i = 1; i < (N - 1); i++) - { - weightedColors[i].m_c[0] = (uint8_t)((lowColor.m_c[0] * (64 - g_bc7_weights2[i]) + highColor.m_c[0] * g_bc7_weights2[i] + 32) >> 6); - weightedColors[i].m_c[1] = (uint8_t)((lowColor.m_c[1] * (64 - g_bc7_weights2[i]) + highColor.m_c[1] * g_bc7_weights2[i] + 32) >> 6); - weightedColors[i].m_c[2] = (uint8_t)((lowColor.m_c[2] * (64 - g_bc7_weights2[i]) + highColor.m_c[2] * g_bc7_weights2[i] + 32) >> 6); - weightedColors[i].m_c[3] = (uint8_t)((lowColor.m_c[3] * (64 - g_bc7_weights2[i]) + highColor.m_c[3] * g_bc7_weights2[i] + 32) >> 6); - } - - // Compute dots and thresholds - const int ar = highColor.m_c[0] - lowColor.m_c[0]; - const int ag = highColor.m_c[1] - lowColor.m_c[1]; - const int ab = highColor.m_c[2] - lowColor.m_c[2]; - const int aa = highColor.m_c[3] - lowColor.m_c[3]; - - int dots[4]; - for (uint32_t i = 0; i < N; i++) - dots[i] = weightedColors[i].m_c[0] * ar + weightedColors[i].m_c[1] * ag + weightedColors[i].m_c[2] * ab + weightedColors[i].m_c[3] * aa; - - int thresh[4 - 1]; - for (uint32_t i = 0; i < (N - 1); i++) - thresh[i] = (dots[i] + dots[i + 1] + 1) >> 1; - - uint64_t total_err = 0; - if (perceptual) - { - // Transform block's interpolated colors to YCbCr - int l1[4], cr1[4], cb1[4]; - for (int j = 0; j < 4; j++) - { - const color_rgba* pE1 = &weightedColors[j]; - l1[j] = pE1->m_c[0] * 109 + pE1->m_c[1] * 366 + pE1->m_c[2] * 37; - cr1[j] = ((int)pE1->m_c[0] << 9) - l1[j]; - cb1[j] = ((int)pE1->m_c[2] << 9) - l1[j]; - } - - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_rgba* pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2] + aa * pC->m_c[3]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const int l2 = pC->m_c[0] * 109 + pC->m_c[1] * 366 + pC->m_c[2] * 37; - const int cr2 = ((int)pC->m_c[0] << 9) - l2; - const int cb2 = ((int)pC->m_c[2] << 9) - l2; - - const int dl = (l1[s] - l2) >> 8; - const int dcr = (cr1[s] - cr2) >> 8; - const int dcb = (cb1[s] - cb2) >> 8; - - const int dca = (int)pC->m_c[3] - (int)weightedColors[s].m_c[3]; - - int ie = (pweights[0] * dl * dl) + (pweights[1] * dcr * dcr) + (pweights[2] * dcb * dcb) + (pweights[3] * dca * dca); - - total_err += ie; - if (total_err > best_err_so_far) - break; - } - } - else - { - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_rgba* pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2] + aa * pC->m_c[3]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const color_rgba* pE1 = &weightedColors[s]; - - int dr = (int)pE1->m_c[0] - (int)pC->m_c[0]; - int dg = (int)pE1->m_c[1] - (int)pC->m_c[1]; - int db = (int)pE1->m_c[2] - (int)pC->m_c[2]; - int da = (int)pE1->m_c[3] - (int)pC->m_c[3]; - - total_err += pweights[0] * (dr * dr) + pweights[1] * (dg * dg) + pweights[2] * (db * db) + pweights[3] * (da * da); - if (total_err > best_err_so_far) - break; - } - } - - return total_err; -} - -// This table contains bitmasks indicating which "key" partitions must be best ranked before this partition is worth evaluating. -// We first rank the best/most used 14 partitions (sorted by usefulness), record the best one found as the key partition, then use -// that to control the other partitions to evaluate. The quality loss is ~.08 dB RGB PSNR, the perf gain is up to ~11% (at uber level 0). -static const uint32_t g_partition_predictors[35] = -{ - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - (1 << 1) | (1 << 2) | (1 << 8), - (1 << 1) | (1 << 3) | (1 << 7), - UINT32_MAX, - UINT32_MAX, - (1 << 2) | (1 << 8) | (1 << 16), - (1 << 7) | (1 << 3) | (1 << 15), - UINT32_MAX, - (1 << 8) | (1 << 14) | (1 << 16), - (1 << 7) | (1 << 14) | (1 << 15), - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - (1 << 14) | (1 << 15), - (1 << 16) | (1 << 22) | (1 << 14), - (1 << 17) | (1 << 24) | (1 << 14), - (1 << 2) | (1 << 14) | (1 << 15) | (1 << 1), - UINT32_MAX, - (1 << 1) | (1 << 3) | (1 << 14) | (1 << 16) | (1 << 22), - UINT32_MAX, - (1 << 1) | (1 << 2) | (1 << 15) | (1 << 17) | (1 << 24), - (1 << 1) | (1 << 3) | (1 << 22), - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - (1 << 14) | (1 << 15) | (1 << 16) | (1 << 17), - UINT32_MAX, - UINT32_MAX, - (1 << 1) | (1 << 2) | (1 << 3) | (1 << 27) | (1 << 4) | (1 << 24), - (1 << 14) | (1 << 15) | (1 << 16) | (1 << 11) | (1 << 17) | (1 << 27) -}; - -// Estimate the partition used by modes 1/7. This scans through each partition and computes an approximate error for each. -static uint32_t estimate_partition(const color_rgba* pPixels, const bc7enc_compress_block_params* pComp_params, uint32_t pweights[4], uint32_t mode) -{ - const uint32_t total_partitions = minimumu(pComp_params->m_max_partitions, BC7ENC_MAX_PARTITIONS); - if (total_partitions <= 1) - return 0; - - uint64_t best_err = UINT64_MAX; - uint32_t best_partition = 0; - - // Partition order sorted by usage frequency across a large test corpus. Pattern 34 (checkerboard) must appear in slot 34. - // Using a sorted order allows the user to decrease the # of partitions to scan with minimal loss in quality. - static const uint8_t s_sorted_partition_order[64] = - { - 1 - 1, 14 - 1, 2 - 1, 3 - 1, 16 - 1, 15 - 1, 11 - 1, 17 - 1, - 4 - 1, 24 - 1, 27 - 1, 7 - 1, 8 - 1, 22 - 1, 20 - 1, 30 - 1, - 9 - 1, 5 - 1, 10 - 1, 21 - 1, 6 - 1, 32 - 1, 23 - 1, 18 - 1, - 19 - 1, 12 - 1, 13 - 1, 31 - 1, 25 - 1, 26 - 1, 29 - 1, 28 - 1, - 33 - 1, 34 - 1, 35 - 1, 46 - 1, 47 - 1, 52 - 1, 50 - 1, 51 - 1, - 49 - 1, 39 - 1, 40 - 1, 38 - 1, 54 - 1, 53 - 1, 55 - 1, 37 - 1, - 58 - 1, 59 - 1, 56 - 1, 42 - 1, 41 - 1, 43 - 1, 44 - 1, 60 - 1, - 45 - 1, 57 - 1, 48 - 1, 36 - 1, 61 - 1, 64 - 1, 63 - 1, 62 - 1 - }; - - assert(s_sorted_partition_order[34] == 34); - - int best_key_partition = 0; - - for (uint32_t partition_iter = 0; (partition_iter < total_partitions) && (best_err > 0); partition_iter++) - { - const uint32_t partition = s_sorted_partition_order[partition_iter]; - - // Check to see if we should bother evaluating this partition at all, depending on the best partition found from the first 14. - if (pComp_params->m_mode17_partition_estimation_filterbank) - { - if ((partition_iter >= 14) && (partition_iter <= 34)) - { - const uint32_t best_key_partition_bitmask = 1 << (best_key_partition + 1); - if ((g_partition_predictors[partition] & best_key_partition_bitmask) == 0) - { - if (partition_iter == 34) - break; - - continue; - } - } - } - - const uint8_t* pPartition = &g_bc7_partition2[partition * 16]; - - color_rgba subset_colors[2][16]; - uint32_t subset_total_colors[2] = { 0, 0 }; - for (uint32_t index = 0; index < 16; index++) - subset_colors[pPartition[index]][subset_total_colors[pPartition[index]]++] = pPixels[index]; - - uint64_t total_subset_err = 0; - for (uint32_t subset = 0; (subset < 2) && (total_subset_err < best_err); subset++) - { - if (mode == 7) - total_subset_err += color_cell_compression_est_mode7(subset_total_colors[subset], &subset_colors[subset][0], pComp_params->m_perceptual, pweights, best_err); - else - total_subset_err += color_cell_compression_est_mode1(subset_total_colors[subset], &subset_colors[subset][0], pComp_params->m_perceptual, pweights, best_err); - } - - if (partition < 16) - { - total_subset_err = (uint64_t)((double)total_subset_err * pComp_params->m_low_frequency_partition_weight + .5f); - } - - if (total_subset_err < best_err) - { - best_err = total_subset_err; - best_partition = partition; - } - - // If the checkerboard pattern doesn't get the highest ranking vs. the previous (lower frequency) patterns, then just stop now because statistically the subsequent patterns won't do well either. - if ((partition == 34) && (best_partition != 34)) - break; - - if (partition_iter == 13) - best_key_partition = best_partition; - - } // partition - - return best_partition; -} - -static void set_block_bits(uint8_t* pBytes, uint32_t val, uint32_t num_bits, uint32_t* pCur_ofs) -{ - assert((num_bits <= 32) && (val < (1ULL << num_bits))); - while (num_bits) - { - const uint32_t n = minimumu(8 - (*pCur_ofs & 7), num_bits); - pBytes[*pCur_ofs >> 3] |= (uint8_t)(val << (*pCur_ofs & 7)); - val >>= n; - num_bits -= n; - *pCur_ofs += n; - } - assert(*pCur_ofs <= 128); -} - -struct bc7_optimization_results -{ - uint32_t m_mode; - uint32_t m_partition; - uint8_t m_selectors[16]; - uint8_t m_alpha_selectors[16]; - color_rgba m_low[3]; - color_rgba m_high[3]; - uint32_t m_pbits[3][2]; - uint32_t m_rotation; - uint32_t m_index_selector; -}; - -void encode_bc7_block(void* pBlock, const bc7_optimization_results* pResults) -{ - assert(pResults->m_index_selector <= 1); - assert(pResults->m_rotation <= 3); - - const uint32_t best_mode = pResults->m_mode; - - const uint32_t total_subsets = g_bc7_num_subsets[best_mode]; - const uint32_t total_partitions = 1 << g_bc7_partition_bits[best_mode]; - //const uint32_t num_rotations = 1 << g_bc7_rotation_bits[best_mode]; - //const uint32_t num_index_selectors = (best_mode == 4) ? 2 : 1; - - const uint8_t* pPartition; - if (total_subsets == 1) - pPartition = &g_bc7_partition1[0]; - else if (total_subsets == 2) - pPartition = &g_bc7_partition2[pResults->m_partition * 16]; - else - pPartition = &g_bc7_partition3[pResults->m_partition * 16]; - - uint8_t color_selectors[16]; - memcpy(color_selectors, pResults->m_selectors, 16); - - uint8_t alpha_selectors[16]; - memcpy(alpha_selectors, pResults->m_alpha_selectors, 16); - - color_rgba low[3], high[3]; - memcpy(low, pResults->m_low, sizeof(low)); - memcpy(high, pResults->m_high, sizeof(high)); - - uint32_t pbits[3][2]; - memcpy(pbits, pResults->m_pbits, sizeof(pbits)); - - int anchor[3] = { -1, -1, -1 }; - - for (uint32_t k = 0; k < total_subsets; k++) - { - uint32_t anchor_index = 0; - if (k) - { - if ((total_subsets == 3) && (k == 1)) - anchor_index = g_bc7_table_anchor_index_third_subset_1[pResults->m_partition]; - else if ((total_subsets == 3) && (k == 2)) - anchor_index = g_bc7_table_anchor_index_third_subset_2[pResults->m_partition]; - else - anchor_index = g_bc7_table_anchor_index_second_subset[pResults->m_partition]; - } - - anchor[k] = anchor_index; - - const uint32_t color_index_bits = get_bc7_color_index_size(best_mode, pResults->m_index_selector); - const uint32_t num_color_indices = 1 << color_index_bits; - - if (color_selectors[anchor_index] & (num_color_indices >> 1)) - { - for (uint32_t i = 0; i < 16; i++) - if (pPartition[i] == k) - color_selectors[i] = (uint8_t)((num_color_indices - 1) - color_selectors[i]); - - if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) - { - for (uint32_t q = 0; q < 3; q++) - { - uint8_t t = low[k].m_c[q]; - low[k].m_c[q] = high[k].m_c[q]; - high[k].m_c[q] = t; - } - } - else - { - color_rgba tmp = low[k]; - low[k] = high[k]; - high[k] = tmp; - } - - if (!g_bc7_mode_has_shared_p_bits[best_mode]) - { - uint32_t t = pbits[k][0]; - pbits[k][0] = pbits[k][1]; - pbits[k][1] = t; - } - } - - if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) - { - const uint32_t alpha_index_bits = get_bc7_alpha_index_size(best_mode, pResults->m_index_selector); - const uint32_t num_alpha_indices = 1 << alpha_index_bits; - - if (alpha_selectors[anchor_index] & (num_alpha_indices >> 1)) - { - for (uint32_t i = 0; i < 16; i++) - if (pPartition[i] == k) - alpha_selectors[i] = (uint8_t)((num_alpha_indices - 1) - alpha_selectors[i]); - - uint8_t t = low[k].m_c[3]; - low[k].m_c[3] = high[k].m_c[3]; - high[k].m_c[3] = t; - } - } - } - - uint8_t* pBlock_bytes = (uint8_t*)(pBlock); - memset(pBlock_bytes, 0, BC7ENC_BLOCK_SIZE); - - uint32_t cur_bit_ofs = 0; - set_block_bits(pBlock_bytes, 1 << best_mode, best_mode + 1, &cur_bit_ofs); - - if ((best_mode == 4) || (best_mode == 5)) - set_block_bits(pBlock_bytes, pResults->m_rotation, 2, &cur_bit_ofs); - - if (best_mode == 4) - set_block_bits(pBlock_bytes, pResults->m_index_selector, 1, &cur_bit_ofs); - - if (total_partitions > 1) - set_block_bits(pBlock_bytes, pResults->m_partition, (total_partitions == 64) ? 6 : 4, &cur_bit_ofs); - - const uint32_t total_comps = (best_mode >= 4) ? 4 : 3; - for (uint32_t comp = 0; comp < total_comps; comp++) - { - for (uint32_t subset = 0; subset < total_subsets; subset++) - { - set_block_bits(pBlock_bytes, low[subset].m_c[comp], (comp == 3) ? g_bc7_alpha_precision_table[best_mode] : g_bc7_color_precision_table[best_mode], &cur_bit_ofs); - set_block_bits(pBlock_bytes, high[subset].m_c[comp], (comp == 3) ? g_bc7_alpha_precision_table[best_mode] : g_bc7_color_precision_table[best_mode], &cur_bit_ofs); - } - } - - if (g_bc7_mode_has_p_bits[best_mode]) - { - for (uint32_t subset = 0; subset < total_subsets; subset++) - { - set_block_bits(pBlock_bytes, pbits[subset][0], 1, &cur_bit_ofs); - if (!g_bc7_mode_has_shared_p_bits[best_mode]) - set_block_bits(pBlock_bytes, pbits[subset][1], 1, &cur_bit_ofs); - } - } - - for (uint32_t y = 0; y < 4; y++) - { - for (uint32_t x = 0; x < 4; x++) - { - int idx = x + y * 4; - - uint32_t n = pResults->m_index_selector ? get_bc7_alpha_index_size(best_mode, pResults->m_index_selector) : get_bc7_color_index_size(best_mode, pResults->m_index_selector); - - if ((idx == anchor[0]) || (idx == anchor[1]) || (idx == anchor[2])) - n--; - - set_block_bits(pBlock_bytes, pResults->m_index_selector ? alpha_selectors[idx] : color_selectors[idx], n, &cur_bit_ofs); - } - } - - if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) - { - for (uint32_t y = 0; y < 4; y++) - { - for (uint32_t x = 0; x < 4; x++) - { - int idx = x + y * 4; - - uint32_t n = pResults->m_index_selector ? get_bc7_color_index_size(best_mode, pResults->m_index_selector) : get_bc7_alpha_index_size(best_mode, pResults->m_index_selector); - - if ((idx == anchor[0]) || (idx == anchor[1]) || (idx == anchor[2])) - n--; - - set_block_bits(pBlock_bytes, pResults->m_index_selector ? color_selectors[idx] : alpha_selectors[idx], n, &cur_bit_ofs); - } - } - } - - assert(cur_bit_ofs == 128); -} - -static void handle_alpha_block_mode5(const color_rgba* pPixels, const bc7enc_compress_block_params* pComp_params, color_cell_compressor_params* pParams, uint32_t lo_a, uint32_t hi_a, bc7_optimization_results* pOpt_results5, uint64_t* pMode5_err, uint64_t* pMode5_alpha_err) -{ - pParams->m_pSelector_weights = g_bc7_weights2; - pParams->m_pSelector_weightsx = (const vec4F*)g_bc7_weights2x; - pParams->m_num_selector_weights = 4; - - pParams->m_comp_bits = 7; - pParams->m_has_pbits = false; - pParams->m_endpoints_share_pbit = false; - pParams->m_has_alpha = false; - - pParams->m_perceptual = pComp_params->m_perceptual; - - pParams->m_num_pixels = 16; - pParams->m_pPixels = pPixels; - - color_cell_compressor_results results5; - results5.m_pSelectors = pOpt_results5->m_selectors; - - uint8_t selectors_temp[16]; - results5.m_pSelectors_temp = selectors_temp; - - *pMode5_err = color_cell_compression(5, pParams, &results5, pComp_params); - assert(*pMode5_err == results5.m_best_overall_err); - - pOpt_results5->m_low[0] = results5.m_low_endpoint; - pOpt_results5->m_high[0] = results5.m_high_endpoint; - - if (lo_a == hi_a) - { - *pMode5_alpha_err = 0; - pOpt_results5->m_low[0].m_c[3] = (uint8_t)lo_a; - pOpt_results5->m_high[0].m_c[3] = (uint8_t)hi_a; - memset(pOpt_results5->m_alpha_selectors, 0, sizeof(pOpt_results5->m_alpha_selectors)); - } - else - { - *pMode5_alpha_err = UINT64_MAX; - - const uint32_t total_passes = (pComp_params->m_uber_level >= 1) ? 3 : 2; - for (uint32_t pass = 0; pass < total_passes; pass++) - { - int32_t vals[4]; - vals[0] = lo_a; - vals[3] = hi_a; - - const int32_t w_s1 = 21, w_s2 = 43; - vals[1] = (vals[0] * (64 - w_s1) + vals[3] * w_s1 + 32) >> 6; - vals[2] = (vals[0] * (64 - w_s2) + vals[3] * w_s2 + 32) >> 6; - - uint8_t trial_alpha_selectors[16]; - - uint64_t trial_alpha_err = 0; - for (uint32_t i = 0; i < 16; i++) - { - const int32_t a = pParams->m_pPixels[i].m_c[3]; - - int s = 0; - int32_t be = iabs32(a - vals[0]); - int e = iabs32(a - vals[1]); if (e < be) { be = e; s = 1; } - e = iabs32(a - vals[2]); if (e < be) { be = e; s = 2; } - e = iabs32(a - vals[3]); if (e < be) { be = e; s = 3; } - - trial_alpha_selectors[i] = (uint8_t)s; - - uint32_t a_err = (uint32_t)(be * be) * pParams->m_weights[3]; - - trial_alpha_err += a_err; - } - - if (trial_alpha_err < *pMode5_alpha_err) - { - *pMode5_alpha_err = trial_alpha_err; - pOpt_results5->m_low[0].m_c[3] = (uint8_t)lo_a; - pOpt_results5->m_high[0].m_c[3] = (uint8_t)hi_a; - memcpy(pOpt_results5->m_alpha_selectors, trial_alpha_selectors, sizeof(pOpt_results5->m_alpha_selectors)); - } - - if (pass != (total_passes - 1U)) - { - float xl, xh; - compute_least_squares_endpoints_a(16, trial_alpha_selectors, (const vec4F*)g_bc7_weights2x, &xl, &xh, pParams->m_pPixels); - - uint32_t new_lo_a = clampi((int)floor(xl + .5f), 0, 255); - uint32_t new_hi_a = clampi((int)floor(xh + .5f), 0, 255); - if (new_lo_a > new_hi_a) - swapu(&new_lo_a, &new_hi_a); - - if ((new_lo_a == lo_a) && (new_hi_a == hi_a)) - break; - - lo_a = new_lo_a; - hi_a = new_hi_a; - } - } - - *pMode5_err += *pMode5_alpha_err; - } -} - -static void handle_alpha_block(void* pBlock, const color_rgba* pPixels, const bc7enc_compress_block_params* pComp_params, color_cell_compressor_params* pParams) -{ - assert((pComp_params->m_mode_mask & (1 << 6)) || (pComp_params->m_mode_mask & (1 << 5)) || (pComp_params->m_mode_mask & (1 << 7))); - - pParams->m_pSelector_weights = g_bc7_weights4; - pParams->m_pSelector_weightsx = (const vec4F*)g_bc7_weights4x; - pParams->m_num_selector_weights = 16; - pParams->m_comp_bits = 7; - pParams->m_has_pbits = true; - pParams->m_endpoints_share_pbit = false; - pParams->m_has_alpha = true; - pParams->m_perceptual = pComp_params->m_perceptual; - pParams->m_num_pixels = 16; - pParams->m_pPixels = pPixels; - - bc7_optimization_results opt_results6, opt_results5, opt_results7; - color_cell_compressor_results results6; - memset(&results6, 0, sizeof(results6)); - - uint64_t best_err = UINT64_MAX; - uint32_t best_mode = 0; - uint8_t selectors_temp[16]; - - if (pComp_params->m_mode_mask & (1 << 6)) - { - results6.m_pSelectors = opt_results6.m_selectors; - results6.m_pSelectors_temp = selectors_temp; - - best_err = (uint64_t)(color_cell_compression(6, pParams, &results6, pComp_params) * pComp_params->m_mode6_error_weight + .5f); - best_mode = 6; - } - - if ((best_err > 0) && (pComp_params->m_mode_mask & (1 << 5))) - { - uint32_t lo_a = 255, hi_a = 0; - for (uint32_t i = 0; i < 16; i++) - { - uint32_t a = pPixels[i].m_c[3]; - lo_a = minimumu(lo_a, a); - hi_a = maximumu(hi_a, a); - } - - uint64_t mode5_err, mode5_alpha_err; - handle_alpha_block_mode5(pPixels, pComp_params, pParams, lo_a, hi_a, &opt_results5, &mode5_err, &mode5_alpha_err); - - mode5_err = (uint64_t)(mode5_err * pComp_params->m_mode5_error_weight + .5f); - - if (mode5_err < best_err) - { - best_err = mode5_err; - best_mode = 5; - } - } - - if ((best_err > 0) && (pComp_params->m_mode_mask & (1 << 7))) - { - const uint32_t trial_partition = estimate_partition(pPixels, pComp_params, pParams->m_weights, 7); - - pParams->m_pSelector_weights = g_bc7_weights2; - pParams->m_pSelector_weightsx = (const vec4F*)g_bc7_weights2x; - pParams->m_num_selector_weights = 4; - pParams->m_comp_bits = 5; - pParams->m_has_pbits = true; - pParams->m_endpoints_share_pbit = false; - pParams->m_has_alpha = true; - - const uint8_t* pPartition = &g_bc7_partition2[trial_partition * 16]; - - color_rgba subset_colors[2][16]; - - uint32_t subset_total_colors7[2] = { 0, 0 }; - - uint8_t subset_pixel_index7[2][16]; - uint8_t subset_selectors7[2][16]; - color_cell_compressor_results subset_results7[2]; - - for (uint32_t idx = 0; idx < 16; idx++) - { - const uint32_t p = pPartition[idx]; - subset_colors[p][subset_total_colors7[p]] = pPixels[idx]; - subset_pixel_index7[p][subset_total_colors7[p]] = (uint8_t)idx; - subset_total_colors7[p]++; - } - - uint64_t trial_err = 0; - for (uint32_t subset = 0; subset < 2; subset++) - { - pParams->m_num_pixels = subset_total_colors7[subset]; - pParams->m_pPixels = &subset_colors[subset][0]; - - color_cell_compressor_results* pResults = &subset_results7[subset]; - pResults->m_pSelectors = &subset_selectors7[subset][0]; - pResults->m_pSelectors_temp = selectors_temp; - uint64_t err = color_cell_compression(7, pParams, pResults, pComp_params); - trial_err += err; - if ((uint64_t)(trial_err * pComp_params->m_mode7_error_weight + .5f) > best_err) - break; - - } // subset - - const uint64_t mode7_trial_err = (uint64_t)(trial_err * pComp_params->m_mode7_error_weight + .5f); - - if (mode7_trial_err < best_err) - { - best_err = mode7_trial_err; - best_mode = 7; - opt_results7.m_mode = 7; - opt_results7.m_partition = trial_partition; - opt_results7.m_index_selector = 0; - opt_results7.m_rotation = 0; - for (uint32_t subset = 0; subset < 2; subset++) - { - for (uint32_t i = 0; i < subset_total_colors7[subset]; i++) - opt_results7.m_selectors[subset_pixel_index7[subset][i]] = subset_selectors7[subset][i]; - opt_results7.m_low[subset] = subset_results7[subset].m_low_endpoint; - opt_results7.m_high[subset] = subset_results7[subset].m_high_endpoint; - opt_results7.m_pbits[subset][0] = subset_results7[subset].m_pbits[0]; - opt_results7.m_pbits[subset][1] = subset_results7[subset].m_pbits[1]; - } - } - } - - if (best_mode == 7) - { - encode_bc7_block(pBlock, &opt_results7); - } - else if (best_mode == 5) - { - opt_results5.m_mode = 5; - opt_results5.m_partition = 0; - opt_results5.m_rotation = 0; - opt_results5.m_index_selector = 0; - - encode_bc7_block(pBlock, &opt_results5); - } - else if (best_mode == 6) - { - opt_results6.m_mode = 6; - opt_results6.m_partition = 0; - opt_results6.m_low[0] = results6.m_low_endpoint; - opt_results6.m_high[0] = results6.m_high_endpoint; - opt_results6.m_pbits[0][0] = results6.m_pbits[0]; - opt_results6.m_pbits[0][1] = results6.m_pbits[1]; - opt_results6.m_rotation = 0; - opt_results6.m_index_selector = 0; - - encode_bc7_block(pBlock, &opt_results6); - } - else - { - assert(0); - } -} - -static void handle_opaque_block(void* pBlock, const color_rgba* pPixels, const bc7enc_compress_block_params* pComp_params, color_cell_compressor_params* pParams) -{ - assert((pComp_params->m_mode_mask & (1 << 6)) || (pComp_params->m_mode_mask & (1 << 1))); - - uint8_t selectors_temp[16]; - - bc7_optimization_results opt_results; - - uint64_t best_err = UINT64_MAX; - - pParams->m_perceptual = pComp_params->m_perceptual; - pParams->m_num_pixels = 16; - pParams->m_pPixels = pPixels; - pParams->m_has_alpha = false; - - opt_results.m_partition = 0; - opt_results.m_index_selector = 0; - opt_results.m_rotation = 0; - - // Mode 6 - if (pComp_params->m_mode_mask & (1 << 6)) - { - pParams->m_pSelector_weights = g_bc7_weights4; - pParams->m_pSelector_weightsx = (const vec4F*)g_bc7_weights4x; - pParams->m_num_selector_weights = 16; - pParams->m_comp_bits = 7; - pParams->m_has_pbits = true; - pParams->m_endpoints_share_pbit = false; - - color_cell_compressor_results results6; - results6.m_pSelectors = opt_results.m_selectors; - results6.m_pSelectors_temp = selectors_temp; - - best_err = (uint64_t)(color_cell_compression(6, pParams, &results6, pComp_params) * pComp_params->m_mode6_error_weight + .5f); - - opt_results.m_mode = 6; - opt_results.m_low[0] = results6.m_low_endpoint; - opt_results.m_high[0] = results6.m_high_endpoint; - opt_results.m_pbits[0][0] = results6.m_pbits[0]; - opt_results.m_pbits[0][1] = results6.m_pbits[1]; - } - - // Mode 1 - if ((best_err > 0) && (pComp_params->m_max_partitions > 0) && (pComp_params->m_mode_mask & (1 << 1))) - { - const uint32_t trial_partition = estimate_partition(pPixels, pComp_params, pParams->m_weights, 1); - - pParams->m_pSelector_weights = g_bc7_weights3; - pParams->m_pSelector_weightsx = (const vec4F*)g_bc7_weights3x; - pParams->m_num_selector_weights = 8; - pParams->m_comp_bits = 6; - pParams->m_has_pbits = true; - pParams->m_endpoints_share_pbit = true; - - const uint8_t* pPartition = &g_bc7_partition2[trial_partition * 16]; - - color_rgba subset_colors[2][16]; - - uint32_t subset_total_colors1[2] = { 0, 0 }; - - uint8_t subset_pixel_index1[2][16]; - uint8_t subset_selectors1[2][16]; - color_cell_compressor_results subset_results1[2]; - - for (uint32_t idx = 0; idx < 16; idx++) - { - const uint32_t p = pPartition[idx]; - subset_colors[p][subset_total_colors1[p]] = pPixels[idx]; - subset_pixel_index1[p][subset_total_colors1[p]] = (uint8_t)idx; - subset_total_colors1[p]++; - } - - uint64_t trial_err = 0; - for (uint32_t subset = 0; subset < 2; subset++) - { - pParams->m_num_pixels = subset_total_colors1[subset]; - pParams->m_pPixels = &subset_colors[subset][0]; - - color_cell_compressor_results* pResults = &subset_results1[subset]; - pResults->m_pSelectors = &subset_selectors1[subset][0]; - pResults->m_pSelectors_temp = selectors_temp; - uint64_t err = color_cell_compression(1, pParams, pResults, pComp_params); - - trial_err += err; - if ((uint64_t)(trial_err * pComp_params->m_mode1_error_weight + .5f) > best_err) - break; - - } // subset - - const uint64_t mode1_trial_err = (uint64_t)(trial_err * pComp_params->m_mode1_error_weight + .5f); - if (mode1_trial_err < best_err) - { - best_err = mode1_trial_err; - opt_results.m_mode = 1; - opt_results.m_partition = trial_partition; - for (uint32_t subset = 0; subset < 2; subset++) - { - for (uint32_t i = 0; i < subset_total_colors1[subset]; i++) - opt_results.m_selectors[subset_pixel_index1[subset][i]] = subset_selectors1[subset][i]; - opt_results.m_low[subset] = subset_results1[subset].m_low_endpoint; - opt_results.m_high[subset] = subset_results1[subset].m_high_endpoint; - opt_results.m_pbits[subset][0] = subset_results1[subset].m_pbits[0]; - } - } - } - - encode_bc7_block(pBlock, &opt_results); -} - -bool bc7enc_compress_block(void* pBlock, const void* pPixelsRGBA, const bc7enc_compress_block_params* pComp_params) -{ - assert(g_bc7_mode_1_optimal_endpoints[255][0].m_hi != 0); - - const color_rgba* pPixels = (const color_rgba*)(pPixelsRGBA); - - color_cell_compressor_params params; - if (pComp_params->m_perceptual) - { - // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.709_conversion - const float pr_weight = (.5f / (1.0f - .2126f)) * (.5f / (1.0f - .2126f)); - const float pb_weight = (.5f / (1.0f - .0722f)) * (.5f / (1.0f - .0722f)); - params.m_weights[0] = (int)(pComp_params->m_weights[0] * 4.0f); - params.m_weights[1] = (int)(pComp_params->m_weights[1] * 4.0f * pr_weight); - params.m_weights[2] = (int)(pComp_params->m_weights[2] * 4.0f * pb_weight); - params.m_weights[3] = pComp_params->m_weights[3] * 4; - } - else - memcpy(params.m_weights, pComp_params->m_weights, sizeof(params.m_weights)); - - if (pComp_params->m_force_alpha) - { - handle_alpha_block(pBlock, pPixels, pComp_params, ¶ms); - return true; - } - - for (uint32_t i = 0; i < 16; i++) - { - if (pPixels[i].m_c[3] < 255) - { - handle_alpha_block(pBlock, pPixels, pComp_params, ¶ms); - return true; - } - } - handle_opaque_block(pBlock, pPixels, pComp_params, ¶ms); - return false; -} - -static const uint8_t g_tdefl_small_dist_extra[512] = -{ - 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7 -}; - -static const uint8_t g_tdefl_large_dist_extra[128] = -{ - 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 -}; - -static inline uint32_t compute_match_cost_estimate(uint32_t dist, uint32_t match_len_in_bytes) -{ - assert(match_len_in_bytes <= 258); - - uint32_t len_cost = 6; - if (match_len_in_bytes >= 12) - len_cost = 9; - else if (match_len_in_bytes >= 8) - len_cost = 8; - else if (match_len_in_bytes >= 6) - len_cost = 7; - - uint32_t dist_cost = 5; - if (dist < 512) - dist_cost += g_tdefl_small_dist_extra[dist & 511]; - else - { - dist_cost += g_tdefl_large_dist_extra[std::min(dist, 32767) >> 8]; - while (dist >= 32768) - { - dist_cost++; - dist >>= 1; - } - } - return len_cost + dist_cost; -} - -class tracked_stat -{ -public: - tracked_stat() { clear(); } - - void clear() { m_num = 0; m_total = 0; m_total2 = 0; } - - void update(uint32_t val) { m_num++; m_total += val; m_total2 += val * val; } - - tracked_stat& operator += (uint32_t val) { update(val); return *this; } - - uint32_t get_number_of_values() { return m_num; } - uint64_t get_total() const { return m_total; } - uint64_t get_total2() const { return m_total2; } - - float get_average() const { return m_num ? (float)m_total / m_num : 0.0f; }; - float get_std_dev() const { return m_num ? sqrtf((float)(m_num * m_total2 - m_total * m_total)) / m_num : 0.0f; } - float get_variance() const { float s = get_std_dev(); return s * s; } - -private: - uint32_t m_num; - uint64_t m_total; - uint64_t m_total2; -}; - -static inline float compute_block_max_std_dev(const color_rgba* pPixels) -{ - tracked_stat r_stats, g_stats, b_stats, a_stats; - - for (uint32_t i = 0; i < 16; i++) - { - r_stats.update(pPixels[i].m_c[0]); - g_stats.update(pPixels[i].m_c[1]); - b_stats.update(pPixels[i].m_c[2]); - a_stats.update(pPixels[i].m_c[3]); - } - - return std::max(std::max(std::max(r_stats.get_std_dev(), g_stats.get_std_dev()), b_stats.get_std_dev()), a_stats.get_std_dev()); -} - -struct bc7_block -{ - uint8_t m_bytes[16]; - - uint32_t get_mode() const - { - uint32_t bc7_mode = 0; - while (((m_bytes[0] & (1 << bc7_mode)) == 0) && (bc7_mode < 8)) - bc7_mode++; - return bc7_mode; - } -}; - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. -If you use this software in a product, attribution / credits is requested but not required. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright(c) 2020-2021 Richard Geldreich, Jr. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files(the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions : -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain(www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non - commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain.We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors.We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ \ No newline at end of file diff --git a/src/ByteEngine/Resources/CommonPermutation.hpp b/src/ByteEngine/Resources/CommonPermutation.hpp deleted file mode 100644 index 87527d2b..00000000 --- a/src/ByteEngine/Resources/CommonPermutation.hpp +++ /dev/null @@ -1,183 +0,0 @@ -#pragma once - -#include "PermutationManager.hpp" -#include "ByteEngine/Render/ShaderGenerator.h" -#include "ByteEngine/Render/Types.hpp" - -struct CommonPermutation : PermutationManager { - CommonPermutation(const GTSL::StringView name) : PermutationManager(name, u8"CommonPermutation") {} - - void Initialize(GPipeline* pipeline, ShaderGenerationData& shader_generation_data) override { - auto descriptorSetBlockHandle = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE , u8"descriptorSetBlock"); - auto firstDescriptorSetBlockHandle = pipeline->DeclareScope(descriptorSetBlockHandle, u8"descriptorSet"); - pipeline->DeclareVariable(firstDescriptorSetBlockHandle, { u8"texture2D[]", u8"textures" }); - pipeline->DeclareVariable(firstDescriptorSetBlockHandle, { u8"image2D[]", u8"images" }); - pipeline->DeclareVariable(firstDescriptorSetBlockHandle, { u8"sampler", u8"s" }); - - pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"InstanceData", INSTANCE_DATA); - - pipeline->SetMakeStruct(pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"TextureReference", { { u8"uint32", u8"Instance" } })); - pipeline->SetMakeStruct(pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"ImageReference", { { u8"uint32", u8"Instance" } })); - pipeline->SetMakeStruct(pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"IndirectDispatchCommand", INDIRECT_DISPATCH_COMMAND_DATA)); - pipeline->SetMakeStruct(pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"PointLightData", POINT_LIGHT_DATA)); - pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"LightingData", LIGHTING_DATA); - - pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"uint32", { { u8"uint32", u8"a"} }); - pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"vec2s", { { u8"u16vec2", u8"wh"} }); - pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"vec2f", { { u8"vec2f", u8"xy"} }); - pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"vec3f", { { u8"vec3f", u8"xyz"} }); - pipeline->DeclareStruct(GPipeline::GLOBAL_SCOPE, u8"vec4f", { { u8"vec4f", u8"xyzw"} }); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"Barycenter", { { u8"vec2f", u8"coords" } }, u8"return vec3(1.0f - coords.x - coords.y, coords.x, coords.y);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec2f", u8"Normalize", { { u8"vec2u", u8"pos" }, { u8"vec2u", u8"extent" } }, u8"return (vec2f(pos) + 0.5f) / vec2f(extent);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"Barycenter", { { u8"vec3f", u8"p" }, { u8"vec3f", u8"a" }, { u8"vec3f", u8"b" }, { u8"vec3f", u8"c" } }, u8"vec3f v0 = b - a, v1 = c - a, v2 = p - a; float32 d00 = dot(v0, v0); float32 d01 = dot(v0, v1); float32 d11 = dot(v1, v1); float32 d20 = dot(v2, v0); float32 d21 = dot(v2, v1); float32 invDenom = 1.0f / (d00 * d11 - d01 * d01); v = (d11 * d20 - d01 * d21) * invDenom; w = (d00 * d21 - d01 * d20) * invDenom; return vec3f(1.0f - v - w, v, w);"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec2u", u8"GetExtent", { { u8"ImageReference", u8"image" } }, u8"return vec2u(imageSize(images[nonuniformEXT(image.Instance)]));"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec2u", u8"GetExtent", { { u8"TextureReference", u8"texture" } }, u8"return vec2u(textureSize(sampler2D(textures[nonuniformEXT(texture.Instance)], s), 0));"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec4f", u8"Sample", { { u8"TextureReference", u8"tex" }, { u8"vec2f", u8"texCoord" } }, u8"return texture(sampler2D(textures[nonuniformEXT(tex.Instance)], s), texCoord);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec4f", u8"Sample", { { u8"TextureReference", u8"tex" }, { u8"vec2f", u8"texCoord" }, { u8"float32", u8"mip" } }, u8"return textureLod(sampler2D(textures[nonuniformEXT(tex.Instance)], s), texCoord, mip);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec4f", u8"SampleNormal", { { u8"TextureReference", u8"tex" }, { u8"vec2f", u8"texCoord" } }, u8"return normalize(texture(sampler2D(textures[nonuniformEXT(tex.Instance)], s), texCoord) * 2.0f - 1.0f);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec4f", u8"Sample", { { u8"TextureReference", u8"tex" }, { u8"vec2f", u8"texCoord" }, { u8"vec2f", u8"ddx" }, { u8"vec2f", u8"ddy" } }, u8"return textureGrad(sampler2D(textures[nonuniformEXT(tex.Instance)], s), texCoord, ddx, ddy);"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec4f", u8"Sample", { { u8"TextureReference", u8"tex" }, { u8"uvec2", u8"pos" } }, u8"return texelFetch(sampler2D(textures[nonuniformEXT(tex.Instance)], s), ivec2(pos % GetExtent(tex)), 0);"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec4u", u8"SampleUint", { { u8"TextureReference", u8"tex" }, { u8"uvec2", u8"pos" } }, u8"return texelFetch(usampler2D(textures[nonuniformEXT(tex.Instance)], s), ivec2(pos), 0);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec4f", u8"Sample", { { u8"ImageReference", u8"img" }, { u8"uvec2", u8"pos" } }, u8"return imageLoad(images[nonuniformEXT(img.Instance)], ivec2(pos));"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"Sample_float32_", { { u8"TextureReference", u8"texture" }, { u8"uvec2", u8"pos" } }, u8"return Sample(texture, pos).x;"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"void", u8"Write", { { u8"ImageReference", u8"img" }, { u8"uvec2", u8"pos" }, { u8"vec4f", u8"value" } }, u8"imageStore(images[nonuniformEXT(img.Instance)], ivec2(pos), value);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"void", u8"Write", { { u8"ImageReference", u8"img" }, { u8"vec2f", u8"pos" }, { u8"vec4f", u8"value" } }, u8"imageStore(images[nonuniformEXT(img.Instance)], ivec2(pos * vec2f(imageSize(images[nonuniformEXT(img.Instance)]))), value);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"void", u8"Write", { { u8"ImageReference", u8"img" }, { u8"uvec2", u8"pos" }, { u8"float32", u8"value" } }, u8"imageStore(images[nonuniformEXT(img.Instance)], ivec2(pos), vec4f(value));"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"X", { { u8"vec4f", u8"vec" } }, u8"return vec.x;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"Y", { { u8"vec4f", u8"vec" } }, u8"return vec.y;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"Z", { { u8"vec4f", u8"vec" } }, u8"return vec.z;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"FresnelSchlick", { { u8"float32", u8"cosTheta" }, { u8"vec3f", u8"F0" } }, u8"return F0 + (1.0 - F0) * pow(max(0.0, 1.0 - cosTheta), 5.0);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"Normalize", { { u8"vec3f", u8"a" } }, u8"return normalize(a);"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"Sigmoid", { { u8"float32", u8"x" } }, u8"return 1.0 / (1.0 + pow(x / (1.0 - x), -3.0));"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"WorldPositionFromDepth", { { u8"vec2f", u8"texture_coordinate" }, { u8"float32", u8"depth" }, { u8"matrix4f", u8"inverse_proj_view_matrix" } }, u8"vec4 clipSpacePosition = vec4((texture_coordinate * 2.0) - 1.0, depth, 1.0); vec4f position = inverse_proj_view_matrix * clipSpacePosition; return position.xyz / position.w;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"WorldPositionFromDepth", { { u8"vec2f", u8"texture_coordinate" }, { u8"float32", u8"depth" }, { u8"matrix4f", u8"inverse_proj_matrix" }, { u8"matrix4f", u8"inverse_view_matrix" } }, u8"vec2 ndc = (texture_coordinate * 2.0) - 1.0; vec4 clipSpacePosition = vec4(ndc, depth, 1.0); vec4f viewSpacePosition = inverse_proj_matrix * clipSpacePosition; viewSpacePosition /= viewSpacePosition.w; return (inverse_view_matrix * viewSpacePosition).xyz;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"PI", { }, u8"return 3.14159265359f;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec2f", u8"SphericalCoordinates", { { u8"vec3f", u8"v" } }, u8"vec2f uv = vec2(atan(v.z, v.x), asin(v.y)); uv *= vec2(0.1591, 0.3183); uv += 0.5; return uv; "); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"DistributionGGX", { { u8"vec3f", u8"N"}, { u8"vec3f", u8"H"}, { u8"float32", u8"roughness"} }, u8"float32 a = roughness * roughness; float32 a2 = a * a; float32 NdotH = max(dot(N, H), 0.0); float32 NdotH2 = NdotH * NdotH; float32 num = a2; float32 denom = (NdotH2 * (a2 - 1.0) + 1.0); denom = PI() * denom * denom; return num / denom;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"GeometrySchlickGGX", { { u8"float32", u8"NdotV"}, { u8"float32", u8"roughness"} }, u8"float32 r = (roughness + 1.0); float32 k = (r * r) / 8.0; float32 num = NdotV; float32 denom = NdotV * (1.0 - k) + k; return num / denom;"); - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"GeometrySmith", { { u8"vec3f", u8"N"}, { u8"vec3f", u8"V"}, { u8"vec3f", u8"L"}, { u8"float32", u8"roughness" } }, u8"float32 NdotV = max(dot(N, V), 0.0); float32 NdotL = max(dot(N, L), 0.0); float32 ggx2 = GeometrySchlickGGX(NdotV, roughness); float32 ggx1 = GeometrySchlickGGX(NdotL, roughness); return ggx1 * ggx2;"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"LinearizeDepth", { { u8"float32", u8"depth"}, { u8"float32", u8"near"}, { u8"float32", u8"far" } }, - u8"return ((near * far) / (far + depth * (near - far))) * far;" - //u8"return (2.f * near * far) / (far + near - depth * (far - near));" - ); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"mat3f", u8"AngleAxis3x3", { { u8"vec3f", u8"axis"}, { u8"float32", u8"angle"} }, - u8"float32 c = cos(angle), s = sin(angle); float32 t = 1 - c; float32 x = axis.x; float32 y = axis.y; float z = axis.z; return mat3f(t * x * x + c, t * x * y - s * z, t * x * z + s * y, t * x * y + s * z, t * y * y + c, t * y * z - s * x, t * x * z - s * y, t * y * z + s * x, t * z * z + c);"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"Perpendicular", { { u8"vec3f", u8"u"} }, u8"vec3f a = abs(u); uint32 xm = ((a.x - a.y)<0 && (a.x - a.z)<0) ? 1 : 0; uint32 ym = (a.y - a.z)<0 ? (1 ^ xm) : 0; uint32 zm = 1 ^ (xm | ym); return cross(u, vec3f(xm, ym, zm));"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"uint32", u8"MakeRandomSeed", { { u8"uint32", u8"val0" }, { u8"uint32", u8"val1" } }, - u8"uint32 v0 = val0, v1 = val1, s0 = 0; for (uint n = 0; n < 16; n++) { s0 += 0x9e3779b9; v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4); v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e); } return v0;"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"NextRandom", { { u8"inout uint32", u8"s" } }, - u8"s += 1375; return fract(sin(dot(vec2f(uint(s), uint(s) + 7), vec2f(12.9898,78.233))) * 43758.5453123);"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec2f", u8"MapRectangleToCircle", { { u8"vec2f", u8"rect" } }, - u8"float32 radius = sqrt(rect.x); float32 angle = rect.y * 2 * PI(); return vec2f(radius * cos(angle), radius * sin(angle));"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"SphereDirection", { { u8"vec2f", u8"rect" }, { u8"vec3f", u8"direction" }, { u8"float32", u8"radius" } }, - u8"vec2f point = MapRectangleToCircle(rect) * radius; vec3f tangent = normalize(cross(direction, vec3f(0, 1, 0))); vec3f bitangent = normalize(cross(tangent, direction)); return normalize(direction + point.x * tangent + point.y * bitangent);"); - - // [Eberly2014] GPGPU Programming for Games and Science - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"float32", u8"FastAcos", { { u8"float32", u8"x" } }, u8"float res = -0.156583 * abs(x) + (PI() / 2); res *= sqrt(1.0 - abs(x)); return x >= 0 ? res : PI() - res;"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"CosineWeightedHemisphereSample", { { u8"vec3f", u8"hitNorm" }, { u8"vec2f", u8"random" } }, - u8"vec3f bitangent = Perpendicualar(hitNorm); vec3f tangent = cross(bitangent, hitNorm); float32 r = sqrt(random.x); float phi = 2.0f * PI() * random.y; return tangent * (r * cos(phi).x) + bitangent * (r * sin(phi)) + hitNorm.xyz * sqrt(1 - random.x);"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"ViewSpacePositionFromDepth", { { u8"vec2f", u8"texture_coordinate" }, { u8"float32", u8"depth" }, { u8"matrix4f", u8"inverse_proj_matrix" } }, u8"vec4f viewPositionH = inverse_proj_matrix * vec4f((texture_coordinate.x - 0.5f) * 2, (texture_coordinate.y - 0.5f) * 2, depth, 1); return viewPositionH.xyz / viewPositionH.w;"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"SampleViewSpacePosition", { { u8"TextureReference", u8"tex" }, { u8"vec2f", u8"coords" }, { u8"ViewData", u8"view_data" }, { u8"float32", u8"mip" } }, u8"float32 rawDepth = Sample(tex, coords, mip).x; return ViewSpacePositionFromDepth(coords, rawDepth, view_data.projInverse);"); - - vertexShaderScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"VertexShader"); - fragmentShaderScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"FragmentShader"); - computeShaderScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"ComputeShader"); - rayGenShaderScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"RayGenShader"); - closestHitShaderScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"ClosestHitShader"); - anyHitShaderScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"AnyHitShader"); - missShaderScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"MissShader"); - - pipeline->DeclareFunction(GPipeline::GLOBAL_SCOPE, u8"vec3f", u8"DirectLighting", { {u8"vec3f", u8"light_position"}, {u8"vec3f", u8"camera_position"}, {u8"vec3f", u8"surface_world_position"}, {u8"vec3f", u8"surface_normal"}, {u8"vec3f", u8"light_color"}, {u8"vec3f", u8"albedo"}, {u8"vec3f", u8"F0"}, {u8"float32", u8"roughness"} }, u8R"( -vec3f V = normalize(camera_position - surface_world_position); -vec3f L = normalize(light_position - surface_world_position); -vec3f H = normalize(V + L); -float32 distance = length(light_position - surface_world_position); -float32 attenuation = 1.0f / (distance * distance); -vec3f radiance = light_color * attenuation; -float32 NDF = DistributionGGX(surface_normal, H, roughness); -float32 G = GeometrySmith(surface_normal, V, L, roughness); -vec3f F = FresnelSchlick(max(dot(H, V), 0.0), F0); -vec3f numerator = NDF * G * F; -float32 denominator = 4.0f * max(dot(surface_normal, V), 0.0f) * max(dot(surface_normal, L), 0.0f) + 0.0001f; -vec3f specular = numerator / denominator; -float32 NdotL = max(dot(surface_normal, L), 0.0f); -vec3f kS = F; vec3f kD = vec3f(1.0) - kS; kD *= 1.0 - 0; -return (kD * albedo / PI() + specular) * radiance * NdotL;)"); - - pipeline->DeclareFunction(fragmentShaderScope, u8"vec2f", u8"GetFragmentPosition", {}, u8"return gl_FragCoord.xy;"); - pipeline->DeclareFunction(fragmentShaderScope, u8"float32", u8"GetFragmentDepth", {}, u8"return gl_FragCoord.z;"); - - pipeline->DeclareVariable(closestHitShaderScope, { u8"vec2f", u8"hitBarycenter" }); - pipeline->DeclareFunction(closestHitShaderScope, u8"vec3f", u8"GetVertexBarycenter", {}, u8"return Barycenter(hitBarycenter);"); - - commonScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"CommonPermutation"); - - pipeline->DeclareStruct(commonScope, u8"GlobalData", GLOBAL_DATA); - pipeline->DeclareStruct(commonScope, u8"ViewData", VIEW_DATA); - pipeline->DeclareStruct(commonScope, u8"CameraData", CAMERA_DATA); - - pipeline->DeclareFunction(commonScope, u8"bool", u8"IsInExtent", { { u8"vec2u", u8"value" }, { u8"vec2u", u8"extent" } }, u8"return value.x < extent.x && value.y < extent.y;"); - - //pipeline->DeclareVariable(fragmentShaderScope, { u8"vec4f", u8"Color" }); - //pipeline->DeclareVariable(fragmentShaderScope, { u8"vec4f", u8"Normal" }); - - auto glPositionHandle = pipeline->DeclareVariable(vertexShaderScope, { u8"vec4f", u8"gl_Position" }); - pipeline->AddMemberDeductionGuide(vertexShaderScope, u8"vertexPosition", { glPositionHandle }); - - pipeline->DeclareFunction(fragmentShaderScope, u8"vec2f", u8"GetSurfaceTextureCoordinates", {}, u8"return vertexTextureCoordinates;"); - pipeline->DeclareFunction(fragmentShaderScope, u8"vec3f", u8"GetSurfaceWorldSpacePosition", {}, u8"return worldSpacePosition;"); - pipeline->DeclareFunction(fragmentShaderScope, u8"vec3f", u8"GetSurfaceWorldSpaceNormal", {}, u8"return worldSpaceNormal;"); - pipeline->DeclareFunction(fragmentShaderScope, u8"vec3f", u8"GetSurfaceViewSpacePosition", {}, u8"return viewSpacePosition;"); - pipeline->DeclareFunction(fragmentShaderScope, u8"vec4f", u8"GetSurfaceViewSpaceNormal", {}, u8"return vec4(viewSpaceNormal, 0);"); - - pipeline->DeclareFunction(computeShaderScope, u8"uvec3", u8"GetThreadIndex", {}, u8"return gl_LocalInvocationID;"); - pipeline->DeclareFunction(computeShaderScope, u8"uvec3", u8"GetWorkGroupIndex", {}, u8"return gl_WorkGroupID;"); - pipeline->DeclareFunction(computeShaderScope, u8"uvec3", u8"GetGlobalIndex", {}, u8"return gl_GlobalInvocationID;"); - pipeline->DeclareFunction(computeShaderScope, u8"uvec3", u8"GetWorkGroupExtent", {}, u8"return gl_WorkGroupSize;"); - pipeline->DeclareFunction(computeShaderScope, u8"uvec3", u8"GetGlobalExtent", {}, u8"return gl_WorkGroupSize * gl_NumWorkGroups;"); - pipeline->DeclareFunction(computeShaderScope, u8"uint32", u8"GetLocalInvocationIndex", {}, u8"return gl_LocalInvocationIndex;"); - - pipeline->DeclareFunction(computeShaderScope, u8"uint32", u8"GetLaneIndex", {}, u8"return gl_SubgroupInvocationID;"); - pipeline->DeclareFunction(computeShaderScope, u8"uint32", u8"GetWaveLaneCount", {}, u8"return gl_SubgroupSize;"); - - pipeline->DeclareFunction(computeShaderScope, u8"void", u8"GroupMemoryAndSynchronize", {}, u8"groupMemoryBarrier(); barrier();"); - - pipeline->DeclareFunction(computeShaderScope, u8"vec3f", u8"GetNormalizedGlobalIndex", {}, u8"return (vec3f(GetGlobalIndex()) + vec3f(0.5f)) / vec3f(GetGlobalExtent());"); - - pipeline->DeclareFunction(computeShaderScope, u8"int32", u8"IntegerDivideBy_11", { { u8"int32", u8"i" } }, u8"return (i * 5958) >> 16;"); - pipeline->DeclareFunction(computeShaderScope, u8"vec2i", u8"IntModAndDiv_11", { { u8"int32", u8"i" } }, u8"ivec2 v = ivec2(i, IntegerDivideBy_11(i)); v.x -= v.y * 11; return v;"); - - pipeline->DeclareFunction(computeShaderScope, u8"float32", u8"ReadValueFromThread", { { u8"float32", u8"x" }, { u8"uint32", u8"i" } }, u8"return subgroupShuffle(x, i);"); - pipeline->DeclareFunction(computeShaderScope, u8"uint32", u8"ReadValueFromThread", { { u8"uint32", u8"x" }, { u8"uint32", u8"i" } }, u8"return subgroupShuffle(x, i);"); - - pipeline->DeclareFunction(rayGenShaderScope, u8"vec2u", u8"GetFragmentPosition", {}, u8"return gl_LaunchIDEXT.xy;"); - pipeline->DeclareFunction(rayGenShaderScope, u8"vec2f", u8"GetNormalizedFragmentPosition", {}, u8"vec2f pixelCenter = vec2f(gl_LaunchIDEXT.xy) + vec2f(0.5f); return pixelCenter / vec2f(gl_LaunchSizeEXT.xy);"); - - computeRenderPassScope = pipeline->DeclareScope(commonScope, u8"ComputeRenderPass"); - pipeline->DeclareFunction(computeRenderPassScope, u8"vec2u", u8"GetPixelPosition", {}, u8"return GetGlobalIndex().xy;"); - pipeline->DeclareFunction(computeRenderPassScope, u8"vec2f", u8"GetNormalizedPixelPosition", {}, u8"return GetNormalizedGlobalIndex().xy;"); - pipeline->DeclareFunction(computeRenderPassScope, u8"vec4f", u8"ACES", { { u8"vec4f", u8"x" } }, u8"const float a = 2.51; const float b = 0.03; const float c = 2.43; const float d = 0.59; const float e = 0.14; return (x * (a * x + b)) / (x * (c * x + d) + e);"); - pipeline->DeclareFunction(computeRenderPassScope, u8"vec4f", u8"Filmic", { { u8"vec4f", u8"x" } }, u8"vec3 X = max(vec3(0.0), vec3f(x) - vec3f(0.004)); vec3 result = (X * (6.2 * X + 0.5)) / (X * (6.2 * X + 1.7) + 0.06); return vec4f(pow(result, vec3(2.2)), x.a); "); - } - - GPipeline::ElementHandle commonScope, computeRenderPassScope; - GPipeline::ElementHandle vertexShaderScope, fragmentShaderScope, computeShaderScope, rayGenShaderScope, closestHitShaderScope, anyHitShaderScope, missShaderScope; -}; diff --git a/src/ByteEngine/Resources/CurvesResourceManager.hpp b/src/ByteEngine/Resources/CurvesResourceManager.hpp deleted file mode 100644 index 83ebd19d..00000000 --- a/src/ByteEngine/Resources/CurvesResourceManager.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "ByteEngine/Core.h" - -#include -#include - -class CurvesResourceManager { - struct CurveHandle { uint32 in; }; - - enum class PlayModes { - STOP, WRAP_AROUND, BOUNCE - }; - - CurveHandle CreateCurveInstance(Id name, PlayModes playMode = PlayModes::STOP, float32 timeScale = 1.f) { - auto index = instances.Emplace(); - auto& instance = instances[index]; - instance.PlayMode = playMode; instance.timeScale = timeScale; - return CurveHandle(index); - } - - float32 Evaluate(const CurveHandle curve_instance_handle, const float32 deltaTime) { - auto& instance = instances[curve_instance_handle.in]; - //const CurveInstance::TimePoint& pointsInTime = { time[GTSL::Math::Clamp(pos - 1u, 0, time)], time[GTSL::Math::Clamp(pos - 1u, 0, time)], time[GTSL::Math::Clamp(pos - 1u, 0, time)], time[pos] }; - float32 currentTime = 0; - - switch (instance.PlayMode) { - case PlayModes::STOP: - currentTime = GTSL::Math::Clamp(instance.currentTime + deltaTime, 0.0f, 1.0f); - break; - case PlayModes::WRAP_AROUND: - currentTime = GTSL::Math::Modulo(instance.currentTime + deltaTime, 1.0f); - break; - case PlayModes::BOUNCE: - instance.currentTime = GTSL::Math::Modulo(instance.currentTime + deltaTime, 1.0f * 2.0f); - currentTime -= GTSL::Math::Clamp(instance.currentTime - 1.0f, 0.0f, 1.0f); - break; - } - - uint32 pos = 0; - - { - GTSL::StaticVector stack; - while (pos < instance.TimePoints && instance.TimePoints[pos].X <= currentTime && stack.GetLength() < 4) { ++pos; stack.EmplaceBack(pos); } - //todo: clear stack when changed curve segment - } - - GTSL::StaticVector points; - const CurveInstance::TimePoint* pointsInTime[] = { &instance.TimePoints[pos - 3u], &instance.TimePoints[pos - 2u], &instance.TimePoints[pos - 1u], &instance.TimePoints[pos] }; - - for(auto e : pointsInTime) { points.EmplaceBack(e->point.y); } - - //GTSL::Math::Lerp(points[0].y, point[1].y, (currentTime - times[0]) / (times[1] - times[0])); - - return EvaulateCubicBezier(points, (currentTime - pointsInTime[0]->X) / (pointsInTime[3]->X - pointsInTime[0]->X)); - } - - static float32 EvaulateCubicBezier(const GTSL::Range points, float32 t) { - return GTSL::Math::Lerp(GTSL::Math::Lerp(GTSL::Math::Lerp(points[0], points[1], t), GTSL::Math::Lerp(points[1], points[2], t), t), GTSL::Math::Lerp(GTSL::Math::Lerp(points[1], points[2], t), GTSL::Math::Lerp(points[2], points[3], t), t), t); - } - -private: - struct CurveInstance { - struct TimePoint { - struct Point { - bool isCP = false; - float32 y = 0.0f; - } point; - - float32 X = 0.0f; - }; - GTSL::StaticVector TimePoints; - - float32 currentTime = 0.0f, timeScale; - PlayModes PlayMode; - }; - - GTSL::FixedVector instances; -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/DebugPermutation.hpp b/src/ByteEngine/Resources/DebugPermutation.hpp deleted file mode 100644 index cef5d442..00000000 --- a/src/ByteEngine/Resources/DebugPermutation.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "CommonPermutation.hpp" - -struct DebugPermutation { - -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/FontResourceManager.cpp b/src/ByteEngine/Resources/FontResourceManager.cpp deleted file mode 100644 index 513accd2..00000000 --- a/src/ByteEngine/Resources/FontResourceManager.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "FontResourceManager.h" - -#include "ByteEngine/Core.h" - -#include -#include -#include -#include - -#include "TextRendering.h" -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Debug/Assert.h" - -FontResourceManager::FontResourceManager(const InitializeInfo& info) : ResourceManager(info, u8"FontResourceManager") { - resource_files_.Start(GetResourcePath(u8"Fonts")); - - { - GTSL::FileQuery file_query(GetUserResourcePath(u8"*.ttf")); - - while(auto r = file_query()) { - auto name = r.Get(); - - RTrimLast(name, U'.'); - - if(resource_files_.Exists(Id(name))) { continue; } - - GTSL::Buffer fontFileContentsBuffer(GetTransientAllocator()); - GTSL::File file; file.Open(GetUserResourcePath(r.Get())); file.Read(fontFileContentsBuffer); - - GTSL::Font font{ GTSL::DefaultAllocatorReference() }; - GTSL::MakeFont(fontFileContentsBuffer.GetRange(), &font); //process ttf file - - GTSL::Buffer pathBuffer(512 * 512, 16, GetTransientAllocator()); - FontData font_data; - - pathBuffer << static_cast(SIZE); // Number of glyphs - - for(uint32 i = 0; i < SIZE; ++i) { - auto& glyph = font.GetGlyph(ALPHABET[i]); - - GTSL::Vector, GTSL::DefaultAllocatorReference>, GTSL::DefaultAllocatorReference> processedGlyph; - - GTSL::MakePath(glyph, &processedGlyph); //generate N point bezier curves for glyph - - pathBuffer << uint32(processedGlyph.GetLength()); // Contours - - auto& m = font_data.Characters.array[i]; - m.Advance = glyph.AdvanceWidth; - - for (auto& c : processedGlyph) { - pathBuffer << uint32(c.GetLength()); // Points - - for (auto& d : c) { - for(auto& point : d.Points) { // Normalize point coordinates - point /= glyph.Max; - } - - if(d.IsBezierCurve()) { - pathBuffer << uint8(3); - pathBuffer.Write(24, reinterpret_cast(d.Points)); - } else { - pathBuffer << uint8(2); - pathBuffer.Write(8, reinterpret_cast(&d.Points[0])); - pathBuffer.Write(8, reinterpret_cast(&d.Points[2])); - } - } - } - } - - resource_files_.AddEntry(name, &font_data, pathBuffer.GetRange()); - } - } -} \ No newline at end of file diff --git a/src/ByteEngine/Resources/FontResourceManager.h b/src/ByteEngine/Resources/FontResourceManager.h deleted file mode 100644 index fa199f3d..00000000 --- a/src/ByteEngine/Resources/FontResourceManager.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "ResourceManager.h" -#include "ByteEngine/Core.h" -#include "ByteEngine/Game/ApplicationManager.h" - -struct IVector2D -{ - IVector2D() = default; - - IVector2D(const int32 x, const int32 y) : X(x), Y(y) {} - - int32 X = 0, Y = 0; -}; - -namespace GTSL { - template - class Buffer; -} - -class FontResourceManager : public ResourceManager -{ -public: - FontResourceManager(const InitializeInfo&); - - struct Character { - GTSL::Extent2D Size; // Size of glyph - IVector2D Bearing; // Offset from baseline to left/top of glyph - GTSL::Extent2D Position; - uint32 Advance; // Offset to advance to next glyph - }; - - static constexpr char8_t ALPHABET[] = u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - static constexpr uint64 SIZE = sizeof(ALPHABET) - 1ull; - - struct FontData : SData { - DEFINE_ARRAY_MEMBER(Character, Characters, SIZE) - }; - - template - void LoadFont(const GTSL::StringView font_name, const TaskHandle, ARGS...> task_handle) { - FontData fontData; - resource_files_.LoadEntry(font_name, fontData); // TODO: handle non existant resources - GTSL::Buffer buffer(GetPersistentAllocator()); - resource_files_.LoadData(fontData, buffer); - GetApplicationManager()->EnqueueTask(task_handle, GTSL::MoveRef(fontData), MoveRef(buffer)); - } - -private: - ResourceFiles resource_files_; - //int8 parseData(const char* data, Font* fontData); -}; diff --git a/src/ByteEngine/Resources/ForwardPermutation.hpp b/src/ByteEngine/Resources/ForwardPermutation.hpp deleted file mode 100644 index 53dff757..00000000 --- a/src/ByteEngine/Resources/ForwardPermutation.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "PermutationManager.hpp" - -#include "ByteEngine/Render/Types.hpp" - -struct ForwardRenderPassPermutation : PermutationManager { - ForwardRenderPassPermutation(const GTSL::StringView instance_name) : PermutationManager(instance_name, u8"ForwardRenderPassPermutation") { - AddTag(u8"RenderTechnique", u8"Forward"); - } - - void Initialize(GPipeline* pipeline, ShaderGenerationData& shader_generation_data) override { - forwardScopeHandle = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"ForwardRenderingPermutation"); - - { - auto vertexBlock = pipeline->DeclareScope(forwardScopeHandle, u8"vertex"); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"POSITION" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"NORMAL" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"TANGENT" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"BITANGENT" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec2f", u8"TEXTURE_COORDINATES" }); - } - - pipeline->DeclareFunction(forwardScopeHandle, u8"vec4f", u8"GetVertexPosition", {}, u8"return vec4(POSITION, 1);"); - pipeline->DeclareFunction(forwardScopeHandle, u8"vec4f", u8"GetVertexNormal", {}, u8"return vec4(NORMAL, 0);"); - pipeline->DeclareFunction(forwardScopeHandle, u8"vec2f", u8"GetVertexTextureCoordinates", {}, u8"return TEXTURE_COORDINATES;"); - - forwardRenderPassScopeHandle = pipeline->DeclareStruct(forwardScopeHandle, u8"RenderPassData", FORWARD_RENDERPASS_DATA); - - { - auto fragmentOutputBlockHandle = pipeline->DeclareScope(forwardScopeHandle, u8"fragmentOutputBlock"); - - for(const auto& e : GTSL::RangeFORWARD_RENDERPASS_DATA) { - if(e.Type == u8"ImageReference") {} - } - - pipeline->DeclareVariable(fragmentOutputBlockHandle, { u8"vec4f", u8"out_Color" }); - pipeline->DeclareVariable(fragmentOutputBlockHandle, { u8"vec3f", u8"out_WorldSpacePosition" }); - pipeline->DeclareVariable(fragmentOutputBlockHandle, { u8"vec3f", u8"out_ViewSpacePosition" }); - pipeline->DeclareVariable(fragmentOutputBlockHandle, { u8"vec4f", u8"out_Normal" }); - pipeline->DeclareVariable(fragmentOutputBlockHandle, { u8"float32", u8"out_Roughness" }); - } - - const CommonPermutation* common_permutation = Find(u8"CommonPermutation", shader_generation_data.Hierarchy); - - if (common_permutation) { - auto vertexSurfaceInterface = pipeline->DeclareScope(forwardScopeHandle, u8"vertexSurfaceInterface"); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"vec2f", u8"vertexTextureCoordinates" }); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"vec3f", u8"viewSpacePosition" }); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"vec3f", u8"viewSpaceNormal" }); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"vec3f", u8"worldSpacePosition" }); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"mat3f", u8"tbn" }); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"uint32", u8"_instanceIndex" }); - } - else { - BE_LOG_ERROR(u8"Needed CommonPermutation to setup state but not found in hierarchy.") - } - } - - GPipeline::ElementHandle forwardScopeHandle, pushConstantBlockHandle, shaderParametersHandle, forwardRenderPassScopeHandle; -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/LUTResourceManager.h b/src/ByteEngine/Resources/LUTResourceManager.h deleted file mode 100644 index 9943f51b..00000000 --- a/src/ByteEngine/Resources/LUTResourceManager.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -#include "ResourceManager.h" -#include "ByteEngine/Core.h" -#include "ByteEngine/Id.h" - -class LUTResourceManager : public ResourceManager { -public: - LUTResourceManager() { - GTSL::FileQuery fileQuery(GetResourcePath(GTSL::MakeRange("*.cube"))); - - while(fileQuery) { - GTSL::File file; file.Open(fileQuery.GetFileNameWithExtension(), GTSL::File::READ); - - GTSL::Buffer buffer; buffer.Allocate(file.GetSize(), 16, GetTransientAllocator()); - - file.Read(buffer.GetBufferInterface()); - - GTSL::LUTData lutData; - //GTSL::ParseLUT(buffer, lutData); - } - } - -private: -}; diff --git a/src/ByteEngine/Resources/PermutationManager.hpp b/src/ByteEngine/Resources/PermutationManager.hpp deleted file mode 100644 index 55931fd2..00000000 --- a/src/ByteEngine/Resources/PermutationManager.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -struct PermutationManager : Object { - struct ShaderGenerationData { - GTSL::StaticVector Hierarchy; - }; - - using ShaderTag = GTSL::Pair, GTSL::ShortString<32>>; - - PermutationManager(const GTSL::StringView instance_name, const GTSL::StringView class_name) : InstanceName(instance_name), ClassName(class_name), JSON(GetPersistentAllocator()) { - - } - - static GTSL::StaticString<8192> MakeShaderString(GTSL::StringView raw_code, GTSL::StringView user_shader_code = {}) { - GTSL::StaticString<8192> shaderCode; - - auto i = raw_code.begin(); - - while(true) { - auto s = i; - - while(i != raw_code.end() && *i != u8'@') { - ++i; - } - - shaderCode += { s, i }; - - if(i == raw_code.end()) { - break; - } - - shaderCode += user_shader_code; - - ++i; - - while(IsAnyOf(*i, u8'\n', u8'\f', u8'\r')) { - ++i; - } - } - - return shaderCode; - } - - static void InitializePermutations(PermutationManager* start, GPipeline* pipeline) { - ShaderGenerationData shader_generation_data; - - auto call = [&](PermutationManager* parent, auto&& self) -> void { - parent->Initialize(pipeline, shader_generation_data); - - shader_generation_data.Hierarchy.EmplaceBack(parent); - - for (const auto& e : parent->Children) { - self(e, self); - } - - shader_generation_data.Hierarchy.PopBack(); - }; - - call(start, call); - } - - virtual void Initialize(GPipeline* pipeline, ShaderGenerationData& shader_generation_data) = 0; - - struct ShaderPermutation { - GAL::ShaderType TargetSemantics; - GTSL::StaticVector Scopes; - GTSL::StaticVector Tags; - }; - - template - PermutationManager* CreateChild(const GTSL::StringView name) { - auto permutationManager = GTSL::SmartPointer(GetPersistentAllocator(), name); - auto* permutationManagerPtr = permutationManager.GetData(); - Children.EmplaceBack(GTSL::MoveRef(permutationManager)); - return static_cast(permutationManagerPtr); - } - - GTSL::StaticVector, 8> Children; - GTSL::StaticString<64> InstanceName; - const GTSL::StaticString<64> ClassName; - - template - static const T* Find(const GTSL::StringView class_name, const GTSL::Range hierarchy) { - for (const auto e : hierarchy) { - if (e->ClassName == class_name) { //pseudo dynamic cast - return static_cast(e); - } - } - - return nullptr; - } - - GTSL::Range GetTagList() { return tags; } - - void AddSupportedDomain(const GTSL::StringView domain_name) { - if(supportedDomains.Find(domain_name)) { return; } - supportedDomains.EmplaceBack(domain_name); - } - - auto& GetSupportedDomains() const {return supportedDomains;} - - GTSL::JSON JSON; - - GTSL::StaticVector, BE::PAR>, 3> a; - - auto GetChildren() -> GTSL::StaticVector { - GTSL::StaticVector children; - for (auto& e : Children) { - children.EmplaceBack(e.GetData()); - } - return children; - } - -protected: - using SIG = GTSL::FunctionPointer&, const GTSL::JSON&, GTSL::Range hierarchy, GTSL::StaticVector& batches)>; - - void AddTag(const GTSL::StringView name, const GTSL::StringView tag_string) { tags.EmplaceBack(name, tag_string); } - -private: - GTSL::StaticVector tags; - GTSL::StaticVector, 4> supportedDomains; -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/PipelineCacheResourceManager.cpp b/src/ByteEngine/Resources/PipelineCacheResourceManager.cpp deleted file mode 100644 index af4e5091..00000000 --- a/src/ByteEngine/Resources/PipelineCacheResourceManager.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "PipelineCacheResourceManager.h" - -#include "ByteEngine/Application/Application.h" - -PipelineCacheResourceManager::PipelineCacheResourceManager(const InitializeInfo& initialize_info) : ResourceManager(initialize_info, u8"PipelineCacheResourceManager") { - - switch (cache.Open(GetResourcePath(u8"PipelineCache", u8"bepkg"), GTSL::File::READ | GTSL::File::WRITE, true)) { - default: ; - } -} - -PipelineCacheResourceManager::~PipelineCacheResourceManager() -{ -} \ No newline at end of file diff --git a/src/ByteEngine/Resources/PipelineCacheResourceManager.h b/src/ByteEngine/Resources/PipelineCacheResourceManager.h deleted file mode 100644 index e0d58cc2..00000000 --- a/src/ByteEngine/Resources/PipelineCacheResourceManager.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "ResourceManager.h" - -#include -#include - -//TODO: support multiple APIs - -class PipelineCacheResourceManager : public ResourceManager { -public: - PipelineCacheResourceManager(const InitializeInfo&); - ~PipelineCacheResourceManager(); - - void DoesCacheExist(bool& doesExist) const { doesExist = cache.GetSize(); } - void GetCacheSize(uint32& size) const { size = static_cast(cache.GetSize()); } - - template - void GetCache(GTSL::Buffer& buffer) { } - - template - void WriteCache(GTSL::Buffer& buffer) - { - cache.SetPointer(0); - cache.Write(buffer); - } -private: - GTSL::File cache; -}; diff --git a/src/ByteEngine/Resources/RayTracePermutation.hpp b/src/ByteEngine/Resources/RayTracePermutation.hpp deleted file mode 100644 index 3c7b6fd3..00000000 --- a/src/ByteEngine/Resources/RayTracePermutation.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "PermutationManager.hpp" - -struct RayTracePermutation : public PermutationManager { - RayTracePermutation(const GTSL::StringView instance_name) : PermutationManager(instance_name, u8"RayTracePermutation") { - - } - - void Initialize(GPipeline* pipeline, ShaderGenerationData& shader_generation_data) override { - auto rayTracePermutationScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"RayTracePermutation"); - - pipeline->DeclareStruct(rayTracePermutationScope, u8"TraceRayParameterData", TRACE_RAY_PARAMETER_DATA); - pipeline->DeclareFunction(rayTracePermutationScope, u8"void", u8"TraceRay", { { u8"vec3f", u8"origin" }, { u8"vec3f", u8"direction" }, { u8"uint32", u8"rayFlags" } }, u8"TraceRayParameterData* r = pushConstantBlock.rayTrace; traceRayEXT(accelerationStructureEXT(r.accelerationStructure), r.rayFlags | rayFlags, 0xff, r.recordOffset, r.recordStride, r.missIndex, vec3f(origin), r.tMin, vec3f(direction), r.tMax, 0);"); - - pipeline->DeclareFunction(rayTracePermutationScope, u8"void", u8"TraceRayFromAToB", { { u8"vec3f", u8"start" }, { u8"vec3f", u8"end" },{ u8"uint32", u8"rayFlags" } }, u8"vec3f AB = end - start; TraceRayParameterData* r = pushConstantBlock.rayTrace; traceRayEXT(accelerationStructureEXT(r.accelerationStructure), r.rayFlags | rayFlags, 0xff, r.recordOffset, r.recordStride, r.missIndex, start, r.tMin, AB, length(AB), 0);"); - - pipeline->DeclareFunction(rayTracePermutationScope, u8"void", u8"MMM", { { u8"vec3f", u8"origin" }, { u8"vec3f", u8"light_position" } }, u8"vec3f toLight = normalize(light_position - origin); vec3f perpL = cross(toLight, vec3f(0,1,0)); if(perpL == 0.0f) { perpL.x = 1.f; } vec3f toLightEdge = normalize((light_position + perpL * light_radius) - origin); float coneAngle = acos(dot(toLight, toLightEdge)) * 2;"); - - pipeline->DeclareFunction(rayTracePermutationScope, u8"vec3f", u8"GetConeSample", { { u8"vec3f", u8"direction" }, { u8"float32", u8"cone_angle" } }, u8"float32 cosAngle = cos(cone_angle); float32 z = NextRandom(randSeed) * (1-cosAngle) + cosAngle; float32 phi = NextRandom(randSeed) * 2 * PI(); float32 x = sqrt(1 - z * z) * cos(phi); float32 y = sqrt(1 - z * *) * sin(phi); vec3f north = vec3f(0, 1, 0); vec3f axis = normalize(cross(north, normalize(direction))); float32 angle = acos(dot(normalize(direction), north)); mat3f r = AngleAxis3x3(axis, angle); return r * vec3f(x, y, z);"); - - pipeline->DeclareStruct(rayTracePermutationScope, u8"RenderPassData", RT_RENDERPASS_DATA); - } -private: -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/ResourceData.h b/src/ByteEngine/Resources/ResourceData.h deleted file mode 100644 index 55eb48b4..00000000 --- a/src/ByteEngine/Resources/ResourceData.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -struct ResourceHandle -{ - uint32 IncrementReferences() { return ++references; } - uint32 DecrementReferences() { return --references; } - [[nodiscard]] uint32 GetReferenceCount() const { return references; } - -protected: - uint32 references = 0; -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/ResourceManager.cpp b/src/ByteEngine/Resources/ResourceManager.cpp deleted file mode 100644 index 300e87f0..00000000 --- a/src/ByteEngine/Resources/ResourceManager.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "ResourceManager.h" - -#include "ByteEngine/Application/Application.h" - -GTSL::StaticString<512> ResourceManager::GetUserResourcePath(const GTSL::Range fileWithExtension) { - GTSL::StaticString<512> path; - path += BE::Application::Get()->GetPathToApplication(); - path += u8"/user/"; path += fileWithExtension; - return path; -} - -GTSL::StaticString<512> ResourceManager::GetUserResourcePath(const GTSL::Range fileName, const GTSL::Range extension) { - GTSL::StaticString<512> path; - path += BE::Application::Get()->GetPathToApplication(); - path += u8"/user/"; path += fileName; path += u8'.'; path += extension; - return path; -} - -GTSL::StaticString<512> ResourceManager::GetResourcePath(const GTSL::Range fileName, const GTSL::Range extension) { - GTSL::StaticString<512> path; - path += BE::Application::Get()->GetPathToApplication(); - path += u8"/resources/"; path += fileName; path += u8'.'; path += extension; - return path; -} - -GTSL::StaticString<512> ResourceManager::GetResourcePath(const GTSL::Range fileWithExtension) { - GTSL::StaticString<512> path; - path += BE::Application::Get()->GetPathToApplication(); - path += u8"/resources/"; path += fileWithExtension; - return path; -} - -void ResourceManager::initializePackageFiles(GTSL::StaticVector& filesPerThread, GTSL::Range path) -{ - for (uint32 i = 0; i < BE::Application::Get()->GetNumberOfThreads(); ++i) { - filesPerThread.EmplaceBack(); - switch (filesPerThread.back().Open(path, GTSL::File::READ | GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: break; - case GTSL::File::OpenResult::CREATED: break; - case GTSL::File::OpenResult::ERROR: break; - } - } -} \ No newline at end of file diff --git a/src/ByteEngine/Resources/ResourceManager.h b/src/ByteEngine/Resources/ResourceManager.h deleted file mode 100644 index dd0613d8..00000000 --- a/src/ByteEngine/Resources/ResourceManager.h +++ /dev/null @@ -1,243 +0,0 @@ -#pragma once - -#include "ByteEngine/Game/System.hpp" -#include "ByteEngine/Game/Tasks.h" - -#include - -#include "GTSL/HashMap.hpp" - -/** - * \brief Used to specify a type of resource loader. - * - * This class will be instanced sometime during the application's lifetime to allow loading of some type of resource made possible by extension of this class. - * - * Every extension will allow for loading of 1 type of resource. - */ -class ResourceManager : public BE::System { -public: - ResourceManager() = default; - - ResourceManager(const InitializeInfo& info, const utf8* name) : System(info, name) {} - - static GTSL::StaticString<512> GetUserResourcePath(const GTSL::Range fileWithExtension); - static GTSL::StaticString<512> GetUserResourcePath(const GTSL::Range fileName, const GTSL::Range extension); - GTSL::StaticString<512> GetResourcePath(const GTSL::Range fileName, const GTSL::Range extension); - GTSL::StaticString<512> GetResourcePath(const GTSL::Range fileWithExtension); - - //DATA - //DATA SERIALIZE : DATA - //INFO : DATA SERIALIZE - - struct Data{}; - - template - struct DataSerialize : public I - { - /** - * \brief Byte offset to the start of the resource binary data into the package file. - */ - uint32 ByteOffset = 0; - - template - friend void Insert(const DataSerialize& textureInfoSerialize, GTSL::Buffer& buffer) - { - Insert(textureInfoSerialize.ByteOffset, buffer); - } - - template - friend void Extract(DataSerialize& textureInfoSerialize, GTSL::Buffer& buffer) - { - Extract(textureInfoSerialize.ByteOffset, buffer); - } - }; - - template - struct Info : public I - { - Info() = default; - Info(const Id name, const I& i) : I(i), Name(name) {} - Info(const I& i) : I(i) {} - - /** - * \brief Name of the resource. - */ - Id Name; - }; - -#define DECL_INFO_CONSTRUCTOR(className, inheritsFrom) className() = default; className(const Id name, const inheritsFrom& i) : inheritsFrom(name, i) {} - - #define INSERT_START(className)\ - template\ - friend void Insert(const className& insertInfo, GTSL::Buffer& buffer) - - #define INSERT_BODY Insert(insertInfo.ByteOffset, buffer); - - #define EXTRACT_START(className)\ - template\ - friend void Extract(className& extractInfo, GTSL::Buffer& buffer) - - #define EXTRACT_BODY Extract(extractInfo.ByteOffset, buffer); - - static constexpr uint8 MAX_THREADS = 32; - -protected: - void initializePackageFiles(GTSL::StaticVector& filesPerThread, GTSL::Range path); -}; - -struct EntryHeader { - uint64 DataOffset = 0, DataSize = 0; - GTSL::ShortString<96> Name; -}; - -struct SData { - EntryHeader Header; - - GTSL::StringView GetName() const { return Header.Name; } -}; - -struct ResourceFiles { - void Start(const GTSL::StringView string) { - bool a = false, b = false, c = false; - - switch (table.Open(GTSL::StaticString<512>(string) + u8".betbl", GTSL::File::READ | GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: a = true; break; - case GTSL::File::OpenResult::CREATED: a = true; break; - case GTSL::File::OpenResult::ERROR: break; - } - - switch (index.Open(GTSL::StaticString<512>(string) + u8".beidx", GTSL::File::READ | GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: b = true; break; - case GTSL::File::OpenResult::CREATED: b = true; break; - case GTSL::File::OpenResult::ERROR: break; - } - - switch (data.Open(GTSL::StaticString<512>(string) + u8".bepkg", GTSL::File::READ | GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: c = true; break; - case GTSL::File::OpenResult::CREATED: c = true; break; - case GTSL::File::OpenResult::ERROR: break; - } - - if (!(a && b && c) or !table.GetSize() or !index.GetSize() or !data.GetSize()) { - table.Resize(0); index.Resize(0); data.Resize(0); - - table.Write(5, reinterpret_cast("BETBL")); - index.Write(5, reinterpret_cast("BEIDX")); - data.Write(5, reinterpret_cast("BEPKG")); - } - else { - table.SetPointer(5); //skip name - - while (true) { - GTSL::StaticBuffer<1024> buffer(1024, 16); - auto read = table.Read(buffer, 1024); - if (!read) { break; } - for (uint32 i = 0; i < buffer.GetLength() / sizeof(TableEntry); ++i) { - TableEntry table_entry; - buffer.Read(sizeof(TableEntry), reinterpret_cast(&table_entry)); - - tableMap.Emplace(table_entry.Name, table_entry.Offset); - } - } - } - } - - template - bool AddEntry(const GTSL::StringView name, T* indexDataPointer, GTSL::Range dataPointer) { - auto hashedName = GTSL::Hash(name); - if (tableMap.Find(hashedName)) { return false; } - TableEntry table_entry; - table_entry.Name = hashedName; - table_entry.Offset = index.GetSize(); - table.Write(sizeof(TableEntry), reinterpret_cast(&table_entry)); - tableMap.Emplace(hashedName, table_entry.Offset); - - indexDataPointer->Header.DataOffset = data.GetSize(); - indexDataPointer->Header.DataSize = dataPointer.Bytes(); - indexDataPointer->Header.Name = name; - index.Write(GTSL::Math::RoundUpByPowerOf2(sizeof(T), BLOCK_SIZE), reinterpret_cast(indexDataPointer)); - - data.Write(GTSL::Math::RoundUpByPowerOf2(dataPointer.Bytes(), BLOCK_SIZE), dataPointer.begin()); - - return true; - } - - template - bool LoadEntry(const GTSL::StringView name, T& entry) { - if (!tableMap.Find(static_cast(Id(name)))) { return false; } - - auto indexDataOffset = tableMap.At(static_cast(Id(name))); - index.SetPointer(indexDataOffset); - index.Read(sizeof(T), &entry); - - return true; - } - - bool Exists(const Id name) { - return tableMap.Find(static_cast(name)); - } - - bool LoadData(auto& info, auto& buffer) { - data.SetPointer(info.Header.DataOffset); - data.Read(buffer, info.Header.DataSize); - return true; - } - - bool LoadData(auto& info, GTSL::Range buffer) { - data.SetPointer(info.Header.DataOffset); - data.Read(info.Header.DataSize, buffer.begin()); - return true; - } - - //bool LoadData(auto& info, GTSL::Range buffer) { - // data.SetPointer(info.Header.DataOffset); - // data.Read(info.Header.DataSize, buffer.begin()); - // return true; - //} - - bool LoadData(auto& info, GTSL::Range buffer, uint32 offset, uint32 size) { - data.SetPointer(info.Header.DataOffset + offset); - data.Read(size, buffer.begin()); - return true; - } - -private: - static constexpr uint64 BLOCK_SIZE = 1024u; - - struct TableEntry { - uint64 Name; uint64 Offset; - }; - - GTSL::File table, index, data; - GTSL::HashMap tableMap; -}; - -template -struct Array -{ - A& EmplaceBack(const A val = A()) { - array[Length] = val; - return array[Length++]; - } - - A& front() { return array[0]; } - A& back() { return array[Length - 1]; } - void PopBack() { --Length; } - - operator GTSL::Range() const { return GTSL::Range(Length, array); } - - operator bool() const { return Length; } - - uint32 Length = 0; - A array[SIZE]; -}; - -#define DEFINE_MEMBER(type, name) type name;\ -type Get##name() const { return name; }\ -type& Get##name() { return name; } -#define DEFINE_ARRAY_MEMBER(type, name, size) Array name;\ -Array& Get##name() { return name; }\ -const Array& Get##name() const { return name; } - -struct SubData { -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/ShaderCompilation.hpp b/src/ByteEngine/Resources/ShaderCompilation.hpp deleted file mode 100644 index 3ae13300..00000000 --- a/src/ByteEngine/Resources/ShaderCompilation.hpp +++ /dev/null @@ -1,209 +0,0 @@ -#pragma once - -#include "ByteEngine/Graph.hpp" - -enum class State : uint8 { - NONE, ADDED, MODIFIED, DELETED -}; - -struct FileChangeNotification { - State state; - uint64 FileNameHash = 0ull, FileHash = 0ull; - GTSL::String Name; - uint64 Pointer = 0ull, ParentFileNameHash = 0ull; -}; - -auto GetChangedFiles(const auto& allocator, const GTSL::File& file, const GTSL::Range paths){ - GTSL::Buffer cacheBuffer(128 * 1024, 16, allocator); - - file.Read(cacheBuffer); - - uint32 cacheEntryCount = cacheBuffer.GetLength() / 512; - byte* buffer = cacheBuffer.begin(); - - GTSL::HashMap, BE::TAR> entriesMap(64, allocator); - - GTSL::Vector files(64, allocator); - - for(uint32 i = 0; i < cacheEntryCount; ++i) { - byte* entry = buffer + 512 * i; - - auto currentNodeHash = *reinterpret_cast(entry); - auto currentNodeFileHash = *(reinterpret_cast(entry) + 1); - auto parentHash = *(reinterpret_cast(entry) + 2); - - GTSL::StaticString<256> fileName(GTSL::StringView{ reinterpret_cast(entry + 24) }); - - entriesMap.Emplace(currentNodeHash, GTSL::MoveRef(currentNodeFileHash), false, GTSL::MoveRef(parentHash), i * 512ull); - } - - for(auto path : paths) { - GTSL::FileQuery fileQuery(path); - - while (auto fileRef = fileQuery()) { - uint64 fileNameHash = GTSL::Hash(fileRef.Get()); - - if(auto res = entriesMap.TryGet(fileNameHash)) { // If file by that name exists - GTSL::Get<1>(res.Get()) = true; // File was seen in this visit - - const uint64 trackedHash = GTSL::Get<0>(res.Get()); - - if(trackedHash != fileQuery.GetFileHash()) { // If file has new hash, then it is has been modified - files.EmplaceBack(State::MODIFIED, fileNameHash, fileQuery.GetFileHash(), GTSL::String{ fileRef.Get(), allocator }, GTSL::Get<3>(res.Get()), GTSL::Get<2>(res.Get())); - } - } else { // File was not being tracked, then is new - files.EmplaceBack(State::ADDED, fileNameHash, fileQuery.GetFileHash(), GTSL::String{ fileRef.Get(), allocator }); - - entriesMap.Emplace(fileNameHash, fileQuery.GetFileHash(), true, 0ull, 0ull); - } - } - } - - if(true) { // If we visited less items than those that we were tracking then something was deleted - for(auto& e : entriesMap) { - if(!GTSL::Get<1>(e)) { // If file was not seen in this iteration then it must have been deleted (or renamed which we can't easily identify) - files.EmplaceBack(State::DELETED, 0ull, GTSL::Get<0>(e), GTSL::String{ u8"", allocator }, GTSL::Get<3>(e), GTSL::Get<2>(e)); - } - } - } - - return files; -} - -auto GetTree(const auto& allocator, GTSL::File& file){ - file.SetPointer(0); - - GTSL::Buffer cacheBuffer(128 * 1024, 16, allocator); - - file.Read(cacheBuffer); - - uint32 cacheEntryCount = cacheBuffer.GetLength() / 512; - byte* buffer = cacheBuffer.begin(); - - GTSL::HashMap, BE::TAR> tree(64, allocator); - - GTSL::Vector, BE::TAR> pendingInserts(128, allocator); - - for(uint32 i = 0; i < cacheEntryCount; ++i) { - byte* entry = buffer + 512 * i; - - auto currentNodeHash = *reinterpret_cast(entry); - auto currentNodeFileHash = *(reinterpret_cast(entry) + 1); - auto parentHash = *(reinterpret_cast(entry) + 2); - - auto& currentNode = tree.Emplace(currentNodeHash, FileChangeNotification{ State::NONE, currentNodeHash, currentNodeFileHash, { GTSL::StringView{ reinterpret_cast(entry + 24) }, allocator }, i * 512, parentHash }); - - if(!parentHash) { continue; } - - pendingInserts.EmplaceBack(currentNodeHash, parentHash); - } - - while(pendingInserts) { - auto& last = pendingInserts.back(); - if(tree.Find(last.Second)) { // Node could not exist if it was not inserted by client - tree[last.Second].Connect(tree[last.First]); // Connect parent to children - } - pendingInserts.PopBack(); - } - - return tree; -} - -inline uint64 CommitFileChangeToCache(GTSL::File& file, GTSL::StringView file_name, uint64 fileHash, uint64 parent_file_name_hash) { - uint64 pointer = file.GetSize(); - file << GTSL::Hash(file_name).value; // Add file name hash - file << fileHash; // Add file hash - file << parent_file_name_hash; - file.Write(file_name.GetBytes(), reinterpret_cast(file_name.GetData())); - byte pad = 0; - for(uint32 i = 0; i < (512 - 8 - 8 - 8) - file_name.GetBytes(); ++i) { file << pad; } - return pointer; -} - -inline void UpdateFileHashCache(uint64 po, GTSL::File& file, uint64 file_hash) { - file.SetPointer(po + 8); - file << file_hash; -} - -inline void UpdateParentFileNameCache(uint64 po, GTSL::File& file, uint64 parent_file_name_hash) { - file.SetPointer(po + 8 * 2); - file << parent_file_name_hash; -} - -template -auto operator<<(A& buffer, const GTSL::StringView string_view) -> A& { - buffer << string_view.GetBytes() << string_view.GetCodepoints(); - buffer.Write(string_view.GetBytes(), reinterpret_cast(string_view.GetData())); - return buffer; -} - -template -auto operator>>(auto& buffer, GTSL::String& vector) -> decltype(buffer)& { - uint32 length, codepoints; - buffer >> length >> codepoints; - for (uint32 i = 0; i < length; ++i) { - char8_t c; - buffer >> c; - vector += c; - } - return buffer; -} - -inline uint64 WriteIndexEntry(GTSL::File& file, uint64 pointer, uint64 data_pointer, GTSL::StringView string_view) { - uint64 p = 0; - if(pointer != ~0ULL) { file.SetPointer(pointer); p = pointer; } else { p = file.GetSize(); } - file << data_pointer; - file << string_view; - byte pad = 0; - for(uint32 i = 0; i < (128 - 8 - 4 - 4 - string_view.GetBytes()); ++i) { file << pad; } - BE_ASSERT(p % 128 == 0, u8"uh oh"); - return p; -} - -inline uint64 ReadIndexEntry(GTSL::File& file, uint64 pointer, auto&& f) { - file.SetPointer(pointer); - - GTSL::StaticBuffer<256> buffer; - auto readBytes = file.Read(buffer, 128); - - uint64 offset = 0; // Points to the data - buffer >> offset; - - GTSL::StaticString<120> string; - buffer >> string; - - f(offset, GTSL::StringView(string)); - - return pointer + readBytes; -} - -inline void UpdateIndexEntry(GTSL::File& file, uint64 pointer, uint64 new_pointer) { - file.SetPointer(pointer); - - file << new_pointer; -} - -inline GAL::ShaderType ShaderTypeFromString(GTSL::StringView string) { - switch (GTSL::Hash(string)) { - case GTSL::Hash(u8"VERTEX"): return GAL::ShaderType::VERTEX; - case GTSL::Hash(u8"FRAGMENT"): return GAL::ShaderType::FRAGMENT; - case GTSL::Hash(u8"COMPUTE"): return GAL::ShaderType::COMPUTE; - case GTSL::Hash(u8"RAY_GEN"): return GAL::ShaderType::RAY_GEN; - case GTSL::Hash(u8"CLOSEST_HIT"): return GAL::ShaderType::CLOSEST_HIT; - case GTSL::Hash(u8"ANY_HIT"): return GAL::ShaderType::ANY_HIT; - case GTSL::Hash(u8"MISS"): return GAL::ShaderType::MISS; - } -} - -#include "ByteEngine/Render/ShaderGenerator.h" - -inline Class ShaderClassFromString(GTSL::StringView string) { - switch (GTSL::Hash(string)) { - case GTSL::Hash(u8"VERTEX"): return Class::VERTEX; - case GTSL::Hash(u8"SURFACE"): return Class::SURFACE; - case GTSL::Hash(u8"COMPUTE"): return Class::COMPUTE; - case GTSL::Hash(u8"RAY_GEN"): return Class::RAY_GEN; - case GTSL::Hash(u8"CLOSEST_HIT"): return Class::CLOSEST_HIT; - case GTSL::Hash(u8"MISS"): return Class::MISS; - } -} \ No newline at end of file diff --git a/src/ByteEngine/Resources/ShaderResourceManager.h b/src/ByteEngine/Resources/ShaderResourceManager.h deleted file mode 100644 index 5dd93e52..00000000 --- a/src/ByteEngine/Resources/ShaderResourceManager.h +++ /dev/null @@ -1,1417 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ResourceManager.h" -#include "ShaderCompilation.hpp" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Render/ShaderGenerator.h" -#include "ByteEngine/Graph.hpp" - -#include "PermutationManager.hpp" -#include "CommonPermutation.hpp" -#include "ForwardPermutation.hpp" -#include "UIPermutation.hpp" -#include "RayTracePermutation.hpp" -#include "GTSL/JSON.hpp" -#include "GTSL/Mutex.h" - -template -auto operator<<(auto& buffer, const GTSL::Vector& vector) -> decltype(buffer)& { - buffer << vector.GetLength(); - for (uint32 i = 0; i < vector.GetLength(); ++i) { buffer << vector[i]; } - return buffer; -} - -template -auto operator>>(auto& buffer, GTSL::Vector& vector) -> decltype(buffer)& { - uint32 length; - buffer >> length; - for (uint32 i = 0; i < length; ++i) { buffer >> vector.EmplaceBack(); } - return buffer; -} - -template -auto Read(auto& buffer, GTSL::Vector& vector, const BE::PAR& allocator) -> decltype(buffer)& { - uint32 length; - buffer >> length; - for (uint32 i = 0; i < length; ++i) { Extract(vector.EmplaceBack(), buffer); } - return buffer; -} - -template -auto operator>>(auto& buffer, GTSL::ShortString& string) -> decltype(buffer)& { - uint32 length, codepoints; - buffer >> length; buffer >> codepoints; - for (uint32 i = 0; i < length; ++i) { buffer >> const_cast(string.begin())[i]; } - return buffer; -} - -template -A& operator<<(A& buffer, GTSL::Enum auto enu) { - buffer << static_cast>(enu); - return buffer; -} - -template -A& operator>>(A& buffer, T& enu) { - buffer >> reinterpret_cast&>(enu); - return buffer; -} - -static unsigned long long quickhash64(const GTSL::Range range) { // set 'mix' to some value other than zero if you want a tagged hash - const unsigned long long mulp = 2654435789; - unsigned long long mix = 0; - - mix ^= 104395301; - - for (auto e : range) - mix += (e * mulp) ^ (mix >> 23); - - return mix ^ (mix << 37); -} - -struct PermutationManager; - -class ShaderResourceManager final : public ResourceManager -{ - static GTSL::ShortString<12> ShaderTypeToFileExtension(GAL::ShaderType type) { - switch (type) { - case GAL::ShaderType::VERTEX: return u8"vert"; - case GAL::ShaderType::TESSELLATION_CONTROL: return u8"tesc"; - case GAL::ShaderType::TESSELLATION_EVALUATION: return u8"tese"; - case GAL::ShaderType::GEOMETRY: return u8"geom"; - case GAL::ShaderType::FRAGMENT: return u8"frag"; - case GAL::ShaderType::COMPUTE: return u8"comp"; - case GAL::ShaderType::RAY_GEN: return u8"rgen"; - case GAL::ShaderType::ANY_HIT: return u8"rahit"; - case GAL::ShaderType::CLOSEST_HIT: return u8"rchit"; - case GAL::ShaderType::MISS: return u8"rmiss"; - case GAL::ShaderType::INTERSECTION: return u8"rint"; - case GAL::ShaderType::CALLABLE: return u8"rcall"; - } - } - -public: - static StructElement readStructElement(GTSL::JSON json) { - return { json[u8"type"], json[u8"name"], json[u8"defaultValue"] }; - } - - using ShaderHash = uint64; - - ShaderResourceManager(const InitializeInfo& initialize_info); - - ~ShaderResourceManager() = default; - - struct Parameter { - GTSL::StaticString<32> Type, Name, Value; - - Parameter() = default; - Parameter(const GTSL::StringView type, const GTSL::StringView name, const GTSL::StringView val) : Type(type), Name(name), Value(val) {} - - template - friend void Insert(const Parameter& parameterInfo, GTSL::Buffer& buffer) { - Insert(parameterInfo.Type, buffer); - Insert(parameterInfo.Name, buffer); - Insert(parameterInfo.Value, buffer); - } - - template - friend void Extract(Parameter& parameterInfo, GTSL::Buffer& buffer) { - Extract(parameterInfo.Type, buffer); - Extract(parameterInfo.Name, buffer); - Extract(parameterInfo.Value, buffer); - } - }; - - struct ShaderGroupInstance { - ShaderGroupInstance() = default; - - GTSL::ShortString<32> Name; - GTSL::StaticVector, GTSL::StaticString<32>>, 16> Parameters; - - ShaderGroupInstance& operator=(const ShaderGroupInstance& shader_group_instance) { - Name = shader_group_instance.Name; Parameters = shader_group_instance.Parameters; - return *this; - } - - template - friend void Insert(const ShaderGroupInstance& materialInstance, GTSL::Buffer& buffer) { - Insert(materialInstance.Name, buffer); - Insert(materialInstance.Parameters, buffer); - } - - template - friend void Extract(ShaderGroupInstance& materialInstance, GTSL::Buffer& buffer) { - Extract(materialInstance.Name, buffer); - Extract(materialInstance.Parameters, buffer); - } - - }; - - struct VertexShader {}; - - struct FragmentShader { - GAL::BlendOperation WriteOperation; - - template - friend void Insert(const FragmentShader& fragment_shader, GTSL::Buffer& buffer) { - Insert(fragment_shader.WriteOperation, buffer); - } - - template - friend void Extract(FragmentShader& fragment_shader, GTSL::Buffer& buffer) { - Extract(fragment_shader.WriteOperation, buffer); - } - }; - - struct TaskShader {}; - - struct MeshShader {}; - - struct ComputeShader {}; - - struct RayGenShader { uint8 Recursion = 1; }; - - struct ClosestHitShader {}; - - struct MissShader {}; - - struct AnyHitShader {}; - - struct IntersectionShader {}; - - struct CallableShader {}; - - struct ShaderInfo { - GTSL::ShortString<64> Name; - GAL::ShaderType Type; uint64 Hash = 0; - GTSL::StaticVector Parameters; - GTSL::StaticVector Tags; - GTSL::StaticString<4096> DebugData; - - uint64 Size = 0; - - union { - VertexShader vertexShader; - FragmentShader fragmentShader; - ComputeShader computeShader; - TaskShader taskShader; - MeshShader meshShader; - RayGenShader rayGenShader; - ClosestHitShader closestHitShader; - MissShader missShader; - AnyHitShader anyHitShader; - IntersectionShader intersectionShader; - CallableShader callableShader; - }; - - //ShaderInfo(const BE::PAR& allocator) : DebugData(allocator) {} - ShaderInfo(const BE::PAR& allocator) {} - - void SetType(GAL::ShaderType type) { - Type = type; - - switch (Type) { - case GAL::ShaderType::VERTEX: ::new(&vertexShader) VertexShader(); break; - case GAL::ShaderType::TESSELLATION_CONTROL: break; - case GAL::ShaderType::TESSELLATION_EVALUATION: break; - case GAL::ShaderType::GEOMETRY: break; - case GAL::ShaderType::FRAGMENT: break; - case GAL::ShaderType::COMPUTE: ::new(&computeShader) ComputeShader(); break; - case GAL::ShaderType::TASK: break; - case GAL::ShaderType::MESH: break; - case GAL::ShaderType::RAY_GEN: ::new(&rayGenShader) RayGenShader(); break; - case GAL::ShaderType::ANY_HIT: break; - case GAL::ShaderType::CLOSEST_HIT: break; - case GAL::ShaderType::MISS: break; - case GAL::ShaderType::INTERSECTION: break; - case GAL::ShaderType::CALLABLE: break; - } - } - - ShaderInfo(const ShaderInfo& shader_info) : Name(shader_info.Name), Type(shader_info.Type), Hash(shader_info.Hash), Parameters(shader_info.Parameters), Tags(shader_info.Tags), DebugData(shader_info.DebugData), Size(shader_info.Size) { - switch (Type) { - case GAL::ShaderType::VERTEX: ::new(&vertexShader) VertexShader(shader_info.vertexShader); break; - case GAL::ShaderType::TESSELLATION_CONTROL: break; - case GAL::ShaderType::TESSELLATION_EVALUATION: break; - case GAL::ShaderType::GEOMETRY: break; - case GAL::ShaderType::FRAGMENT: ::new(&fragmentShader) FragmentShader(shader_info.fragmentShader); break; - case GAL::ShaderType::COMPUTE: ::new(&computeShader) ComputeShader(shader_info.computeShader); break; - case GAL::ShaderType::TASK: break; - case GAL::ShaderType::MESH: break; - case GAL::ShaderType::RAY_GEN: ::new(&rayGenShader) RayGenShader(shader_info.rayGenShader); break; - case GAL::ShaderType::ANY_HIT: break; - case GAL::ShaderType::CLOSEST_HIT: break; - case GAL::ShaderType::MISS: break; - case GAL::ShaderType::INTERSECTION: break; - case GAL::ShaderType::CALLABLE: break; - } - } - - ~ShaderInfo() { - switch (Type) { - case GAL::ShaderType::VERTEX: GTSL::Destroy(vertexShader); break; - case GAL::ShaderType::TESSELLATION_CONTROL: break; - case GAL::ShaderType::TESSELLATION_EVALUATION: break; - case GAL::ShaderType::GEOMETRY: break; - case GAL::ShaderType::FRAGMENT: GTSL::Destroy(fragmentShader); break; - case GAL::ShaderType::COMPUTE: GTSL::Destroy(computeShader); break; - case GAL::ShaderType::TASK: GTSL::Destroy(taskShader); break; - case GAL::ShaderType::MESH: GTSL::Destroy(meshShader); break; - case GAL::ShaderType::RAY_GEN: GTSL::Destroy(rayGenShader); break; - case GAL::ShaderType::ANY_HIT: GTSL::Destroy(anyHitShader); break; - case GAL::ShaderType::CLOSEST_HIT: GTSL::Destroy(closestHitShader); break; - case GAL::ShaderType::MISS: GTSL::Destroy(missShader); break; - case GAL::ShaderType::INTERSECTION: GTSL::Destroy(intersectionShader); break; - case GAL::ShaderType::CALLABLE: GTSL::Destroy(callableShader); break; - } - } - - ShaderInfo& operator=(const ShaderInfo& other) { - Size = other.Size; - Name = other.Name; - Type = other.Type; - Hash = other.Hash; - Parameters = other.Parameters; - Tags = other.Tags; - DebugData = other.DebugData; - - switch (Type) { - case GAL::ShaderType::VERTEX: vertexShader = other.vertexShader; break; - case GAL::ShaderType::TESSELLATION_CONTROL: break; - case GAL::ShaderType::TESSELLATION_EVALUATION: break; - case GAL::ShaderType::GEOMETRY: break; - case GAL::ShaderType::FRAGMENT: fragmentShader = other.fragmentShader; break; - case GAL::ShaderType::COMPUTE: computeShader = other.computeShader; break; - case GAL::ShaderType::TASK: break; - case GAL::ShaderType::MESH: break; - case GAL::ShaderType::RAY_GEN: rayGenShader = other.rayGenShader; break; - case GAL::ShaderType::ANY_HIT: break; - case GAL::ShaderType::CLOSEST_HIT: break; - case GAL::ShaderType::MISS: break; - case GAL::ShaderType::INTERSECTION: break; - case GAL::ShaderType::CALLABLE: break; - } - - return *this; - } - - template - friend void Insert(const ShaderInfo& shader, GTSL::Buffer& buffer) { - Insert(shader.Name, buffer); - Insert(shader.Type, buffer); - Insert(shader.Size, buffer); - Insert(shader.Parameters, buffer); - Insert(shader.Tags, buffer); - Insert(shader.DebugData, buffer); - - switch (shader.Type) { - case GAL::ShaderType::VERTEX: Insert(shader.vertexShader, buffer); break; - case GAL::ShaderType::FRAGMENT: Insert(shader.fragmentShader, buffer); break; - case GAL::ShaderType::COMPUTE: Insert(shader.computeShader, buffer); break; - } - } - - template - friend void Extract(ShaderInfo& shader, GTSL::Buffer& buffer) { - Extract(shader.Name, buffer); - Extract(shader.Type, buffer); - Extract(shader.Size, buffer); - Extract(shader.Parameters, buffer); - Extract(shader.Tags, buffer); - Extract(shader.DebugData, buffer); - - switch (shader.Type) { - case GAL::ShaderType::VERTEX: Extract(shader.vertexShader, buffer); break; - case GAL::ShaderType::FRAGMENT: Extract(shader.fragmentShader, buffer); break; - case GAL::ShaderType::COMPUTE: Extract(shader.computeShader, buffer); break; - } - } - }; - - struct ShaderGroupData : Data { - ShaderGroupData(const BE::PAR& allocator) : Parameters(allocator), Instances(allocator), Shaders(allocator), Tags(allocator) {} - - GTSL::ShortString<32> Name; - - GTSL::Vector Parameters; - GTSL::Vector Instances; - GTSL::Vector Shaders; - GTSL::Vector Tags; - GTSL::StaticVector, 8> VertexElements; - }; - - struct ShaderGroupInfo { - ShaderGroupInfo(const BE::PAR& allocator) : Shaders(allocator), Instances(allocator), Parameters(allocator), Tags(allocator) {} - - ShaderGroupInfo(ShaderGroupInfo&&) = default; - - GTSL::ShortString<32> Name; - - GTSL::Vector Shaders; - GTSL::Vector Instances; - GTSL::Vector Parameters; - GTSL::Vector Tags; - GTSL::StaticVector, 8> VertexElements; - - struct RayTraceData { - StructElement Payload; - - struct Group { - GTSL::StaticVector ShadersPerGroup; - } Groups[4]; - } RayTrace; - }; - - struct ShaderGroupDataSerialize : ShaderGroupData, Object { - ShaderGroupDataSerialize(const BE::PAR& allocator) : ShaderGroupData(allocator) {} - ShaderGroupDataSerialize(const ShaderGroupDataSerialize& other) = delete; - ShaderGroupDataSerialize(ShaderGroupDataSerialize&&) = default; - bool RayTrace; - ShaderGroupInfo::RayTraceData RayTraceData; - GTSL::StaticVector, 8>, 8> SSS; - GTSL::StaticVector, 8> ShaderJSONs; - }; - - template - void LoadShaderGroupInfo(ApplicationManager* gameInstance, Id shaderGroupName, TaskHandle dynamicTaskHandle, ARGS&&... args) { - gameInstance->EnqueueTask(gameInstance->RegisterTask(this, u8"loadShaderInfosFromDisk", {}, &ShaderResourceManager::loadShaderGroup), GTSL::MoveRef(shaderGroupName), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - - template - void LoadShaderGroup(ApplicationManager* gameInstance, ShaderGroupInfo shader_group_info, TaskHandle, ARGS...> dynamicTaskHandle, GTSL::Range buffer, ARGS&&... args) { - gameInstance->EnqueueTask(gameInstance->RegisterTask(this, u8"loadShadersFromDisk", {}, &ShaderResourceManager::loadShaders), GTSL::MoveRef(shader_group_info), GTSL::MoveRef(buffer), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - -private: - GTSL::File shaderGroupInfosFile, shaderInfosFile, shaderPackageFile, changeCache; - GTSL::HashMap shaderGroupInfoOffsets; - GTSL::HashMap shaderInfoOffsets, shaderOffsets, shaderInfoPointers, shadersPointer; - - mutable GTSL::ReadWriteMutex mutex; - - GAL::ShaderCompiler compiler_; - - using ShaderMap = GTSL::HashMap, GTSL::String>, BE::TAR>; - - void processShaderGroup(const GTSL::JSON& json, GPipeline& pipeline, PermutationManager* root_permutation, ShaderGroupDataSerialize*, const ShaderMap& shader_map); - void makeShaderGroup(const GTSL::JSON& json, GPipeline& pipeline, PermutationManager* root_permutation, ShaderGroupDataSerialize*, const ShaderMap& shader_map); - - void serializeShaderGroup(const PermutationManager* permutation_manager, const ShaderGroupDataSerialize& shader_group_data_serialize); - - GTSL::Buffer compileShader(const GTSL::JSON& json, - const GPipeline& pipeline, - const GTSL::Range - scopes); - void serializeShader(const GTSL::JSON& json, GTSL::Range shader_binary_buffer); - - template - void loadShaderGroup(TaskInfo taskInfo, Id shaderGroupName, TaskHandle dynamicTaskHandle, ARGS... args) { //TODO: check why can't use ARGS&& - if(!shaderGroupInfoOffsets.Find(shaderGroupName)) { BE_LOG_WARNING(u8"Shader group: ", GTSL::StringView(shaderGroupName), u8", does not exist."); return; } - - shaderGroupInfosFile.SetPointer(shaderGroupInfoOffsets[shaderGroupName]); - - ShaderGroupInfo shaderGroupInfo(GetPersistentAllocator()); - - shaderGroupInfosFile >> shaderGroupInfo.Name; - - uint32 shaderCount; - shaderGroupInfosFile >> shaderCount; - - for (uint32 s = 0; s < shaderCount; ++s) { - uint64 shaderHash; - shaderGroupInfosFile >> shaderHash; - - auto& shader = shaderGroupInfo.Shaders.EmplaceBack(GetPersistentAllocator()); - - { - shaderInfosFile.SetPointer(shaderInfoOffsets[shaderHash]); - - GTSL::String jsonString(GetTransientAllocator()); - - shaderInfosFile >> jsonString; - - auto shaderJSON = GTSL::JSON(jsonString, GetTransientAllocator()); - - shader.Name = shaderJSON[u8"name"]; - shader.Size = uint64(shaderJSON[u8"binarySize"]); - shader.Hash = uint64(shaderJSON[u8"binaryHash"]); - - // TODO: params - - shader.SetType(ShaderTypeFromString(shaderJSON[u8"targetSemantics"])); - - for(auto tag : shaderJSON[u8"tags"]) { - shader.Tags.EmplaceBack(GTSL::StringView(tag[u8"name"]), GTSL::StringView(tag[u8"value"])); - } - - //shaderInfosFile >> shader.DebugData; - } - } - - { - uint32 parameterCount; - shaderGroupInfosFile >> parameterCount; - - for (uint32 p = 0; p < parameterCount; ++p) { - auto& parameter = shaderGroupInfo.Parameters.EmplaceBack(); - shaderGroupInfosFile >> parameter.Type >> parameter.Name >> parameter.Value; - } - } - - { - uint32 tagCount; - shaderGroupInfosFile >> tagCount; - - for (uint32 p = 0; p < tagCount; ++p) { - auto& tag = shaderGroupInfo.Tags.EmplaceBack(); - shaderGroupInfosFile >> tag.First >> tag.Second; - } - } - - uint32 instanceCount; - shaderGroupInfosFile >> instanceCount; - - for (uint32 i = 0; i < instanceCount; ++i) { - auto& instance = shaderGroupInfo.Instances.EmplaceBack(); - shaderGroupInfosFile >> instance.Name; - - uint32 params = 0; - shaderGroupInfosFile >> params; - - for (uint32 p = 0; p < params; ++p) { - auto& param = instance.Parameters.EmplaceBack(); - shaderGroupInfosFile >> param.First >> param.Second; - } - } - - uint32 vertexStreamCount = 0; - shaderGroupInfosFile >> vertexStreamCount; - - for (uint32 a = 0; a < vertexStreamCount; ++a) { - auto& stream = shaderGroupInfo.VertexElements.EmplaceBack(); - - uint32 vertexElements = 0; - shaderGroupInfosFile >> vertexElements; - - for (uint32 a = 0; a < vertexElements; ++a) { - auto& e = stream.EmplaceBack(); - shaderGroupInfosFile >> e.Type >> e.Name; - } - } - - bool rayTrace = false; shaderGroupInfosFile >> rayTrace; - - if (rayTrace) { - shaderGroupInfosFile >> shaderGroupInfo.RayTrace.Payload.Type >> shaderGroupInfo.RayTrace.Payload.Name >> shaderGroupInfo.RayTrace.Payload.DefaultValue; - - for (uint32 i = 0; i < 4; ++i) { - uint32 groupCount; shaderGroupInfosFile >> groupCount; - - for (uint32 j = 0; j < groupCount; ++j) { - shaderGroupInfosFile >> shaderGroupInfo.RayTrace.Groups[i].ShadersPerGroup.EmplaceBack(); - } - } - } - - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(shaderGroupInfo), GTSL::ForwardRef(args)...); - }; - - template - void loadShaders(TaskInfo taskInfo, ShaderGroupInfo shader_group_info, GTSL::Range buffer, TaskHandle, ARGS...> dynamicTaskHandle, ARGS... args) { - uint32 offset = 0; - - for (const auto& s : shader_group_info.Shaders) { - shaderPackageFile.SetPointer(shaderOffsets[GTSL::Hash(s.Name)]); - shaderPackageFile.Read(s.Size, buffer.begin() + offset); - offset += s.Size; - } - - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(shader_group_info), GTSL::MoveRef(buffer), GTSL::ForwardRef(args)...); - } - - using Result = GTSL::StaticVector; - - GTSL::File shaderGroupsTableFile, shaderInfoTableFile, shadersTableFile; -}; - -struct VertexPermutationManager { - VertexPermutationManager(GPipeline* pipeline) { - for(uint32 i = 0; i < vertexPermutations; ++i) { - - GTSL::StaticVector structElements; - - for(uint32 j = 0; j < vertexPermutations[i]; ++j) { - } - - //vertexPermutationHandles.EmplaceBack(pipeline->DeclareStruct({}, u8"vertex", structElements)); - } - } - - GTSL::StaticVector, 8>, 8> vertexPermutations; - GTSL::StaticVector vertexPermutationHandles; -}; - -inline ShaderResourceManager::ShaderResourceManager(const InitializeInfo& initialize_info) : ResourceManager(initialize_info, u8"ShaderResourceManager"), shaderGroupInfoOffsets(8, GetPersistentAllocator()), shaderInfoOffsets(8, GetPersistentAllocator()), shaderOffsets(8, GetPersistentAllocator()), shaderInfoPointers(8, GetPersistentAllocator()), shadersPointer(8, GetPersistentAllocator()) { - auto a0 = shaderPackageFile.Open(GetResourcePath(u8"Shaders", u8"bepkg"), GTSL::File::READ | GTSL::File::WRITE, true); - - auto a1 = shaderGroupsTableFile.Open(GetResourcePath(u8"ShaderGroups.betbl"), GTSL::File::READ | GTSL::File::WRITE, true); - auto a2 = shaderInfoTableFile.Open(GetResourcePath(u8"ShaderInfo.betbl"), GTSL::File::READ | GTSL::File::WRITE, true); - auto a3 = shadersTableFile.Open(GetResourcePath(u8"Shaders.betbl"), GTSL::File::READ | GTSL::File::WRITE, true); - - switch (shaderInfosFile.Open(GetResourcePath(u8"Shaders", u8"beidx"), GTSL::File::READ | GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: break; - case GTSL::File::OpenResult::CREATED: break; - case GTSL::File::OpenResult::ERROR: break; - } - - switch (shaderGroupInfosFile.Open(GetResourcePath(u8"ShaderGroups", u8"beidx"), GTSL::File::READ | GTSL::File::WRITE, true)) { - case GTSL::File::OpenResult::OK: break; - case GTSL::File::OpenResult::CREATED: break; - case GTSL::File::OpenResult::ERROR: break; - } - - GTSL::HashMap permutationsMap(8, GetPersistentAllocator()); - - GTSL::SmartPointer commonPermutation(GetTransientAllocator(), u8"CommonPermutation"); - - permutationsMap.Emplace(u8"CommonPermutation", static_cast(commonPermutation.GetData())); - - - { //configure permutations - permutationsMap.Emplace(u8"ForwardRenderingPermutation", commonPermutation->CreateChild(u8"ForwardRenderingPermutation")); - permutationsMap.Emplace(u8"RayTracePermutation", commonPermutation->CreateChild(u8"RayTracePermutation")); - permutationsMap.Emplace(u8"UIPermutation", commonPermutation->CreateChild(u8"UIPermutation")); - } - - GPipeline pipeline; - - PermutationManager::InitializePermutations(commonPermutation, &pipeline); - - auto a4 = changeCache.Open(GetResourcePath(u8"ShaderResourceManagerCache.bin"), GTSL::File::READ | GTSL::File::WRITE, true); - - auto changedFiles = GetChangedFiles(GetTransientAllocator(), changeCache, { GetUserResourcePath(u8"*.bespg.json"), GetUserResourcePath(u8"*.besh.json"), GetUserResourcePath(u8"*.besg.json"), GetUserResourcePath(u8"*.besh.txt") }); - - if (!(shaderPackageFile.GetSize() && shaderGroupsTableFile.GetSize() && shaderInfoTableFile.GetSize() && shadersTableFile.GetSize() && shaderInfosFile.GetSize() && shaderGroupInfosFile.GetSize() && changeCache.GetSize())) { - shaderPackageFile.Resize(0); - shaderGroupsTableFile.Resize(0); - shaderInfoTableFile.Resize(0); - shadersTableFile.Resize(0); - shaderInfosFile.Resize(0); - shaderGroupInfosFile.Resize(0); - } - - ShaderMap shaderMap(32, GetTransientAllocator()); - GTSL::HashMap shaderGroupMap(32, GetTransientAllocator()); - GTSL::HashMap, BE::TAR> shaderGroupJSONsMap(32, GetTransientAllocator()); - - auto fileTree = GetTree(GetTransientAllocator(), changeCache); - - struct IFile { - GTSL::StaticString<128> Name; - uint64 FileHash = 0; - uint64 Pointer = 0ull; - State state; - }; - - GTSL::HashMap, BE::TAR> dependencyTree(128, GetTransientAllocator()); - - for(auto& e : fileTree) { // Add files from the cache to the map - dependencyTree.Emplace(e.GetData().FileNameHash, IFile{ GTSL::StringView(e.GetData().Name), e.GetData().FileHash, e.GetData().Pointer, e.GetData().state }); - } - - // Add new files to the map and update properties for files added from the cache. - for (auto& e : changedFiles) { - switch (e.state) { - case State::ADDED: BE_LOG_MESSAGE(u8"Created ", e.Name); dependencyTree.Emplace(GTSL::Hash(e.Name), IFile{ GTSL::StaticString<128>(e.Name), e.FileHash, 0ull, e.state }); break; - case State::MODIFIED: BE_LOG_MESSAGE(u8"Modified ", e.Name); - dependencyTree[GTSL::Hash(e.Name)].GetData().FileHash = e.FileHash; - dependencyTree[GTSL::Hash(e.Name)].GetData().state = e.state; - break; - case State::DELETED: BE_LOG_MESSAGE(u8"Deleted ", e.Name); break; - } - } - - // Reads all files and populates all needed structures to compile shaders - auto populateTree = [&](Graph& node, State state) -> void { - auto& fileData = node.GetData(); - - if(state == State::ADDED) { // Only add file to cache if it's the first time we see it. - fileData.Pointer = CommitFileChangeToCache(changeCache, fileData.Name, fileData.FileHash, 0ull); - } - - if(GTSL::IsIn(fileData.Name, u8"bespg")) { - GTSL::File file(GetUserResourcePath(fileData.Name)); - - GTSL::StaticBuffer<2048> fileBuffer(file); - - auto json = GTSL::JSON(GTSL::StringView(fileBuffer), GetPersistentAllocator()); - - auto permutation = permutationsMap[GTSL::StringView(json[u8"name"])]; - - auto permutationScopeHandle = pipeline.TryDeclareScope(GPipeline::GLOBAL_SCOPE, GTSL::StringView(json[u8"name"])); - - if(auto inherits = json[u8"inherits"]) { - for(auto de : inherits) { // Connect parent permutation guides to their children - auto& parentDependency = dependencyTree[GTSL::Hash(GTSL::StaticString<128>(de) + u8".bespg.json")]; - parentDependency.Connect(node); - } - } - - if(auto dataLayers = json[u8"dataLayers"]) { - auto pcd = pipeline.DeclareScope(permutationScopeHandle, u8"pushConstantBlock"); - - for(auto dataLayer : dataLayers) { - pipeline.DeclareVariable(pcd, { dataLayer[u8"type"], dataLayer[u8"name"] }); - } - } - - for(auto option : json[u8"options"]) { - auto& a = permutation->a.EmplaceBack(GetPersistentAllocator()); - - permutation->AddSupportedDomain(option[u8"domain"]); - - for(auto subset : option[u8"subsets"]) { - GTSL::StaticString<128> subsetPath; - subsetPath += GTSL::Join { { GTSL::StringView(json[u8"name"]), GTSL::StringView(option[u8"name"]), GTSL::StringView(subset[u8"name"]) }, u8"." }; - GTSL::File guideSubsetShaderTemplateFile(GetUserResourcePath(subsetPath, u8"besh.txt")); - - node.Connect(dependencyTree[GTSL::Hash(subsetPath + u8".besh.txt")]); // Connect permutation guide to shader template - - if(guideSubsetShaderTemplateFile) { - a.EmplaceBack(guideSubsetShaderTemplateFile, GetPersistentAllocator()); - } else { - BE_LOG_WARNING(u8"Didn't find any shader subset template for subset: ", GTSL::StringView(subset[u8"name"]), u8"."); - } - } - } - - permutation->JSON = GTSL::MoveRef(json); - } - - if(GTSL::IsIn(fileData.Name, u8"besh.json")) { - GTSL::File jsonShaderFile(GetUserResourcePath(fileData.Name)); - GTSL::StaticBuffer<2048> jsonShaderFileBuffer(jsonShaderFile); - - auto json = GTSL::JSON(GTSL::StringView(jsonShaderFileBuffer), GetPersistentAllocator()); - - auto& shaderEntry = shaderMap.Emplace(json[u8"name"], GetPersistentAllocator(), GetPersistentAllocator()); - - if(auto code = json[u8"code"]) { - shaderEntry.rest.element = GTSL::StringView(code); - } else { - GTSL::File shaderFile(GetUserResourcePath(json[u8"name"], u8"besh.txt")); - - if(shaderFile) { - GTSL::Buffer shaderFileBuffer(shaderFile, GetTransientAllocator()); - shaderEntry.rest.element = GTSL::StringView(shaderFileBuffer); - } else { - BE_LOG_WARNING(u8"Did not find a shader file for shader: ", json[u8"name"], u8"."); - } - } - - shaderEntry.element = GTSL::MoveRef(json); - } - - if(GTSL::IsIn(fileData.Name, u8"besg")) { - auto shaderGroupName = fileData.Name; RTrimFirst(shaderGroupName, u8'.'); - - ShaderGroupDataSerialize& shaderGroupDataSerialize = shaderGroupMap.Emplace(shaderGroupName, GetPersistentAllocator()); - - { - GTSL::FileQuery shaderGroupInstanceFileQuery(GetUserResourcePath(shaderGroupName + u8"_*", u8"json")); - - while (auto instanceFileRef = shaderGroupInstanceFileQuery()) { - GTSL::File shaderGroupInstanceFile(GetUserResourcePath(instanceFileRef.Get()), GTSL::File::READ, false); - GTSL::Buffer shaderGroupInstanceBuffer(shaderGroupInstanceFile, GetTransientAllocator()); - - auto shaderGroupInstanceJson = GTSL::JSON(GTSL::StringView(shaderGroupInstanceBuffer), GetPersistentAllocator()); - - auto instanceName = instanceFileRef.Get(); - LTrimFirst(instanceName, u8'_'); RTrimLast(instanceName, u8'.'); - - auto& instance = shaderGroupDataSerialize.Instances.EmplaceBack(); - instance.Name = instanceName; - - for (auto f : shaderGroupInstanceJson[u8"parameters"]) { - auto& param = instance.Parameters.EmplaceBack(); - param.First = f[u8"name"]; - param.Second = f[u8"defaultValue"]; - } - } - } - - GTSL::File shaderGroupFile(GetUserResourcePath(fileData.Name)); - - GTSL::Buffer shaderGroupBuffer(GetTransientAllocator()); shaderGroupFile.Read(shaderGroupBuffer); - - const auto& json = shaderGroupJSONsMap.Emplace(shaderGroupName, GTSL::StringView(shaderGroupBuffer), GetPersistentAllocator()); - - // Do domain to permutation guide matching - auto domain = json[u8"domain"]; - - for(auto permutation : permutationsMap) { - for(auto d : permutation->GetSupportedDomains()) { - if(GTSL::StringView(domain) == d) { // If this permutation guide supports this domain, add - dependencyTree[GTSL::Hash(GTSL::StaticString<128>(permutation->InstanceName) + u8".bespg.json")].Connect(node); // Connect permutation guide to shader group - } - } - } - - // Connect shader group to shaders in dependency tree - for(auto shader : json[u8"shaders"]) { - auto shaderName = shader[u8"name"]; - - node.Connect(dependencyTree[GTSL::Hash(GTSL::StaticString<128>(shaderName) + u8".besh.json")]); - node.Connect(dependencyTree[GTSL::Hash(GTSL::StaticString<128>(shaderName) + u8".besh.txt")]); - } - - //TODO: connect shader group instances and shaders to those so when shader instances are modified shaders can be updated - - processShaderGroup(json, pipeline, commonPermutation, &shaderGroupDataSerialize, shaderMap); - } - }; - - // Handles serialization and does compilation - auto processTree = [&](const Graph& processed, const Graph& node, GTSL::StringView match, State state, auto&& self) -> void { - if(state == State::NONE) { return; } - - auto& interestData = processed.GetData(); auto& parentData = node.GetData(); - - if(GTSL::IsIn(parentData.Name, match) and state == State::MODIFIED) { // If current node is of the needed type - auto shaderGroupName = parentData.Name; RTrimFirst(shaderGroupName, u8'.'); - - auto& sgd = shaderGroupMap[shaderGroupName]; // TODO: don't remake shader group, only do if first time compiling - - if(GTSL::IsIn(interestData.Name, u8"besh.txt")) { // If interested node is shader - auto shaderName = GTSL::StaticString<128>(interestData.Name); - RTrimFirst(shaderName, u8'.'); - BE_LOG_MESSAGE(u8"Recompiling ", interestData.Name, u8" shader."); - - makeShaderGroup(shaderGroupJSONsMap[shaderGroupName], pipeline, commonPermutation, &sgd, shaderMap); // TODO: watch out for shader scope handles, when doing hot reloading as they will still be in the shader group data serialize - - auto shaderJSON = GTSL::Find(sgd.ShaderJSONs, [&shaderName](const GTSL::JSON& json){ return json[u8"name"] == shaderName; }); - - auto shaderBinaryBuffer = compileShader(*shaderJSON.Get(), pipeline, sgd.SSS[0][shaderJSON.Get() - sgd.ShaderJSONs.begin()]); - - if(shaderBinaryBuffer.GetLength()) { // If succesfully compiled shader - serializeShader(*shaderJSON.Get(), shaderBinaryBuffer.GetRange()); - UpdateFileHashCache(interestData.Pointer, changeCache, interestData.FileHash); // Update cached hash of file only if shader was actually updated - } else { // Failed to compile shader - BE_LOG_ERROR(u8"Failed to compile shader: ", shaderName, u8"."); - } - - return; - } - } - - if(GTSL::IsIn(interestData.Name, u8"bespg")) { - } - - if(GTSL::IsIn(interestData.Name, u8"besh") and state == State::MODIFIED) { - // Look for first shader group upstream and recompile the shader under that context, as shaders "cannot" be compiled stand-alone - //BE_LOG_WARNING(u8"Parents: ") - //for(auto& e : node.GetParents()) { - // BE_LOG_WARNING(e.GetData().Name); - //} - - for(auto& e : node.GetParents()) { - self(processed, e, u8"besg", state, self); - } - } - - if(GTSL::IsIn(interestData.Name, u8"besg")) { - auto shaderGroupName = interestData.Name; RTrimFirst(shaderGroupName, u8'.'); - - auto& sgd = shaderGroupMap[shaderGroupName]; - auto& sgdJSON = shaderGroupJSONsMap[shaderGroupName]; - - makeShaderGroup(sgdJSON, pipeline, commonPermutation, &sgd, shaderMap); // TODO: watch out for shader scope handles, when doing hot reloading as they will still be in the shader group data serialize - - if(interestData.Name == parentData.Name) { - for(auto& permutationManager : permutationsMap) { - // If permutation guide supports this domain - if (Contains(permutationManager->GetSupportedDomains(), GTSL::StringView(sgdJSON[u8"domain"]))) { - serializeShaderGroup(permutationManager, sgd); - break; // Make it so only one permutation guide can used, TODO: support multiple permutation guides per shader group - } - } - - for(const auto& p : sgd.SSS) { - BE_ASSERT(p.GetLength() == sgd.ShaderJSONs.GetLength(), u8""); - - for(uint32 i = 0; i < p; ++i) { - auto& s = p[i]; - const auto& shaderJSON = sgd.ShaderJSONs[i]; - - auto shaderBinaryBuffer = compileShader(shaderJSON, pipeline, s); - serializeShader(shaderJSON, shaderBinaryBuffer.GetRange()); - } - } - } - - return; - } - }; - - if(changedFiles) { // If there are any changed files, load all info - for(auto& e : fileTree) { // Visit file tree to build all state - populateTree(dependencyTree[GTSL::Hash(e.GetData().Name)], e.GetData().state); - } - - for(auto& e : changedFiles) { // Visit new files and add them to the tree - if(fileTree.Find(GTSL::Hash(e.Name)) and e.state != State::DELETED) { continue; } - populateTree(dependencyTree[GTSL::Hash(e.Name)], e.state); - } - } - - { - uint32 offset = 0; - - while(offset != shaderInfoTableFile.GetSize()) { - offset = ReadIndexEntry(shaderInfoTableFile, offset, [&](const uint64 offs, const GTSL::StringView name) { - shaderInfoOffsets.Emplace(GTSL::Hash(name), offs); - shaderInfoPointers.Emplace(GTSL::Hash(name), offset); - }); - } - } - - { - uint32 offset = 0; - - while(offset != shadersTableFile.GetSize()) { - offset = ReadIndexEntry(shadersTableFile, offset, [&](const uint64 offs, const GTSL::StringView name) { - shaderOffsets.Emplace(GTSL::Hash(name), offs); - shadersPointer.Emplace(GTSL::Hash(name), offset); - }); - } - } - - // After the whole tree is populated and info pointers have been loaded - // Visit the tree once more now compiling everything based on the data that was generated earlier - - for(auto& node : dependencyTree) { - processTree(node, node, u8"xxxxxxxxxxx", node.GetData().state, processTree); - } - - auto printDependencyTree = [&](uint64 parent_file_name_hash, const Graph& node, auto&& self) -> void { - auto& nodeData = node.GetData(); - - UpdateParentFileNameCache(nodeData.Pointer, changeCache, parent_file_name_hash); - - //BE_LOG_SUCCESS(u8"Parent: ", parent_file_name_hash, u8"Node: ", node.GetData().Name); - for(auto& e : node.GetChildren()) { - //BE_LOG_SUCCESS(u8"Child: ", e.GetData().Name); - self(GTSL::Hash(nodeData.Name), e, self); - } - }; - - if(changedFiles) { - printDependencyTree(0ull, dependencyTree[GTSL::Hash(u8"CommonPermutation.bespg.json")], printDependencyTree); - } - - for (auto& e : changedFiles) { - if(e.state != State::DELETED) { continue; } - // TODO: delete - } - - { - uint32 offset = 0; - - while(offset != shaderGroupsTableFile.GetSize()) { - offset = ReadIndexEntry(shaderGroupsTableFile, offset, [&](const uint64 offset, const GTSL::StringView name) { shaderGroupInfoOffsets.Emplace(Id(name), offset); }); - } - } -} - -inline void ParseStructJSONAndDeclareStruct(const GTSL::JSON& json, GPipeline& pipeline, GPipeline::ElementHandle scope) { - GTSL::StaticVector elements; - - for (auto m : json[u8"members"]) { - elements.EmplaceBack(m[u8"type"], m[u8"name"]); - } - - pipeline.DeclareStruct(scope, json[u8"name"], elements); -} - -inline void ShaderResourceManager::processShaderGroup(const GTSL::JSON& json, GPipeline& pipeline, - PermutationManager* root_permutation, ShaderGroupDataSerialize* shader_group_data_serialize, const ShaderMap& shader_map) { - auto shaderGroupScope = pipeline.DeclareScope(GPipeline::GLOBAL_SCOPE, json[u8"name"]); - - pipeline.DeclareConstant(shaderGroupScope, { u8"uint32", u8"DEBUG", u8"0" }); - - for (auto s : json[u8"structs"]) { - ParseStructJSONAndDeclareStruct(s, pipeline, shaderGroupScope); - } - - for(auto scope : json[u8"scopes"]) { - auto scopeHandle = pipeline.DeclareScope(shaderGroupScope, scope[u8"name"]); - - for(auto e : scope[u8"elements"]) { - pipeline.DeclareVariable(scopeHandle, { e[u8"type"], e[u8"name"] }); - } - } - - if(auto dataLayers = json[u8"dataLayers"]) { - auto pcb = pipeline.DeclareScope(shaderGroupScope, u8"pushConstantBlock"); - - for(auto dataLayer : dataLayers) { - pipeline.DeclareVariable(pcb, { dataLayer[u8"type"], dataLayer[u8"name"] }); - } - } - - for (auto f : json[u8"functions"]) { - GTSL::StaticVector elements; - for (auto p : f[u8"parameters"]) { elements.EmplaceBack(p[u8"type"], p[u8"name"]); } - pipeline.DeclareFunction(shaderGroupScope, f[u8"type"], f[u8"name"], elements, f[u8"code"]); - } - - shader_group_data_serialize->Name = json[u8"name"]; - - for (auto e : json[u8"tags"]) { - shader_group_data_serialize->Tags.EmplaceBack(e[u8"name"].GetStringView(), e[u8"value"].GetStringView()); - } - - { - GPipeline::ElementHandle shaderParametersDataHandle; - GTSL::StaticVector structElements; - - for (auto p : json[u8"parameters"]) { - if (auto def = p[u8"defaultValue"]) { - shader_group_data_serialize->Parameters.EmplaceBack(p[u8"type"], p[u8"name"], def); - structElements.EmplaceBack(p[u8"type"], p[u8"name"], def); - } else { - shader_group_data_serialize->Parameters.EmplaceBack(p[u8"type"], p[u8"name"], u8""); - structElements.EmplaceBack(p[u8"type"], p[u8"name"], u8""); - } - } - - shaderParametersDataHandle = pipeline.DeclareStruct(shaderGroupScope, u8"ShaderParametersData", structElements); - } - - shader_group_data_serialize->VertexElements.EmplaceBack().EmplaceBack(u8"vec3f", u8"POSITION"); - shader_group_data_serialize->VertexElements.EmplaceBack().EmplaceBack(u8"vec3f", u8"NORMAL"); - shader_group_data_serialize->VertexElements.EmplaceBack().EmplaceBack(u8"vec3f", u8"TANGENT"); - shader_group_data_serialize->VertexElements.EmplaceBack().EmplaceBack(u8"vec3f", u8"BITANGENT"); - shader_group_data_serialize->VertexElements.EmplaceBack().EmplaceBack(u8"vec2f", u8"TEXTURE_COORDINATES"); - - if(!shader_group_data_serialize->Instances) { - auto& basicInstance = shader_group_data_serialize->Instances.EmplaceBack(); - basicInstance.Name = json[u8"name"]; - } - - bool rayTrace = false; ShaderGroupInfo::RayTraceData ray_trace_data; - - auto shaderGroupDomain = json[u8"domain"]; - - shader_group_data_serialize->RayTrace = rayTrace; - shader_group_data_serialize->RayTraceData = ray_trace_data; -} - -inline void ShaderResourceManager::makeShaderGroup(const GTSL::JSON& json, GPipeline& pipeline, PermutationManager* root_permutation, ShaderGroupDataSerialize* shader_group_data_serialize, const ShaderMap& shader_map) { - auto shaderGroupScope = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, json[u8"name"]); - auto& scopesPerPermutations = shader_group_data_serialize->SSS; - - const auto shaderGroupDomain = json[u8"domain"]; - - auto evaluateForPermutation = [&](PermutationManager* permutation_manager, GTSL::StaticVector permutationScopes, auto&& self) -> void { - auto permutationScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, permutation_manager->InstanceName); - permutationScopes.EmplaceBack(permutationScopeHandle); //Insert permutation handle - - // If permutation handles this shader group's domains, evalute shader group for permutation, else check if children can handle this domain and then return - if (!Contains(permutation_manager->GetSupportedDomains(), GTSL::StringView(shaderGroupDomain))) { - for(auto e : permutation_manager->GetChildren()) { - self(e, permutationScopes, self); - } - - return; - } - - auto& xxx = scopesPerPermutations.EmplaceBack(); - - permutationScopes.EmplaceBack(shaderGroupScope); - - auto auxScopes = permutationScopes; - - for (auto s : json[u8"shaders"]) { - permutationScopes = auxScopes; //reset scopes for every shader built - - if(!shader_map.Find(s[u8"name"])) { BE_LOG_WARNING(u8"Could not find any shader under name: ", GTSL::StringView(s[u8"name"])); continue; } - - auto& shaderEntry = shader_map[s[u8"name"]]; - auto& shaderJson = GTSL::Get<0>(shaderEntry); - - GTSL::StaticString<64> executionString; - - shaderJson[u8"execution"](executionString); - - if (GTSL::StringView(shaderGroupDomain) == GTSL::StringView(u8"Screen")) { - executionString = GTSL::ShortString<64>(u8"windowExtent"); - } - - GPipeline::ElementHandle shaderScope = pipeline.DeclareShader(shaderGroupScope, shaderJson[u8"name"]); - - auto pcd = pipeline.DeclareScope(shaderScope, u8"pushConstantBlock"); - - pipeline.DeclareVariable(pcd, { u8"ShaderParametersData*", u8"shaderParameters" }); - - for(auto sharedVariableJSON : shaderJson[u8"sharedVariables"]) { - pipeline.DeclareShared(shaderScope, { sharedVariableJSON[u8"type"], sharedVariableJSON[u8"name"] }); - } - - if (shaderJson[u8"class"].GetStringView() == GTSL::StringView(u8"COMPUTE") or shaderJson[u8"class"].GetStringView() == GTSL::StringView(u8"RAY_GEN")) { - GTSL::StaticString<64> x, y, z; - - if(auto res = shaderJson[u8"localSize"]) { - GTSL::ToString(x, res[0].GetUint()); GTSL::ToString(y, res[1].GetUint()); GTSL::ToString(z, res[2].GetUint()); - } else { - x = u8"1"; y = u8"1"; z = u8"1"; - } - - pipeline.DeclareVariable(shaderScope, { u8"uint16", u8"group_size_x", x }); - pipeline.DeclareVariable(shaderScope, { u8"uint16", u8"group_size_y", y }); - pipeline.DeclareVariable(shaderScope, { u8"uint16", u8"group_size_z", z }); - } - - uint32 i = 0, j = 0; bool found = false; - - for(; i < permutation_manager->JSON[u8"options"]; ++i) { - if(permutation_manager->JSON[u8"options"][i][u8"domain"] == GTSL::StringView(shaderGroupDomain)) { - for(; j < permutation_manager->JSON[u8"options"][i][u8"subsets"]; ++j) { - auto shaderClass = GTSL::StaticString<64>(shaderJson[u8"class"]); - - for(uint32 k = 0; k < permutation_manager->JSON[u8"options"][i][u8"subsets"][j][u8"sourceClasses"]; ++k) { - auto s = GTSL::StaticString<64>(permutation_manager->JSON[u8"options"][i][u8"subsets"][j][u8"sourceClasses"][k]); - if(s == shaderClass) { - found = true; - break; - } - } - - if(found) break; - } - - if(found) break; - } - } - - if(!found or !(i < permutation_manager->a) or !(j < permutation_manager->a[i])) { - BE_LOG_WARNING(u8"Could not generate shader: ", GTSL::StringView(shaderJson[u8"name"]), u8", for shader group: ", GTSL::StringView(json[u8"name"]), u8", because a shader template for permutation: ", permutation_manager->InstanceName, (i < permutation_manager->a) ? GTSL::StaticString<128>(u8", option: ") + GTSL::StringView(permutation_manager->JSON[u8"options"][i][u8"name"]) : GTSL::StaticString<128>(), (i < permutation_manager->a && j < permutation_manager->a[i]) ? GTSL::StaticString<128>(u8", subset: ") + GTSL::StringView(permutation_manager->JSON[u8"options"][i][u8"subsets"][j][u8"name"]) : GTSL::StaticString<128>(), u8", was not available."); - return; - } - - auto& shaderFileSourceCode = shaderEntry.rest.element; - - GTSL::Vector tokens(GetTransientAllocator()); - tokenizeCode(shaderFileSourceCode, tokens, GetTransientAllocator()); - - for(uint32 t = 0u; t < tokens; ++t) { - if(tokens[t].Name != u8"function") { continue; } - - ++t; // Skip "function" token - - auto returnType = tokens[t].Name; - ++t; - auto functionName = tokens[t].Name; - ++t; - - ++t; // Skip open parenthesis - - GTSL::StaticVector parameters; - - while(true) { - if(tokens[t].Name == u8")") { ++t; break; } - - auto parameterReturnType = tokens[t].Name; - ++t; - - if(parameterReturnType == u8"inout" or parameterReturnType == u8"in" or parameterReturnType == u8"out") { - parameterReturnType &= tokens[t].Name; - ++t; - } - - auto parameterName = tokens[t].Name; - ++t; - parameters.EmplaceBack(parameterReturnType, parameterName); - if(tokens[t].ValueType == ShaderNode::Type::COMMA) { ++t; } - } - - ++t; // Skip open brace - - const auto shaderGuide = GTSL::StringView(permutation_manager->a[i][j]); - - auto b = shaderGuide.begin(); - - while(b != shaderGuide.end() && *b != u8'@') { - ++b; - } - - auto functionHandle = pipeline.DeclareFunction(shaderScope, returnType, functionName, parameters); - - if(functionName == u8"main") { - pipeline.AddCodeToFunction(functionHandle, { shaderGuide.begin(), b }); - } - - uint32 startFunctionCode = t; - - uint32 openCloseCounter = 1u; // Must be one because we skipped over open brace - while(true) { - if(tokens[t].Name == u8"}") { - --openCloseCounter; - if(!openCloseCounter) { - break; - } - } - if(tokens[t].Name == u8"{") { ++openCloseCounter; } - ++t; - } - - pipeline.AddCodeToFunction(functionHandle, {t - startFunctionCode, tokens.begin() + startFunctionCode}); - - if(functionName == u8"main") { - pipeline.AddCodeToFunction(functionHandle, { ++b, shaderGuide.end() }); - } - } - - { - // FIX - { - auto commonPermutationScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, u8"CommonPermutation"); - - Class shaderClass = ShaderClassFromString(shaderJson[u8"class"]); - - GPipeline::ElementHandle subScopeHandle; - - switch (shaderClass) { - case Class::VERTEX: subScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, u8"VertexShader"); break; - case Class::SURFACE: subScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, u8"FragmentShader"); break; - case Class::COMPUTE: subScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, u8"ComputeShader"); - permutationScopes.EmplaceBack(pipeline.GetElementHandle(commonPermutationScopeHandle, u8"ComputeRenderPass")); - break; - case Class::RENDER_PASS: break; - case Class::CLOSEST_HIT: subScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, u8"ClosestHitShader"); break; - case Class::RAY_GEN: subScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, u8"RayGenShader"); break; - case Class::MISS: subScopeHandle = pipeline.GetElementHandle(GPipeline::GLOBAL_SCOPE, u8"MissShader"); break; - } - - permutationScopes.EmplaceBack(subScopeHandle); - } - // FIX - - permutationScopes.EmplaceBack(shaderScope); - - GTSL::String shaderJsonString(GetTransientAllocator()); - - auto serializer = GTSL::MakeSerializer(shaderJsonString); - - GTSL::Insert(serializer, shaderJsonString, u8"name", shaderJson[u8"name"]); - GTSL::Insert(serializer, shaderJsonString, u8"binarySize", 0ull); - GTSL::Insert(serializer, shaderJsonString, u8"binaryHash", 0ull); - GTSL::Insert(serializer, shaderJsonString, u8"class", shaderJson[u8"class"]); - GTSL::Insert(serializer, shaderJsonString, u8"targetSemantics", permutation_manager->JSON[u8"options"][i][u8"subsets"][j][u8"targetSemantics"]); - - GTSL::StartArray(serializer, shaderJsonString, u8"tags"); - - for(auto e : permutation_manager->JSON[u8"tags"]) { - GTSL::StartObject(serializer, shaderJsonString); - - GTSL::Insert(serializer, shaderJsonString, u8"name", e[u8"name"]); - GTSL::Insert(serializer, shaderJsonString, u8"value", e[u8"value"]); - - GTSL::EndObject(serializer, shaderJsonString); - } - - for(auto e : json[u8"tags"]) { - GTSL::StartObject(serializer, shaderJsonString); - - GTSL::Insert(serializer, shaderJsonString, u8"name", e[u8"name"]); - GTSL::Insert(serializer, shaderJsonString, u8"value", e[u8"value"]); - - GTSL::EndObject(serializer, shaderJsonString); - } - - for(auto e : shaderJson[u8"tags"]) { - GTSL::StartObject(serializer, shaderJsonString); - - GTSL::Insert(serializer, shaderJsonString, u8"name", e[u8"name"]); - GTSL::Insert(serializer, shaderJsonString, u8"value", e[u8"value"]); - - GTSL::EndObject(serializer, shaderJsonString); - } - - GTSL::EndArray(serializer, shaderJsonString); - - GTSL::EndSerializer(shaderJsonString, serializer); - - shader_group_data_serialize->ShaderJSONs.EmplaceBack(GTSL::JSON(shaderJsonString, GetTransientAllocator())); - - shader_group_data_serialize->Shaders.EmplaceBack(GTSL::Hash(shaderJson[u8"name"])); - - xxx.EmplaceBack(permutationScopes); - } - } - }; - - evaluateForPermutation(root_permutation, {GPipeline::GLOBAL_SCOPE}, evaluateForPermutation); -} - -inline void ShaderResourceManager::serializeShaderGroup(const PermutationManager* permutation_manager, const ShaderGroupDataSerialize& shader_group_data_serialize) { - for(auto& e :shader_group_data_serialize.Instances) { - WriteIndexEntry(shaderGroupsTableFile, ~0ULL, shaderGroupInfosFile.GetSize(), e.Name); // write offset to shader group for each instance name - } - - { - shaderGroupInfosFile << shader_group_data_serialize.Name; - - shaderGroupInfosFile << shader_group_data_serialize.Shaders.GetLength(); - for (auto& e : shader_group_data_serialize.Shaders) { shaderGroupInfosFile << e; } - - shaderGroupInfosFile << shader_group_data_serialize.Parameters.GetLength(); - for (auto& p : shader_group_data_serialize.Parameters) { - shaderGroupInfosFile << p.Type << p.Name << p.Value; - } - - uint32 tagCount = 0; - tagCount += permutation_manager->JSON[u8"tags"].GetCount(); - tagCount += shader_group_data_serialize.Tags.GetLength(); - shaderGroupInfosFile << tagCount; - - for(auto e : permutation_manager->JSON[u8"tags"]) { - shaderGroupInfosFile << e[u8"name"] << e[u8"value"]; - } - - for (auto& p : shader_group_data_serialize.Tags) { - shaderGroupInfosFile << p.First << p.Second; - } - - shaderGroupInfosFile << shader_group_data_serialize.Instances.GetLength(); - for (auto& i : shader_group_data_serialize.Instances) { - - shaderGroupInfosFile << i.Name; - - shaderGroupInfosFile << i.Parameters.GetLength(); - for (auto& p : i.Parameters) { - shaderGroupInfosFile << p.First << p.Second; - } - } - - - shaderGroupInfosFile << shader_group_data_serialize.VertexElements.GetLength(); - for (auto& e : shader_group_data_serialize.VertexElements) { - shaderGroupInfosFile << e.GetLength(); - for (auto& ve : e) { - shaderGroupInfosFile << ve.Type << ve.Name; - } - } - - shaderGroupInfosFile << shader_group_data_serialize.RayTrace; - - if (shader_group_data_serialize.RayTrace) { - const auto& rayTraceData = shader_group_data_serialize.RayTraceData; - shaderGroupInfosFile << rayTraceData.Payload.Type << rayTraceData.Payload.Name << rayTraceData.Payload.DefaultValue; - - for (uint32 i = 0; i < 4; ++i) { - shaderGroupInfosFile << rayTraceData.Groups[i].ShadersPerGroup.GetLength(); - - for (uint32 j = 0; j < rayTraceData.Groups[i].ShadersPerGroup.GetLength(); ++j) { - shaderGroupInfosFile << rayTraceData.Groups[i].ShadersPerGroup[j]; - } - } - } - } -} - -inline GTSL::Buffer ShaderResourceManager::compileShader( - const GTSL::JSON& json, const GPipeline& pipeline, - const GTSL::Range source_scopes) { - GTSL::StaticVector scopesStrings; - - GTSL::StaticVector scopes(source_scopes); - - // Make shader name by appending all the names of the scopes that comprise, which allows to easily identify the permutation - for (auto& e : scopes) { if (auto& n = pipeline.GetElement(e).Name) { scopesStrings.EmplaceBack(n); } } - - GTSL::StaticString<64> shaderName = GTSL::StringView(json[u8"name"]); - GTSL::StaticString<512> qualifiedShaderName; qualifiedShaderName += GTSL::Join{ scopesStrings, u8"." }; - - const auto targetSemantics = ShaderTypeFromString(json[u8"targetSemantics"]); - - auto shaderCode = GenerateShader(pipeline, scopes, targetSemantics, GetTransientAllocator()); - if (!shaderCode) { BE_LOG_WARNING(shaderCode.Get().Second); } - - auto [compilationSuccessCode, compilationErrors, shaderBinaryBuffer] = compiler_.Compile(shaderCode.Get().First, shaderName, targetSemantics, GAL::ShaderLanguage::GLSL, true, GetTransientAllocator()); - - if (!compilationSuccessCode) { - GTSL::Console::Print(shaderCode.Get().First); - BE_LOG_ERROR(compilationErrors); - } - - return GTSL::MoveRef(shaderBinaryBuffer); -} - -inline void ShaderResourceManager::serializeShader(const GTSL::JSON& json, GTSL::Range shader_binary_buffer) { - auto a = shaderInfoPointers.TryEmplace(GTSL::Hash(json[u8"name"]), ~0ULL); - auto b = shadersPointer.TryEmplace(GTSL::Hash(json[u8"name"]), ~0ULL); - - auto nameHash = GTSL::Hash(json[u8"name"]); - - auto x = shaderInfosFile.GetSize(); - auto y = shaderPackageFile.GetSize(); - - a.Get() = WriteIndexEntry(shaderInfoTableFile, a.Get(), x, json[u8"name"]); - b.Get() = WriteIndexEntry(shadersTableFile, b.Get(), y, json[u8"name"]); - - if(shaderInfoOffsets.Find(nameHash)) { - shaderInfoOffsets[nameHash] = x; - } else { - shaderInfoOffsets.Emplace(nameHash, x); - } - - if(shaderOffsets.Find(nameHash)) { - shaderOffsets.At(nameHash) = y; - } else { - shaderOffsets.Emplace(nameHash, y); - } - - GTSL::String string(GetTransientAllocator()); - - GTSL::JSONSerializer serializer = GTSL::MakeSerializer(string); - - GTSL::Insert(serializer, string, u8"name", GTSL::StringView(json[u8"name"])); - GTSL::Insert(serializer, string, u8"binarySize", shader_binary_buffer.Bytes()); - const auto shaderBinaryHash = quickhash64(shader_binary_buffer); - GTSL::Insert(serializer, string, u8"binaryHash", shaderBinaryHash); - GTSL::Insert(serializer, string, u8"targetSemantics", json[u8"targetSemantics"]); - - GTSL::StartArray(serializer, string, u8"tags"); - - for (auto t : json[u8"tags"]) { - GTSL::StartObject(serializer, string); - GTSL::Insert(serializer, string, u8"name", t[u8"name"]); - GTSL::Insert(serializer, string, u8"value", t[u8"value"]); - GTSL::EndObject(serializer, string); - } - - GTSL::EndArray(serializer, string); - - //pipeline.MakeJSON(string, scopes); //MAKE JSON - - GTSL::EndSerializer(string, serializer); - - shaderInfosFile.SetPointer(x); - shaderInfosFile << string; - shaderPackageFile.SetPointer(y); - shaderPackageFile.Write(shader_binary_buffer); -} \ No newline at end of file diff --git a/src/ByteEngine/Resources/StaticMeshResourceManager.cpp b/src/ByteEngine/Resources/StaticMeshResourceManager.cpp deleted file mode 100644 index 49fc7799..00000000 --- a/src/ByteEngine/Resources/StaticMeshResourceManager.cpp +++ /dev/null @@ -1,410 +0,0 @@ -#include "StaticMeshResourceManager.h" - -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Debug/Assert.h" - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -static GTSL::Vector4 ToGTSL(const aiColor4D assimpVector) { - return GTSL::Vector4(assimpVector.r, assimpVector.g, assimpVector.b, assimpVector.a); -} - -static GTSL::Vector3 ToGTSL(const aiVector3D assimpVector) { - return GTSL::Vector3(assimpVector.x, assimpVector.y, assimpVector.z); -} - -static GTSL::Vector2 ToGTSL(const aiVector2D assimpVector) { - return GTSL::Vector2(assimpVector.x, assimpVector.y); -} - -static GTSL::Matrix4 ToGTSL(const aiMatrix4x4 assimpMatrix) -{ - return GTSL::Matrix4( - assimpMatrix.a1, assimpMatrix.a2, assimpMatrix.a3, assimpMatrix.a4, - assimpMatrix.b1, assimpMatrix.b2, assimpMatrix.b3, assimpMatrix.b4, - assimpMatrix.c1, assimpMatrix.c2, assimpMatrix.c3, assimpMatrix.c4, - assimpMatrix.d1, assimpMatrix.d2, assimpMatrix.d3, assimpMatrix.d4 - ); -} - -using ShaderDataTypeType = GTSL::UnderlyingType; - -StaticMeshResourceManager::StaticMeshResourceManager(const InitializeInfo& initialize_info) : ResourceManager(initialize_info, u8"StaticMeshResourceManager") { - - resource_files_.Start(GetResourcePath(u8"StaticMeshes")); - - { - GTSL::File meshDescriptionsFile; meshDescriptionsFile.Open(GetUserResourcePath(u8"meshes.json")); - - GTSL::Buffer buffer(GetPersistentAllocator()); meshDescriptionsFile.Read(buffer); - - auto json = GTSL::JSON(GTSL::StringView(buffer.GetLength(), buffer.GetLength(), reinterpret_cast(buffer.GetData())), GetTransientAllocator()); - - for(auto mesh : json[u8"meshes"]) { - auto fileName = mesh[u8"name"]; - const auto hashed_name = GTSL::Id64(fileName); - - if (!resource_files_.Exists(hashed_name)) { - GTSL::StaticString<8> fileExtension; - - GTSL::File meshFile; - - for(auto e : { u8"obj", u8"fbx" }) { - GTSL::File queryFile; - auto res = queryFile.Open(GetUserResourcePath(fileName, e), GTSL::File::READ, false); - - if(res != GTSL::File::OpenResult::ERROR) { - fileExtension = e; - meshFile.Open(GetUserResourcePath(fileName, e), GTSL::File::READ, false); - break; - } - } - - GTSL::Buffer meshFileBuffer(meshFile.GetSize(), 32, GetTransientAllocator()); - meshFile.Read(meshFileBuffer); - - GTSL::Buffer meshDataBuffer(2048 * 2048 * 8, 8, GetTransientAllocator()); - - StaticMeshInfo meshInfo; - - auto loadMeshSuccess = loadMesh(meshFileBuffer, meshInfo, meshDataBuffer, fileExtension); - - for (uint32 i = 0; auto sm : mesh[u8"meshes"]) { - auto& s = meshInfo.GetSubMeshes().array[i]; - if (i < mesh[u8"meshes"].GetCount()) { // If user specified data exists for this sub-mesh use that, else leave default data - s.GetShaderGroupName() = sm[u8"shaderGroup"]; - } else { - s.GetShaderGroupName() = GTSL::ShortString<32>(u8"default"); - } - - ++i; - } - - if (loadMeshSuccess) { - resource_files_.AddEntry(fileName, &meshInfo, meshDataBuffer.GetRange()); - } - } - } - } -} - -StaticMeshResourceManager::~StaticMeshResourceManager() -{ -} - -template -struct nEl { - T e[N]; -}; - -bool StaticMeshResourceManager::loadMesh(const GTSL::Buffer& sourceBuffer, StaticMeshInfo& static_mesh_data, GTSL::Buffer& meshDataBuffer, const GTSL::StringView file_extension) -{ - Assimp::Importer importer; - const auto* const ai_scene = importer.ReadFileFromMemory(sourceBuffer.GetData(), sourceBuffer.GetLength(), aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices | aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs, reinterpret_cast(file_extension.GetData())); - - if (!ai_scene || (ai_scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { - BE_LOG_ERROR(reinterpret_cast(importer.GetErrorString())); - return false; - } - - if (!ai_scene->mMeshes) { return false; } - - bool interleavedStream = false; - - if (interleavedStream) { - auto& a = static_mesh_data.GetVertexDescriptor().EmplaceBack(); - - //MESH ALWAYS HAS POSITIONS - a.EmplaceBack(GAL::ShaderDataType::FLOAT3); - - if (true) { - a.EmplaceBack(GAL::ShaderDataType::FLOAT3); - } - - if (true) { - a.EmplaceBack(GAL::ShaderDataType::FLOAT3); - a.EmplaceBack(GAL::ShaderDataType::FLOAT3); - } - - for (uint8 tex_coords = 0; tex_coords < static_cast(1); ++tex_coords) { - a.EmplaceBack(GAL::ShaderDataType::FLOAT2); - } - - for (uint8 colors = 0; colors < static_cast(0); ++colors) { - a.EmplaceBack(GAL::ShaderDataType::FLOAT4); - } - } else { - //MESH ALWAYS HAS POSITIONS - static_mesh_data.GetVertexDescriptor().EmplaceBack().EmplaceBack(GAL::ShaderDataType::FLOAT3); - - if (true) { - static_mesh_data.GetVertexDescriptor().EmplaceBack().EmplaceBack(GAL::ShaderDataType::FLOAT3); - } - - if (true) { - static_mesh_data.GetVertexDescriptor().EmplaceBack().EmplaceBack(GAL::ShaderDataType::FLOAT3); - static_mesh_data.GetVertexDescriptor().EmplaceBack().EmplaceBack(GAL::ShaderDataType::FLOAT3); - } - - for (uint8 tex_coords = 0; tex_coords < static_cast(1); ++tex_coords) { - static_mesh_data.GetVertexDescriptor().EmplaceBack().EmplaceBack(GAL::ShaderDataType::FLOAT2); - } - - for (uint8 colors = 0; colors < static_cast(0); ++colors) { - static_mesh_data.GetVertexDescriptor().EmplaceBack().EmplaceBack(GAL::ShaderDataType::FLOAT4); - } - } - - static_mesh_data.GetInterleaved() = interleavedStream; - - static_mesh_data.GetVertexCount() = 0; static_mesh_data.GetIndexCount() = 0; static_mesh_data.GetBoundingRadius() = 0; static_mesh_data.GetBoundingBox() = GTSL::Vector3(); - - { - static_mesh_data.GetIndexSize() = 0; - - auto visitNodeValidateAndAllocate = [&](aiNode* ai_node, auto&& self) -> bool { - for (uint32 i = 0; i < ai_node->mNumMeshes; ++i) { - auto inMesh = ai_scene->mMeshes[ai_node->mMeshes[i]]; - if (!(inMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) { return false; } - - if (!inMesh->HasNormals()) { return false; } - if (!inMesh->HasTangentsAndBitangents()) { return false; } - if (!inMesh->HasTextureCoords(0)) { return false; } - if (inMesh->HasVertexColors(0)) { return false; } - - auto& meshInfo = static_mesh_data.GetSubMeshes().EmplaceBack(); - - meshInfo.GetVertexCount() = inMesh->mNumVertices; - meshInfo.GetIndexCount() = inMesh->mNumFaces * 3; - meshInfo.GetBoundingBox() = GTSL::Vector3(); meshInfo.GetBoundingRadius() = 0.0f; - meshInfo.GetMaterialIndex() = inMesh->mMaterialIndex; - - static_mesh_data.GetIndexCount() += meshInfo.GetIndexCount(); - static_mesh_data.GetVertexCount() += meshInfo.GetVertexCount(); - - if(inMesh->mNumVertices > 0xFFFF) { - GTSL::Max(&static_mesh_data.GetIndexSize(), static_cast(4)); - } else { - GTSL::Max(&static_mesh_data.GetIndexSize(), static_cast(2)); - } - } - - for(uint32 i = 0; i < ai_node->mNumChildren; ++i) { - self(ai_node->mChildren[i], self); - } - - return true; - }; - - if(!visitNodeValidateAndAllocate(ai_scene->mRootNode, visitNodeValidateAndAllocate)) { return false; } - - //meshDataBuffer.Resize(static_mesh_data.GetVertexCount() * static_mesh_data.GetVertexSize() + static_mesh_data.GetIndexCount() * static_mesh_data.GetIndexSize()); - meshDataBuffer.DeltaResize(static_mesh_data.GetVertexCount() * static_mesh_data.GetVertexSize() + static_mesh_data.GetIndexCount() * static_mesh_data.GetIndexSize()); - meshDataBuffer.PushBytes(static_mesh_data.GetVertexCount() * static_mesh_data.GetVertexSize() + static_mesh_data.GetIndexCount() * static_mesh_data.GetIndexSize()); - } - - { - uint32 meshIndex = 0; - byte* const dataPointer = meshDataBuffer.GetData(); - uint64 offset = 0; - - auto visitNodeAndLoadMesh = [&](aiNode* ai_node, auto&& self) -> void { - for (uint32 m = 0; m < ai_node->mNumMeshes; ++m) { - const uint64 vertexSize = static_mesh_data.GetVertexSize(); - - //set jump size as variable, since we can write array as interleaved or not - uint64 jumpSize = 0; - - aiMesh* inMesh = ai_scene->mMeshes[ai_node->mMeshes[m]]; - - auto matrix = ToGTSL(ai_node->mTransformation); //TODO: are mesh coordinates relative to own origin or to scene ccenter - - uint32 ai = 0, bi = 0; - - auto& meshInfo = static_mesh_data.GetSubMeshes().array[meshIndex++]; - - uint64 accumulatedOffset = 0; - - auto advanceVertexElement = [&]() { - if(interleavedStream) { - jumpSize = vertexSize; - auto* po = dataPointer + offset + GAL::GraphicsPipeline::GetByteOffsetToMember(bi, static_mesh_data.GetVertexDescriptor().array[ai]); - ++bi; - return po; - } else { - if(bi == static_mesh_data.GetVertexDescriptor().array[ai].Length) { - bi = 0; - ++ai; - } - - jumpSize = GAL::GraphicsPipeline::GetByteOffsetToMember(bi + 1, static_mesh_data.GetVertexDescriptor().array[ai]); - auto* po = dataPointer + offset + accumulatedOffset * static_mesh_data.GetVertexCount(); - - accumulatedOffset += jumpSize; - - ++bi; - - return po; - } - }; - - auto writeElement = [&](T * elementPointer, const T & obj, const uint32 elementIndex) -> void { - *reinterpret_cast(reinterpret_cast(elementPointer) + (elementIndex * jumpSize)) = obj; - }; - - auto doWrite = [writeElement](const GAL::ShaderDataType format, T value, byte * byteData, uint32 vertexIndex) { - switch (format) { - case GAL::ShaderDataType::FLOAT2: { - if constexpr (std::is_same_v) { - auto* positions = reinterpret_cast(byteData); - writeElement(positions, value, vertexIndex); - } - - if constexpr (std::is_same_v) { - auto* positions = reinterpret_cast(byteData); - writeElement(positions, GTSL::Vector2(value[0], value[1]), vertexIndex); - } - - break; - } - case GAL::ShaderDataType::FLOAT3: { - if constexpr (std::is_same_v) { - auto* positions = reinterpret_cast(byteData); - writeElement(positions, value, vertexIndex); - } - break; - } - case GAL::ShaderDataType::U16_SNORM3: { - if constexpr (std::is_same_v) { - auto* positions = reinterpret_cast*>(byteData); - writeElement(positions, { GAL::FloatToSNORM(value[0]), GAL::FloatToSNORM(value[1]), GAL::FloatToSNORM(value[2]) }, vertexIndex); - } - - break; - } - case GAL::ShaderDataType::U16_UNORM2: { - if constexpr (std::is_same_v) { - auto* positions = reinterpret_cast*>(byteData); - auto textureCoordinate = GTSL::Vector2(value); - writeElement(positions, { GAL::FloatToUNORM(textureCoordinate[0]), GAL::FloatToUNORM(textureCoordinate[1]) }, vertexIndex); - } - break; - } - case GAL::ShaderDataType::UINT64: { - if constexpr (std::is_same_v) { - auto* positions = reinterpret_cast*>(byteData); - writeElement(positions, { static_cast(value[0] * static_cast(127)), static_cast(value[1] * static_cast(127)), static_cast(value[2] * static_cast(127)) }, vertexIndex); - } - break; - } - case GAL::ShaderDataType::FLOAT4: { - if constexpr (std::is_same_v) { - auto* positions = reinterpret_cast(byteData); - writeElement(positions, value, vertexIndex); - } - break; - } - } - }; - - auto writeAndReadVertexComponent = [&](GAL::ShaderDataType format, T * assimpDataArray, auto && perVertexFunc) { - auto* byteData = advanceVertexElement(); - - for (uint64 vertexIndex = 0; vertexIndex < inMesh->mNumVertices; ++vertexIndex) { - auto assimpAttribute = ToGTSL(assimpDataArray[vertexIndex]); - perVertexFunc(assimpAttribute); - doWrite(format, assimpAttribute, byteData, vertexIndex); - } - }; - - auto writeVertexComponent = [&](GAL::ShaderDataType format, T * assimpDataArray) -> void { - auto* byteData = advanceVertexElement(); - - for (uint64 vertexIndex = 0; vertexIndex < inMesh->mNumVertices; ++vertexIndex) { - doWrite(format, ToGTSL(assimpDataArray[vertexIndex]), byteData, vertexIndex); - } - }; - - writeAndReadVertexComponent(GAL::ShaderDataType::FLOAT3, inMesh->mVertices, [&](GTSL::Vector3 position) { - meshInfo.GetBoundingBox() = GTSL::Math::Max(meshInfo.GetBoundingBox(), GTSL::Math::Abs(position)); - meshInfo.GetBoundingRadius() = GTSL::Math::Max(meshInfo.GetBoundingRadius(), GTSL::Math::Length(position)); - }); - - if (inMesh->HasNormals()) { - writeVertexComponent(GAL::ShaderDataType::FLOAT3, inMesh->mNormals); - } - - if (inMesh->HasTangentsAndBitangents()) { - writeVertexComponent(GAL::ShaderDataType::FLOAT3, inMesh->mTangents); - writeVertexComponent(GAL::ShaderDataType::FLOAT3, inMesh->mBitangents); - } - - for (uint8 i = 0; i < 8 && inMesh->HasTextureCoords(i); ++i) { - writeVertexComponent(GAL::ShaderDataType::FLOAT2, inMesh->mTextureCoords[i]); - } - - for (uint8 i = 0; i < 8 && inMesh->HasVertexColors(i); ++i) { - writeVertexComponent(GAL::ShaderDataType::FLOAT4, inMesh->mColors[i]); - } - - //write all vertices together at start, all indices together at the end - //mesh[0].Vertices[], mesh[1].Vertices[], mesh[0].Indices[], mesh[1].Indices[] - if (static_mesh_data.GetIndexSize() == 2) { - //if (inMesh->mNumFaces * 3 < 0xFF) { - // indexSize = 1; - // - // for (uint32 face = 0; face < inMesh->mNumFaces; ++face) { - // for (uint32 index = 0; index < 3; ++index) { - // uint8 idx = static_cast(inMesh->mFaces[face].mIndices[index]); - // meshDataBuffer.CopyBytes(indexSize, reinterpret_cast(&idx)); - // } - // } - //} - //else { - - for (uint32 face = 0; face < inMesh->mNumFaces; ++face) { - for (uint32 index = 0; index < 3; ++index) { - reinterpret_cast(meshDataBuffer.GetData() + static_mesh_data.GetVertexCount() * vertexSize)[face * 3 + index] = static_cast(inMesh->mFaces[face].mIndices[index]); - } - } - } else { - for (uint32 face = 0; face < inMesh->mNumFaces; ++face) { - for (uint32 index = 0; index < 3; ++index) { - reinterpret_cast(meshDataBuffer.GetData() + static_mesh_data.GetVertexCount() * vertexSize)[face * 3 + index] = static_cast(inMesh->mFaces[face].mIndices[index]); - } - } - } - - static_mesh_data.GetBoundingBox() = GTSL::Math::Max(static_mesh_data.GetBoundingBox(), meshInfo.GetBoundingBox()); - - for(uint32 i = 0; i < inMesh->mNumVertices; ++i) { - if(*reinterpret_cast(meshDataBuffer.begin() + 48 * inMesh->mNumVertices + i * 8) != GTSL::Vector2(ToGTSL(inMesh->mTextureCoords[0][i]))) { - } - } - - offset += meshInfo.GetVertexCount() * vertexSize + meshInfo.GetIndexCount() * static_mesh_data.GetIndexSize(); - } - - for (uint32 i = 0; i < ai_node->mNumChildren; ++i) { - self(ai_node->mChildren[i], self); - } - }; - - visitNodeAndLoadMesh(ai_scene->mRootNode, visitNodeAndLoadMesh); - } - - return true; -} \ No newline at end of file diff --git a/src/ByteEngine/Resources/StaticMeshResourceManager.h b/src/ByteEngine/Resources/StaticMeshResourceManager.h deleted file mode 100644 index db39fb4c..00000000 --- a/src/ByteEngine/Resources/StaticMeshResourceManager.h +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once - -#include - -#include "ResourceManager.h" - -#include -#include - -#include "ByteEngine/Game/ApplicationManager.h" -#include "GAL/Pipelines.h" - -namespace GAL { - enum class ShaderDataType : unsigned char; -} - -namespace GTSL { - class Vector2; -} - -class StaticMeshResourceManager final : public ResourceManager -{ -public: - StaticMeshResourceManager(const InitializeInfo&); - ~StaticMeshResourceManager(); - - struct StaticMeshInfo : SData { - struct SubMeshData : SubData { - /** - * \brief Number of vertices the loaded mesh contains. - */ - DEFINE_MEMBER(uint32, VertexCount) - - /** - * \brief Number of indeces the loaded mesh contains. Every face can only have three indeces. - */ - DEFINE_MEMBER(uint32, IndexCount) - DEFINE_MEMBER(uint32, MaterialIndex) - DEFINE_MEMBER(GTSL::Vector3, BoundingBox) - DEFINE_MEMBER(float32, BoundingRadius) - DEFINE_MEMBER(GTSL::ShortString<32>, ShaderGroupName); - }; - - DEFINE_MEMBER(uint32, VertexCount) - DEFINE_MEMBER(uint32, IndexCount) - - /** - * \brief Size of a single index to determine whether to use uint16 or uint32. - */ - DEFINE_MEMBER(uint8, IndexSize) - DEFINE_MEMBER(GTSL::Vector3, BoundingBox) - DEFINE_MEMBER(float32, BoundingRadius) - Array, 8> VertexDescriptor; - DEFINE_ARRAY_MEMBER(SubMeshData, SubMeshes, 16) - DEFINE_MEMBER(bool, Interleaved) - - Array, 8>& GetVertexDescriptor() { return VertexDescriptor; } - const auto& GetVertexDescriptor() const { return VertexDescriptor; } - - uint32 GetVertexSize() const { - uint32 size = 0; - - for (auto& element : GetVertexDescriptor().array) { - size += GAL::GraphicsPipeline::GetVertexSize(element); - } - - return size; - } - }; - - template - void LoadStaticMeshInfo(ApplicationManager* gameInstance, GTSL::StringView meshName, TaskHandle dynamicTaskHandle, ARGS&&... args) { - gameInstance->EnqueueTask(gameInstance->RegisterTask(this, u8"StaticMeshResourceManager::loadStaticMeshInfo", {}, &StaticMeshResourceManager::loadStaticMeshInfo), GTSL::MoveRef(Id(meshName)), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - - template - void LoadStaticMesh(ApplicationManager* gameInstance, StaticMeshInfo staticMeshInfo, uint32 verticesOffset, GTSL::Range vertexBuffer, uint32 indicesOffset, GTSL::Range indexBuffer, TaskHandle dynamicTaskHandle, ARGS&&... args) { - gameInstance->EnqueueTask(gameInstance->RegisterTask(this, u8"StaticMeshResourceManager::loadStaticMesh", {}, &StaticMeshResourceManager::loadMesh, {}, {}), GTSL::MoveRef(staticMeshInfo), GTSL::MoveRef(verticesOffset), GTSL::MoveRef(vertexBuffer), GTSL::MoveRef(indicesOffset), GTSL::MoveRef(indexBuffer), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - -private: - ResourceFiles resource_files_; - - template - void loadStaticMeshInfo(TaskInfo taskInfo, Id meshName, TaskHandle dynamicTaskHandle, ARGS... args) - { - StaticMeshInfo static_mesh_info; - resource_files_.LoadEntry(GTSL::StringView(meshName), static_mesh_info); - - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(static_mesh_info), GTSL::ForwardRef(args)...); - }; - - template - void loadMesh(TaskInfo taskInfo, StaticMeshInfo staticMeshInfo, uint32 verticesOffset, GTSL::Range vertexBuffer, uint32 indicesOffset, GTSL::Range indexBuffer, TaskHandle dynamicTaskHandle, ARGS... args) - { - auto verticesSize = staticMeshInfo.GetVertexSize() * staticMeshInfo.GetVertexCount(); auto indicesSize = staticMeshInfo.GetIndexSize() * staticMeshInfo.GetIndexCount(); - - BE_ASSERT(vertexBuffer.Bytes() >= verticesSize, u8"") - BE_ASSERT(indexBuffer.Bytes() >= indicesSize, u8"") - - byte* vertices = vertexBuffer.begin(); - byte* indices = indexBuffer.begin(); - - const auto bufferSize = vertexBuffer.Bytes(), verticesThatFitInBuffer = (bufferSize / staticMeshInfo.GetVertexSize()); - - for(auto i = 0u, offsetReadInFile = 0u, accumulatedVertexOffset = 0u; i < staticMeshInfo.GetVertexDescriptor().Length; ++i) { - auto streamSize = GAL::GraphicsPipeline::GetVertexSize(staticMeshInfo.GetVertexDescriptor().array[i]); - resource_files_.LoadData(staticMeshInfo, { staticMeshInfo.GetVertexCount() * streamSize, vertices + accumulatedVertexOffset * verticesThatFitInBuffer + verticesOffset * streamSize }, offsetReadInFile, streamSize * staticMeshInfo.GetVertexCount()); - offsetReadInFile += streamSize * staticMeshInfo.GetVertexCount(); - accumulatedVertexOffset += streamSize; - } - - resource_files_.LoadData(staticMeshInfo, { staticMeshInfo.GetIndexCount() * 2u/*todo: use actual byte offset*/, indexBuffer.begin() + indicesOffset * 2u/*todo: use actual index byte offset*/}, verticesSize, indicesSize); - - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(staticMeshInfo), GTSL::ForwardRef(args)...); - }; - - bool loadMesh(const GTSL::Buffer& sourceBuffer, StaticMeshInfo& meshInfo, GTSL::Buffer& meshDataBuffer, const GTSL::StringView fileExtension); -}; diff --git a/src/ByteEngine/Resources/TextRendering.h b/src/ByteEngine/Resources/TextRendering.h deleted file mode 100644 index c1423072..00000000 --- a/src/ByteEngine/Resources/TextRendering.h +++ /dev/null @@ -1,203 +0,0 @@ -#pragma once - -#include -#include -#include "ByteEngine/Application/AllocatorReferences.h" -#include -#include - -struct LinearBezier -{ - LinearBezier(GTSL::Vector2 a, GTSL::Vector2 b) : Points{ a, b } {} - GTSL::Vector2 Points[2]; -}; - -struct CubicBezier -{ - CubicBezier(GTSL::Vector2 a, GTSL::Vector2 b, GTSL::Vector2 c) : Points{ a, b, c } {} - GTSL::Vector2 Points[3]; -}; - -inline float det(GTSL::Vector2 a, GTSL::Vector2 b) { return a.X() * b.Y() - b.X() * a.Y(); } -// Find vector vi given pixel p=(0,0) and Bezier points b0, b1, b2 -inline GTSL::Vector2 get_distance_vector(GTSL::Vector2 b0, GTSL::Vector2 b1, GTSL::Vector2 b2) { - float a = det(b0, b2), b = 2 * det(b1, b0), d = 2 * det(b2, b1); // ab,c(p) - float f = b * d - a * a; // f(p) - - GTSL::Vector2 d21 = b2 - b1, d10 = b1 - b0, d20 = b2 - b0; - - GTSL::Vector2 gf = (d21 * b + d10 * d + d20 * a) * 2.0f; - gf = GTSL::Vector2(gf.Y(), -gf.X()); // delta f(p) - GTSL::Vector2 pp = gf * -f / GTSL::Math::DotProduct(gf, gf); // p' - GTSL::Vector2 d0p = b0 - pp; // p' to origin - float ap = det(d0p, d20), bp = 2 * det(d10, d0p); // a,b(p') - // (note that 2*ap+bp+dp=2*a+b+d=4*area(b0,b1,b2)) - float t = GTSL::Math::Clamp((ap + bp) / (2 * a + b + d), 0.0f, 1.0f); // t- - return GTSL::Math::Lerp(GTSL::Math::Lerp(b0, b1, t), GTSL::Math::Lerp(b1, b2, t), t); // vi = bc(t-) -} - -struct Band -{ - GTSL::Vector Lines; - GTSL::Vector Curves; - - Band(const BE::PAR& allocator) : Lines(allocator), Curves(allocator) {} -}; - -struct Face -{ - GTSL::Vector LinearBeziers; - GTSL::Vector CubicBeziers; - - GTSL::Vector Bands; - - Face(const BE::PAR& allocator) : LinearBeziers(allocator), CubicBeziers(allocator), Bands(allocator) {} -}; - -//Lower index bands represent lower Y locations -//Fonts are in the range 0 <-> 1 -//inline void MakeFromPaths(const GTSL::Glyph& glyph, Face& face, const uint16 bands, const BE::PAR& allocator) -//{ -// auto minBBox = glyph.BoundingBox[0]; auto maxBBox = glyph.BoundingBox[1]; -// -// for (const auto& path : glyph.Paths) { -// for (const auto& segment : path) { -// if (segment.IsBezierCurve()) { -// GTSL::Vector2 postPoints[3]; -// -// postPoints[0] = GTSL::Math::MapToRange(segment.Points[0], minBBox, maxBBox, GTSL::Vector2(0.0f, 0.0f), GTSL::Vector2(1.0f, 1.0f)); -// postPoints[1] = GTSL::Math::MapToRange(segment.Points[1], minBBox, maxBBox, GTSL::Vector2(0.0f, 0.0f), GTSL::Vector2(1.0f, 1.0f)); -// postPoints[2] = GTSL::Math::MapToRange(segment.Points[2], minBBox, maxBBox, GTSL::Vector2(0.0f, 0.0f), GTSL::Vector2(1.0f, 1.0f)); -// -// face.CubicBeziers.EmplaceBack(postPoints[0], postPoints[1], postPoints[2]); -// } -// else { -// GTSL::Vector2 postPoints[2]; -// -// postPoints[0] = GTSL::Math::MapToRange(segment.Points[0], minBBox, maxBBox, GTSL::Vector2(0.0f, 0.0f), GTSL::Vector2(1.0f, 1.0f)); -// postPoints[1] = GTSL::Math::MapToRange(segment.Points[2], minBBox, maxBBox, GTSL::Vector2(0.0f, 0.0f), GTSL::Vector2(1.0f, 1.0f)); -// -// face.LinearBeziers.EmplaceBack(postPoints[0], postPoints[1]); -// } -// } -// } -// -// for (uint16 i = 0; i < bands; ++i) { -// face.Bands.EmplaceBack(allocator); -// } -// -// auto GetBandsForLinear = [&](const LinearBezier& linearBezier, uint16& from, uint16& to) -> void { -// auto height = 1.0f / static_cast(bands); -// auto min = 0.0f; auto max = height; -// -// from = GTSL::Math::Clamp(uint16(linearBezier.Points[0].Y() * static_cast(bands)), uint16(0), uint16(bands - 1)); -// to = GTSL::Math::Clamp(uint16(linearBezier.Points[1].Y() * static_cast(bands)), uint16(0), uint16(bands - 1)); -// }; -// -// auto GetBandsForCubic = [&](const CubicBezier& cubicBezier, uint16& from, uint16& to) -> void { -// auto height = 1.0f / static_cast(bands); -// auto min = 0.0f; auto max = height; -// -// from = GTSL::Math::Clamp(uint16(cubicBezier.Points[0].Y() * static_cast(bands)), uint16(0), uint16(bands - 1)); -// to = GTSL::Math::Clamp(uint16(cubicBezier.Points[2].Y() * static_cast(bands)), uint16(0), uint16(bands - 1)); -// }; -// -// for (uint16 l = 0; l < face.LinearBeziers.GetLength(); ++l) { -// uint16 from, to; -// GetBandsForLinear(face.LinearBeziers[l], from, to); GTSL::Math::MinMax(from, to, from, to); -// for (uint16 b = from; b < to + 1; ++b) { face.Bands[b].Lines.EmplaceBack(l); } -// } -// -// for (uint16 c = 0; c < face.CubicBeziers.GetLength(); ++c) { -// uint16 from, to; -// GetBandsForCubic(face.CubicBeziers[c], from, to); GTSL::Math::MinMax(from, to, from, to); -// for (uint16 b = from; b < to + 1; ++b) { face.Bands[b].Curves.EmplaceBack(c); } -// } -//} - -//float32 Eval(GTSL::Vector2 point, GTSL::Vector2 iResolution, uint16 ch) -//{ -// constexpr auto AA_LENGTH = 0.001f; constexpr uint16 BANDS = 4; -// -// auto getBandIndex = [](const GTSL::Vector2 pos) { -// return GTSL::Math::Clamp(static_cast(pos.Y() * static_cast(BANDS)), static_cast(0), uint16(BANDS - 1)); -// }; -// -// auto face = Face({}); -// -// auto& band = face.Bands[getBandIndex(point)]; -// -// float32 result = 0.0f; float32 lowestLength = 100.0f; -// -// for(uint8 i = 0; i < band.Lines.GetLength(); ++i) -// { -// auto line = face.LinearBeziers[band.Lines[i]]; -// -// GTSL::Vector2 min, max; -// -// GTSL::Math::MinMax(line.Points[0], line.Points[1], min, max); -// -// if(GTSL::Math::PointInBoxProjection(min, max, point)) { -// float32 isOnSegment; -// auto pointLine = GTSL::Math::ClosestPointOnLineSegmentToPoint(line.Points[0], line.Points[1], point, isOnSegment); -// auto dist = GTSL::Math::LengthSquared(point, pointLine); -// -// if(dist < lowestLength) { -// lowestLength = dist; -// auto side = GTSL::Math::TestPointToLineSide(line.Points[0], line.Points[1], point) > 0.0f ? 1.0f : 0.0f; -// result = GTSL::Math::MapToRange(GTSL::Math::Clamp(lowestLength, 0.0f, AA_LENGTH), 0.0f, AA_LENGTH, 0.0f, 1.0f) * side; -// //result = GTSL::Math::TestPointToLineSide(line.Points[0], line.Points[1], point) >= 0.0f ? 1.0f : 0.0f; -// } -// } -// } -// -// { -// GTSL::Vector2 closestAB, closestBC; -// -// for(uint8 i = 0; i < band.Curves.GetLength(); ++i) -// { -// const auto& curve = face.CubicBeziers[band.Curves[i]]; -// -// GTSL::Vector2 min, max; -// -// GTSL::Math::MinMax(curve.Points[0], curve.Points[2], min, max); -// -// if(GTSL::Math::PointInBoxProjection(min, max, point)) -// { -// float32 dist = 100.0f; -// -// constexpr uint16 LOOPS = 32; float32 bounds[2] = { 0.0f, 1.0f }; -// -// uint8 sideToAdjust = 0; -// -// for (uint32 l = 0; l < LOOPS; ++l) -// { -// for (uint8 i = 0, ni = 1; i < 2; ++i, --ni) -// { -// auto t = GTSL::Math::Lerp(bounds[0], bounds[1], static_cast(i) / 1.0f); -// auto ab = GTSL::Math::Lerp(curve.Points[0], curve.Points[1], t); -// auto bc = GTSL::Math::Lerp(curve.Points[1], curve.Points[2], t); -// auto pos = GTSL::Math::Lerp(ab, bc, t); -// auto newDist = GTSL::Math::LengthSquared(pos, point); -// -// if (newDist < dist) { sideToAdjust = ni; dist = newDist; closestAB = ab; closestBC = bc; } -// } -// -// bounds[sideToAdjust] = (bounds[0] + bounds[1]) / 2.0f; -// } -// -// if (dist < lowestLength) -// { -// lowestLength = dist; -// -// auto side = GTSL::Math::TestPointToLineSide(closestAB, closestBC, point) > 0.0f ? 1.0f : 0.0f; -// result = GTSL::Math::MapToRange(GTSL::Math::Clamp(lowestLength, 0.0f, AA_LENGTH), 0.0f, AA_LENGTH, 0.0f, 1.0f) * side; -// -// //result = GTSL::Math::TestPointToLineSide(closestAB, closestBC, point) >= 0.0f ? 1.0f : 0.0f; -// } -// } -// } -// } -// -// return result; -//} \ No newline at end of file diff --git a/src/ByteEngine/Resources/TextureResourceManager.cpp b/src/ByteEngine/Resources/TextureResourceManager.cpp deleted file mode 100644 index 81645f5c..00000000 --- a/src/ByteEngine/Resources/TextureResourceManager.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "TextureResourceManager.h" - -#include - -#include -#include - -#define STB_IMAGE_IMPLEMENTATION -//#define STBI_NO_STDIO -//#define STBI_NO_GIF -#include "stb_image.h" - -#undef Extract - -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Render/ShaderGenerator.h" - -bool FindString(const GTSL::StringView string, const GTSL::StringView match) { - for(auto e = string.begin(); e != string.end(); ++e) { - uint32 i = 0; - - for (auto f = match.begin(); f != match.end() && *f == *e && e != string.end(); ++f, ++e) { ++i; } - - if (i == match.GetCodepoints()) { return true; } - } - - return false; -} - -TextureResourceManager::TextureResourceManager(const InitializeInfo& initialize_info) : ResourceManager(initialize_info, u8"TextureResourceManager") { - GTSL::String indexFileString(5192, GetTransientAllocator()); - auto serializer = GTSL::MakeSerializer(indexFileString); - GTSL::StartArray(serializer, indexFileString, u8"textures"); - - resource_files_.Start(GetResourcePath(u8"Textures")); - - GTSL::FileQuery file_query(GetUserResourcePath(u8"*")); - - while (auto queryResult = file_query()) { - auto fileName = queryResult.Get(); RTrimLast(fileName, u8'.'); - auto fileExtension = queryResult.Get(); LTrimFirst(fileExtension, u8'.'); - - if(!IsAnyOf(fileExtension, u8"png", u8"jpg")) { continue; } - - const auto hashed_name = GTSL::Id64(fileName); - - GAL::ColorSpaces colorSpace = GAL::ColorSpaces::LINEAR; - - if (!resource_files_.Exists(hashed_name)) { - GTSL::File query_file; - query_file.Open(GetUserResourcePath(queryResult.Get()), GTSL::File::READ, false); - - GTSL::Buffer textureFileBuffer(GetTransientAllocator()); - query_file.Read(textureFileBuffer); - - int32 x = 0, y = 0, channel_count = 0; - stbi_info_from_memory(textureFileBuffer.GetData(), textureFileBuffer.GetLength(), &x, &y, &channel_count); - auto finalChannelCount = GTSL::NextPowerOfTwo(static_cast(channel_count)); - byte* data = nullptr; - - { - GTSL::StaticVector, 8> substrings; - - GTSL::Substrings(queryResult.Get(), substrings, U'.'); - - for(auto& e : substrings) { - switch (GTSL::Hash(e)) { - break; case GTSL::Hash(u8"png"): - case GTSL::Hash(u8"jpg"): { - data = stbi_load_from_memory(textureFileBuffer.GetData(), textureFileBuffer.GetLength(), &x, &y, &channel_count, finalChannelCount); - - if(FindString(queryResult.Get(), u8"diff") or FindString(queryResult.Get(), u8"COL")) { - colorSpace = GAL::ColorSpaces::SRGB_NONLINEAR; - } else { - colorSpace = GAL::ColorSpaces::LINEAR; - } - - //for(uint32 i = 0; i < x * y; ++i) { - // for (uint32 j = 0; j < finalChannelCount; ++j) { - // data[i * finalChannelCount + j] = static_cast(GTSL::Math::Power(static_cast(data[i * finalChannelCount + j]) / 255.0f, 2.2f) * 255.0f); - // } - //} - - } - break; case GTSL::Hash(u8"hdr"): { - data = reinterpret_cast(stbi_loadf_from_memory(textureFileBuffer.GetData(), textureFileBuffer.GetLength(), &x, &y, &channel_count, finalChannelCount)); - colorSpace = GAL::ColorSpaces::LINEAR; - } - } - } - - if(FindString(queryResult.Get(), u8"GLOSS")) { // If texture is a gloss texture, convert to roughness - for(uint32 i = 0; i < x * y * finalChannelCount; ++i) { - data[i] = static_cast(GTSL::Math::InvertRange(static_cast(data[i]), 255u)); - } - } - } - - TextureInfo texture_info; - - texture_info.Format = GAL::FormatDescriptor(GAL::ComponentType::INT, finalChannelCount, 8, GAL::TextureType::COLOR, finalChannelCount > 0 ? 0 : 0, finalChannelCount > 1 ? 1 : 0, finalChannelCount > 2 ? 2 : 0, finalChannelCount > 3 ? 3 : 0, colorSpace); - const uint32 size = static_cast(x) * y * finalChannelCount; - texture_info.Extent = { static_cast(x), static_cast(y), 1 }; - - //GTSL::StartObject(serializer, indexFileString); - // GTSL::Insert(serializer, indexFileString, u8"name", fileName); - // GTSL::Insert(serializer, indexFileString, u8"format", GTSL::StringView(u8"INT_4_8_C_0123")); - // GTSL::StartArray(serializer, indexFileString, u8"extent"); - // GTSL::Insert(serializer, indexFileString, x); - // GTSL::Insert(serializer, indexFileString, y); - // GTSL::Insert(serializer, indexFileString, 1); - // GTSL::EndArray(serializer, indexFileString); - //GTSL::EndObject(serializer, indexFileString); - - resource_files_.AddEntry(fileName, &texture_info, { size, static_cast(data) }); - - stbi_image_free(data); - } - } -} - -TextureResourceManager::~TextureResourceManager() -{ -} \ No newline at end of file diff --git a/src/ByteEngine/Resources/TextureResourceManager.h b/src/ByteEngine/Resources/TextureResourceManager.h deleted file mode 100644 index 830ffa4b..00000000 --- a/src/ByteEngine/Resources/TextureResourceManager.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "ResourceManager.h" - -#include -#include -#include -#include -#include - -#include "ByteEngine/Game/ApplicationManager.h" - -class TextureResourceManager final : public ResourceManager -{ -public: - TextureResourceManager(const InitializeInfo&); - ~TextureResourceManager(); - - struct TextureInfo : SData { - DEFINE_MEMBER(GTSL::Extent3D, Extent); - DEFINE_MEMBER(GAL::FormatDescriptor, Format); - }; - - template - void LoadTextureInfo(ApplicationManager* gameInstance, Id textureName, TaskHandle dynamicTaskHandle, ARGS&&... args) { - gameInstance->EnqueueTask(gameInstance->RegisterTask(this, u8"loadTextureInfo", {}, &TextureResourceManager::loadTextureInfo, {}, {}), GTSL::MoveRef(textureName), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - - template - void LoadTexture(ApplicationManager* gameInstance, TextureInfo textureInfo, GTSL::Range buffer, TaskHandle dynamicTaskHandle, ARGS&&... args) { - gameInstance->EnqueueTask(gameInstance->RegisterTask(this, u8"loadTexture", {}, &TextureResourceManager::loadTexture, {}, {}), GTSL::MoveRef(textureInfo), GTSL::MoveRef(buffer), GTSL::MoveRef(dynamicTaskHandle), GTSL::ForwardRef(args)...); - } - -private: - template - void loadTextureInfo(TaskInfo taskInfo, Id textureName, TaskHandle dynamicTaskHandle, ARGS... args) { - TextureInfo textureInfo; - resource_files_.LoadEntry(GTSL::StringView(textureName), textureInfo); - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(textureInfo), GTSL::ForwardRef(args)...); - }; - - template - void loadTexture(TaskInfo taskInfo, TextureInfo textureInfo, GTSL::Range buffer, TaskHandle dynamicTaskHandle, ARGS... args) { - resource_files_.LoadData(textureInfo, buffer); - taskInfo.AppManager->EnqueueTask(dynamicTaskHandle, GTSL::MoveRef(textureInfo), GTSL::ForwardRef(args)...); - }; - - ResourceFiles resource_files_; -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/UIPermutation.hpp b/src/ByteEngine/Resources/UIPermutation.hpp deleted file mode 100644 index b039a647..00000000 --- a/src/ByteEngine/Resources/UIPermutation.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "PermutationManager.hpp" -#include "ByteEngine/Render/ShaderGenerator.h" - -class UIPermutation : public PermutationManager { -public: - UIPermutation(const GTSL::StringView instance_name) : PermutationManager(instance_name, u8"UIPermutation") { - AddSupportedDomain(u8"UI"); - } - - void Initialize(GPipeline* pipeline, ShaderGenerationData& shader_generation_data) override { - uiScope = pipeline->DeclareScope(GPipeline::GLOBAL_SCOPE, u8"UIPermutation"); - - pipeline->DeclareStruct(uiScope, u8"TextData", UI_TEXT_DATA); - pipeline->DeclareStruct(uiScope, u8"LinearSegment", UI_LINEAR_SEGMENT); - pipeline->DeclareStruct(uiScope, u8"QuadraticSegment", UI_QUADRATIC_SEGMENT); - pipeline->DeclareStruct(uiScope, u8"GlyphContourData", UI_GLYPH_CONTOUR_DATA); - pipeline->DeclareStruct(uiScope, u8"GlyphData", UI_GLYPH_DATA); - pipeline->DeclareStruct(uiScope, u8"FontData", UI_FONT_DATA); - pipeline->DeclareStruct(uiScope, u8"UIData", UI_DATA); - pipeline->DeclareStruct(uiScope, u8"UIInstanceData", UI_INSTANCE_DATA); - pipeline->DeclareStruct(uiScope, u8"UIRes", UI_RES); - - // No vertex declaration as we have no incoming data - AddVertexSurfaceInterfaceBlockDeclaration(pipeline, uiScope, { {u8"vec2f", u8"vertexPos"}, {u8"vec2f", u8"vertexUV"}, {u8"uint32", u8"instanceIndex"} }); - uiRenderPassScopeHandle = pipeline->DeclareStruct(uiScope, u8"RenderPassData", { { u8"TextureReference", u8"Color" } }); - - { - auto fragmentOutputBlockHandle = pipeline->DeclareScope(uiScope, u8"fragmentOutputBlock"); - auto outColorHandle = pipeline->DeclareVariable(fragmentOutputBlockHandle, { u8"vec4f", u8"out_Color" }); - pipeline->AddMemberDeductionGuide(uiScope, u8"surfaceColor", { outColorHandle }); - } - - pipeline->DeclareFunction(uiScope, u8"vec4f", u8"GetVertexPosition", {}, u8"return vec4(vertexPos, 0, 1);"); - pipeline->DeclareFunction(uiScope, u8"vec2f", u8"GetVertexTextureCoordinates", {}, u8"return vertexUV;"); - - auto closestPointOnLineSegmentToPointHandle = pipeline->DeclareFunction(uiScope, u8"vec2f", u8"ClosestPointOnLineSegmentToPoint", { { u8"vec2f", u8"a" }, { u8"vec2f", u8"b" }, { u8"vec2f", u8"p" } }, u8"const vec2f AB = b - a; float32 t = dot(AB, p - a) / dot(AB, AB); return a + AB * clamp(t, 0.0f, 1.0f);"); - - auto testPointToLineSideFunctionHandle = pipeline->DeclareFunction(uiScope, u8"float32", u8"TestPointToLineSide", { { u8"vec2f", u8"a" }, { u8"vec2f", u8"b" }, { u8"vec2f", u8"p" } }, u8"return ((a.x - b.x) * (p.y - b.y) - (a.y - b.y) * (p.x - b.x));"); - - auto solveLinearSegmentFunctionHandle = pipeline->DeclareFunction(uiScope, u8"UIRes", u8"SolveLinearSegment", { { u8"float32", u8"distance" }, { u8"LinearSegment", u8"segment" }, { u8"vec2f", u8"a" }, { u8"vec2f", u8"b" }, { u8"vec2f", u8"point" } }, u8"vec2f p = ClosestPointOnLineSegmentToPoint(segment.segments[0], segment.segments[1], point); float32 l = length(p - point); if(l < distance) { return UIRes(l, segment.segments[0], segment.segments[1]); } return UIRes(distance, a, b);"); - - auto solveQuadraticSegmentFunctionHandle = pipeline->DeclareFunction(uiScope, u8"UIRes", u8"SolveQuadraticSegment", { { u8"float32", u8"distance" }, { u8"QuadraticSegment", u8"segment" }, { u8"vec2f", u8"a" }, { u8"vec2f", u8"b" }, { u8"vec2f", u8"point" } }); - - pipeline->AddCodeToFunction(solveQuadraticSegmentFunctionHandle, u8"vec2f abl[2] = vec2f[2](vec2f(0), vec2f(0)); float32 dist = 100.0f; const uint32 LOOPS = 32; float32 bounds[2] = float32[](0.0f, 1.0f); uint32 sideToAdjust = 0; for (uint32 l = 0; l < LOOPS; ++l) { for (uint32 i = 0, ni = 1; i < 2; ++i, --ni) { float32 t = mix(bounds[0], bounds[1], float32(i) / 1.0f); vec2f ab = mix(segment.segments[0], segment.segments[1], t); vec2f bc = mix(segment.segments[1], segment.segments[2], t); vec2f pos = mix(ab, bc, t); abl[0] = ab; abl[1] = bc; float32 newDist = length(pos - point); if (newDist < dist) { sideToAdjust = ni; dist = newDist; } } bounds[sideToAdjust] = (bounds[0] + bounds[1]) / 2.0f; } if(dist < distance) { return UIRes(dist, abl[0], abl[1]); } return UIRes(distance, a, b);"); - } - -private: - GPipeline::ElementHandle uiScope, uiRenderPassScopeHandle; -}; \ No newline at end of file diff --git a/src/ByteEngine/Resources/VisibilityPermutation.hpp b/src/ByteEngine/Resources/VisibilityPermutation.hpp deleted file mode 100644 index bc9749b8..00000000 --- a/src/ByteEngine/Resources/VisibilityPermutation.hpp +++ /dev/null @@ -1,377 +0,0 @@ -#pragma once - -#include "PermutationManager.hpp" -#include "ByteEngine/Render/Culling.h" - -struct VisibilityRenderPassPermutation : PermutationManager { - VisibilityRenderPassPermutation(const GTSL::StringView instance_name) : PermutationManager(instance_name, u8"VisibilityRenderPassPermutation") { - AddTag(u8"RenderTechnique", u8"Visibility"); - - AddSupportedDomain(u8"Visibility"); - AddSupportedDomain(u8"CountPixels"); - AddSupportedDomain(u8"PrefixPass"); - AddSupportedDomain(u8"SelectPixels"); - AddSupportedDomain(u8"World"); - } - - void Initialize(GPipeline* pipeline, ShaderGenerationData& shader_generation_data) override { - visibilityHandle = pipeline->DeclareScope(shader_generation_data.Scopes.back(), u8"Visibility"); - - pipeline->DeclareStruct(visibilityHandle, u8"renderPassData", { { u8"ImageReference", u8"Visibility" }, { u8"ImageReference", u8"Depth"} }); - - shader_generation_data.Scopes.EmplaceBack(visibilityHandle); - - pipeline->SetMakeStruct(pipeline->DeclareStruct(visibilityHandle, u8"BarycentricDeriv", { { u8"vec3f", u8"m_lambda" }, { u8"vec3f", u8"m_ddx" }, { u8"vec3f", u8"m_ddy" } })); - pipeline->SetMakeStruct(pipeline->DeclareStruct(visibilityHandle, u8"Derivatives", { { u8"vec3f", u8"db_dx" }, { u8"vec3f", u8"db_dy" } })); - pipeline->DeclareFunction(visibilityHandle, u8"BarycentricDeriv", u8"CalcFullBary", { { u8"vec4f", u8"pt0" }, { u8"vec4f", u8"pt1" }, { u8"vec4f", u8"pt2" }, { u8"vec2f", u8"pixelNdc" }, { u8"vec2f", u8"winSize" } }, u8"BarycentricDeriv ret; vec3f invW = vec3f(1) / vec3f(pt0.w, pt1.w, pt2.w); vec2f ndc0 = pt0.xy * invW.x; vec2f ndc1 = pt1.xy * invW.y; vec2f ndc2 = pt2.xy * invW.z; float32 invDet = 1.0f / determinant(mat2f(ndc2 - ndc1, ndc0 - ndc1)); ret.m_ddx = vec3f(ndc1.y - ndc2.y, ndc2.y - ndc0.y, ndc0.y - ndc1.y) * invDet; ret.m_ddy = vec3f(ndc2.x - ndc1.x, ndc0.x - ndc2.x, ndc1.x - ndc0.x) * invDet; vec2f deltaVec = pixelNdc - ndc0; float32 interpInvW = (invW.x + deltaVec.x * dot(invW, ret.m_ddx) + deltaVec.y * dot(invW, ret.m_ddy)); float32 interpW = 1.0f / interpInvW; ret.m_lambda.x = interpW * (invW[0] + deltaVec.x * ret.m_ddx.x * invW[0] + deltaVec.y * ret.m_ddy.x * invW[0]); ret.m_lambda.y = interpW * (0.0f + deltaVec.x * ret.m_ddx.y * invW[1] + deltaVec.y * ret.m_ddy.y * invW[1]); ret.m_lambda.z = interpW * (0.0f + deltaVec.x * ret.m_ddx.z * invW[2] + deltaVec.y * ret.m_ddy.z * invW[2]); ret.m_ddx *= (2.0f / winSize.x); ret.m_ddy *= (2.0f / winSize.y); ret.m_ddy *= -1.0f; return ret;"); - pipeline->DeclareFunction(visibilityHandle, u8"vec3f", u8"InterpolateWithDeriv", { { u8"BarycentricDeriv", u8"deriv" }, { u8"vec3f", u8"mergedV" } }, u8"vec3f ret; ret.x = dot(deriv.m_lambda, mergedV); ret.y = dot(deriv.m_ddx * mergedV, vec3f(1, 1, 1)); ret.z = dot(deriv.m_ddy * mergedV, vec3f(1, 1, 1)); return ret;"); - - pipeline->DeclareFunction(visibilityHandle, u8"Derivatives", u8"ComputePartialDerivatives", { { u8"vec2f[3]", u8"v" } }, u8"Derivatives result; float32 d = 1.0f / determinant(mat2f(v[2] - v[1], v[0] - v[1])); result.db_dx = vec3f(v[1].y - v[2].y, v[2].y - v[0].y, v[0].y - v[1].y) * d; result.db_dy = vec3f(v[2].x - v[1].x, v[0].x - v[2].x, v[1].x - v[0].x) * d; return result;"); - - pipeline->DeclareFunction(visibilityHandle, u8"float32", u8"InterpolateAttribute", { { u8"vec3f", u8"attributes" }, { u8"vec3f", u8"db_dx" }, { u8"vec3f", u8"db_dy" }, { u8"vec2f", u8"d" } }, u8"float attribute_x = dot(attributes, db_dx); float attribute_y = dot(attributes, db_dy); float attribute_s = attributes[0]; return (attribute_s + d.x * attribute_x + d.y * attribute_y);"); - - pipeline->DeclareFunction(visibilityHandle, u8"vec3f", u8"InterpolateAttribute", { { u8"mat3f", u8"attributes" }, { u8"vec3f", u8"db_dx" }, { u8"vec3f", u8"db_dy" }, { u8"vec2f", u8"d" } }, u8"vec3f attribute_x = db_dx * attributes; vec3f attribute_y = db_dy * attributes; vec3f attribute_s = attributes[0]; return (attribute_s + d.x * attribute_x + d.y * attribute_y);"); - - pipeline->SetMakeStruct(pipeline->DeclareStruct(visibilityHandle, u8"PointLightData", { { u8"vec3f", u8"position" }, {u8"float32", u8"radius"} })); - pipeline->DeclareStruct(visibilityHandle, u8"LightingData", { {u8"uint32", u8"pointLightsLength"}, {u8"PointLightData[4]", u8"pointLights"} }); - - pipeline->DeclareStruct(visibilityHandle, u8"VisibilityData", { { u8"vec3f*", u8"positionStream" }, { u8"vec3f*", u8"normalStream" }, { u8"vec3f*", u8"tangentStream" }, { u8"vec3f*", u8"bitangentStream" }, { u8"vec2f*", u8"textureCoordinatesStream" }, {u8"uint32", u8"shaderGroupLength"}, {u8"uint32[256]", u8"shaderGroupUseCount"}, {u8"uint32[256]", u8"shaderGroupStart" } , { u8"IndirectDispatchCommand[256]", u8"indirectBuffer" }, {u8"vec2s*", u8"pixelBuffer"}}); - - simplePushConstant = pipeline->DeclareScope(visibilityHandle, u8"pushConstantBlock"); - pipeline->DeclareVariable(simplePushConstant, { u8"GlobalData*", u8"global" }); - pipeline->DeclareVariable(simplePushConstant, { u8"renderPassData*", u8"renderPass" }); - auto instancesPointerHandle = pipeline->DeclareVariable(simplePushConstant, { u8"InstanceData*", u8"instances" }); - auto visibilityDataHandle = pipeline->DeclareVariable(simplePushConstant, { u8"VisibilityData*", u8"visibility" }); - - { //visibility pass - visibilityPass = pipeline->DeclareScope(shader_generation_data.Scopes.back(), u8"VisibilityPass"); - - pipeline->DeclareFunction(visibilityHandle, u8"mat4f", u8"GetInstancePosition", {}, u8"return mat4(pushConstantBlock.instances[gl_InstanceIndex].ModelMatrix);"); - pipeline->DeclareFunction(visibilityHandle, u8"uint32", u8"GetVertexIndex", {}, u8"return gl_VertexIndex;"); - - auto vertexBlock = pipeline->DeclareScope(visibilityPass, u8"vertex"); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"POSITION" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"NORMAL" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"TANGENT" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec3f", u8"BITANGENT" }); - pipeline->DeclareVariable(vertexBlock, { u8"vec2f", u8"TEXTURE_COORDINATES" }); - } - - { //count pixels pass - countShaderGroupsShader = pipeline->DeclareShader(shader_generation_data.Scopes.back(), u8"CountShaderGroups"); - - pipeline->AddMemberDeductionGuide(countShaderGroupsShader, u8"visibility", { simplePushConstant, visibilityDataHandle, }); - pipeline->AddMemberDeductionGuide(countShaderGroupsShader, u8"instances", { simplePushConstant, instancesPointerHandle }); - - // Count how many pixels contain each shader group - pipeline->DeclareFunction(countShaderGroupsShader, u8"void", u8"main", {}, u8"uint32 shaderGroupIndex = instances[SampleUint(pushConstantBlock.renderPass.visibility).r].shaderGroupIndex; atomicAdd(visibility.shaderGroupUseCount[shaderGroupIndex].a, 1);"); - //execution = windowExtent - } - - { //prefix sum pass - prefixSumShader = pipeline->DeclareShader(shader_generation_data.Scopes.back(), u8"PrefixSum"); - - pipeline->DeclareFunction(prefixSumShader, u8"void", u8"main", {}, u8"uint32 sum = 0; for(uint32 i = 0; i < pushConstantBlock.visibility.shaderGroupLength; ++i) { pushConstantBlock.visibility.shaderGroupStart[i].a = sum; sum += pushConstantBlock.visibility.shaderGroupUseCount[i].a; pushConstantBlock.visibility.indirectBuffer[i].width = pushConstantBlock.visibility.shaderGroupUseCount[i].a; }"); - } - - { //select pixels pass - buildPixelBufferShader = pipeline->DeclareShader(shader_generation_data.Scopes.back(), u8"BuildPixelBuffer"); - - pipeline->AddMemberDeductionGuide(buildPixelBufferShader, u8"visibility", { simplePushConstant, visibilityDataHandle, }); - - // For every pixel on the screen determine which shader group is visible and append the current pixel coordinate to a per shader group list of pixels that need to be shaded - pipeline->DeclareFunction(buildPixelBufferShader, u8"void", u8"main", {}, u8"visibility.pixelBuffer[atomicAdd(visibility.shaderGroupStart[pushConstantBlock.instances[SampleUint(pushConstantBlock.renderPass.visibility).r].shaderGroupIndex].a, 1)] = vec2s(GetGlobalIndex());"); - //execution = windowExtent - } - - { //paint pass - paintPass = pipeline->DeclareScope(shader_generation_data.Scopes.back(), u8"PaintPass"); - - paintPushConstant = pipeline->DeclareScope(paintPass, u8"pushConstantBlock"); - pipeline->DeclareVariable(paintPushConstant, { u8"GlobalData*", u8"global" }); - pipeline->DeclareVariable(paintPushConstant, { u8"CameraData*", u8"camera" }); - pipeline->DeclareVariable(paintPushConstant, { u8"renderPassData*", u8"renderPass" }); - pipeline->DeclareVariable(paintPushConstant, { u8"LightingData*", u8"lightingData" }); - pipeline->DeclareVariable(paintPushConstant, { u8"InstanceData*", u8"instances" }); - - pipeline->DeclareFunction(paintPass, u8"vec4f", u8"RandomColorFromUint", { { u8"uint32", u8"index" } }, u8"vec3f table[8] = vec3f[8](vec3f(0, 0.9, 0.4), vec3f(0, 0.2, 0.9), vec3f(1, 0.3, 1), vec3f(0.1, 0, 0.9), vec3f(1, 0.5, 0.1), vec3f(0.5, 0.4, 0.4), vec3f(1, 1, 0), vec3f(1, 0, 0)); return vec4f(table[index % 8], 1);"); - } - - const CommonPermutation* common_permutation = Find(u8"CommonPermutation", shader_generation_data.Hierarchy); - - if (common_permutation) { - pipeline->DeclareFunction(visibilityHandle, u8"vec3f", u8"GetCameraPosition", {}, u8"return vec3f(pushConstantBlock.camera.worldPosition);"); - - auto vertexSurfaceInterface = pipeline->DeclareScope(visibilityHandle, u8"vertexSurfaceInterface"); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"uint32", u8"instanceIndex" }); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"uint32", u8"triangleIndex" }); - - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"vec3f", u8"worldSpacePosition" }); - pipeline->DeclareVariable(vertexSurfaceInterface, { u8"vec3f", u8"worldSpaceNormal" }); - } - else { - BE_LOG_ERROR(u8"Needed CommonPermutation to setup state but not found in hierarchy.") - } - } - - GTSL::Vector MakeShaderGroups(GPipeline* pipeline, GTSL::Range hierarchy) override { - GTSL::Vector results(8, GetTransientAllocator()); - - { //visibility - auto& sg = results.EmplaceBack(); - sg.ShaderGroupJSON = -u8R"({ - "name":"VisibilityShaderGroup", - "instances":[{"name":"Visibility", "parameters":[]}], - "domain":"Visibility" -})"; - } - - { //count shader groups - auto& result = results.EmplaceBack(); - result.ShaderGroupJSON = - u8R"({ - "name":"CountShaderGroups", - "instances":[{"name":"Count", "parameters":[]}], - "domain":"Visibility" -})"; - } - - { //prefix sum - auto& result = results.EmplaceBack(); - result.ShaderGroupJSON = - u8R"({ - "name":"PrefixSum", - "instances":[{"name":"PrefixSum", "parameters":[]}], - "domain":"Visibility" -})"; - } - - { //build pixel buffer - auto& result = results.EmplaceBack(); - result.ShaderGroupJSON = - u8R"({ - "name":"BuildPixelBuffer", - "instances":[{"name":"BuildPixelBuffer", "parameters":[]}], - "domain":"Visibility" -})"; - } - - return { GetTransientAllocator() }; - } - - void ProcessShader(GPipeline* pipeline, GTSL::JSON shader_group_json, GTSL::JSON shader_json, const GTSL::Range hierarchy, GTSL::StaticVector& batches) override { - GTSL::StaticVector shaderParameters; - - if (auto parameters = shader_group_json[u8"parameters"]) { - for (auto p : parameters) { - if (auto def = p[u8"defaultValue"]) { - shaderParameters.EmplaceBack(p[u8"type"], p[u8"name"], def); - } - else { - shaderParameters.EmplaceBack(p[u8"type"], p[u8"name"], u8""); - } - } - } - - auto shaderScope = pipeline->DeclareShader(visibilityHandle, shader_json[u8"name"]); - auto mainFunctionHandle = pipeline->DeclareFunction(shaderScope, u8"void", u8"main"); - - { //add deduction guides for reaching shader parameters - auto shaderParametersStructHandle = pipeline->DeclareStruct(shaderScope, u8"shaderParametersData", shaderParameters); - - for (auto& e : shaderParameters) { - // simplePushConstant will work under all passes, but it's nn ot the correct way to do this - pipeline->AddMemberDeductionGuide(shaderScope, e.Name, { simplePushConstant, shaderParametersHandle, pipeline->GetElementHandle(shaderParametersStructHandle, e.Name) }); - } - - } - - auto& main = pipeline->GetFunction({ shaderScope }, u8"main"); - - switch (Hash(shader_group_json[u8"domain"])) { - case GTSL::Hash(u8"World"): { - auto& batch = batches.EmplaceBack(); - - batch.Tags = GetTagList(); - batch.Scopes.EmplaceBack(GPipeline::GLOBAL_SCOPE); - - const CommonPermutation* common_permutation = Find(u8"CommonPermutation", hierarchy); - batch.Scopes.EmplaceBack(common_permutation->commonScope); - batch.Scopes.EmplaceBack(visibilityHandle); - batch.Scopes.EmplaceBack(visibilityPass); - - switch (Hash(shader_json[u8"class"])) { - case GTSL::Hash(u8"Vertex"): { - batch.TargetSemantics = GAL::ShaderType::VERTEX; - batch.Scopes.EmplaceBack(common_permutation->vertexShaderScope); - batch.Scopes.EmplaceBack(shaderScope); - - tokenizeCode(u8"instanceIndex = gl_InstanceIndex; triangleIndex = gl_VertexIndex / 3;", main.Tokens); - tokenizeCode(u8"worldSpacePosition = vec3f(GetInstancePosition() * GetVertexPosition()); worldSpaceNormal = vec3f(GetInstancePosition() * GetVertexNormal());", main.Tokens, GetPersistentAllocator()); - tokenizeCode(shader_json[u8"code"], main.Tokens, GetPersistentAllocator()); - break; - } - case GTSL::Hash(u8"Surface"): { - batch.TargetSemantics = GAL::ShaderType::COMPUTE; - batch.Scopes.EmplaceBack(common_permutation->computeShaderScope); - batch.Scopes.EmplaceBack(shaderScope); - - tokenizeCode(u8"float32 surfaceRoughness = 1.0f; vec4f surfaceNormal = vec4f(0, 0, -1, 0); vec4f surfaceColor = vec4f(0);", main.Tokens, GetPersistentAllocator()); - tokenizeCode(u8"vec4u pixel = SampleUint(pushConstantBlock.renderPass.Visibility, GetPixelPosition()); uint32 instanceIndex = pixel.r; uint32 triangleIndex = pixel.g;", main.Tokens); - - tokenizeCode(u8"instanceData* instance = pushConstantBlock.instances[instanceIndex];", main.Tokens); - tokenizeCode(u8"u16vec3 indices = index*(pushConstantBlock.visibility.indexBuffer + instance.indexBufferOffset)[triangleIndex].indexTri; vec3f* vertices = pushConstantBlock.visibility.positionStream + instance.vertexBufferOffset; vec3f pos[3] = vec3f[3](vertices[indices[0]].xyz, vertices[indices[1]].xyz, vertices[indices[2]].xyz);", main.Tokens); - tokenizeCode(u8"mat4f mvp = instance.matrix * pushConstantBlock.camera.vp;", main.Tokens); // Calculate MVP matrix - tokenizeCode(u8"vec4f positions[3] = vec4f[3](mvp * float4(pos[0], 1.0f), mvp * float4(pos[1], 1.0f), mvp * float4(pos[2], 1.0f));", main.Tokens); // Transform positions to clip space - tokenizeCode(u8"vec3f oneOverW = vec3f(1.0f) / vec3f(positions[0].w, positions[1].w, positions[2].w);", main.Tokens); // Calculate the inverse of w, since it's going to be used several times - tokenizeCode(u8"positions[0] *= oneOverW[0]; positions[1] *= oneOverW[1]; positions[2] *= oneOverW[2];", main.Tokens); // Project vertex positions to calculate 2D post-perspective positions - tokenizeCode(u8"vec2f screenPosition[3] = vec2f[3](positions[0].xy, positions[1].xy, positions[2].xy);", main.Tokens); - tokenizeCode(u8"Derivatives derivativesOut = ComputePartialDerivatives(screenPosition);", main.Tokens); // Compute partial derivatives. This is necessary to interpolate triangle attributes per pixel. - tokenizeCode(u8"vec2f d = vec2f(GetNormalizedGlobalIndex()) + -screenPosition[0];", main.Tokens); // Calculate delta vector (d) that points from the projected vertex 0 to the current screen point - tokenizeCode(u8"float32 w = 1.0f / InterpolateAttribute(oneOverW, derivativesOut.db_dx, derivativesOut.db_dy, d);", main.Tokens); // Interpolate the 1/w (one_over_w) for all three vertices of the triangle using the barycentric coordinates and the delta vector - tokenizeCode(u8"float z = w * getElem(Get(transform)[VIEW_CAMERA].projection, 2, 2) + getElem(Get(transform)[VIEW_CAMERA].projection, 3, 2);", main.Tokens); // Reconstruct the Z value at this screen point performing only the necessary matrix * vector multiplication operations that involve computing Z - - //tokenizeCode(shader_json[u8"code"], main.Tokens, GetPersistentAllocator()); - //tokenizeCode(u8"vec4f BE_COLOR_0 = surfaceColor; surfaceColor = vec4f(0); for(uint32 i = 0; i < pushConstantBlock.lightingData.pointLightsLength; ++i) { PointLightData l = pushConstantBlock.lightingData.pointLights[i]; surfaceColor += vec4f(light(l.position, GetCameraPosition(), //GetSurfaceWorldSpacePosition(), GetSurfaceWorldSpaceNormal(), vec3f(1) * l.radius, normalize(GetCameraPosition() - GetSurfaceWorldSpacePosition()), vec3f(BE_COLOR_0), vec3f(0.04f), surfaceRoughness), 0.1); }", main.Tokens, GetPersistentAllocator()); - tokenizeCode(u8"Write(pushConstantBlock.renderPass.Color, pushConstantBlock.visibility.pixelBuffer[GetGlobalIndex().x].hw, RandomColorFromUint(triangleIndex));", main.Tokens); - //tokenizeCode(u8"Write(pushConstantBlock.renderPass.Color, GetPixelPosition(), surfaceColor);", main.Tokens); - - batches.PopBack(); - - break; - } - case GTSL::Hash(u8"Miss"): { - batch.TargetSemantics = GAL::ShaderType::COMPUTE; - batch.Scopes.EmplaceBack(common_permutation->computeShaderScope); - batch.Scopes.EmplaceBack(shaderScope); - //todo: emit compute shader for raster - break; - } - default: { - batches.PopBack(); //remove added batch as no shader was created - BE_LOG_ERROR(u8"Can't utilize this shader class in this domain.") - } - } - - break; - } - case GTSL::Hash(u8"CountPixels"): { break; } - case GTSL::Hash(u8"PrefixPass"): { break; } - case GTSL::Hash(u8"SelectPixels"): { break; } - } - } - - void ProcessVisibility(GPipeline* pipeline, GTSL::JSON shader_group_json, GTSL::JSON shader_json, GTSL::Range hierarchy, GTSL::StaticVector& batches) { - GTSL::StaticVector shaderParameters; - - if (auto parameters = shader_group_json[u8"parameters"]) { - for (auto p : parameters) { - if (auto def = p[u8"defaultValue"]) { - shaderParameters.EmplaceBack(p[u8"type"], p[u8"name"], def); - } - else { - shaderParameters.EmplaceBack(p[u8"type"], p[u8"name"], u8""); - } - } - } - - auto shaderScope = pipeline->DeclareShader(visibilityHandle, shader_json[u8"name"]); - auto mainFunctionHandle = pipeline->DeclareFunction(shaderScope, u8"void", u8"main"); - auto& main = pipeline->GetFunction({ shaderScope }, u8"main"); - - { //add deduction guides for reaching shader parameters - auto shaderParametersStructHandle = pipeline->DeclareStruct(shaderScope, u8"shaderParametersData", shaderParameters); - - for (auto& e : shaderParameters) { - pipeline->AddMemberDeductionGuide(shaderScope, e.Name, { simplePushConstant, shaderParametersHandle, pipeline->GetElementHandle(shaderParametersStructHandle, e.Name) }); - } - - } - - auto& batch = batches.EmplaceBack(); - - batch.Tags = GetTagList(); - batch.Scopes.EmplaceBack(GPipeline::GLOBAL_SCOPE); - - const CommonPermutation* common_permutation = Find(u8"CommonPermutation", hierarchy); - batch.Scopes.EmplaceBack(common_permutation->commonScope); - batch.Scopes.EmplaceBack(visibilityHandle); - batch.Scopes.EmplaceBack(visibilityPass); - - switch (Hash(shader_json[u8"class"])) { - case GTSL::Hash(u8"Vertex"): { - batch.TargetSemantics = GAL::ShaderType::VERTEX; - batch.Scopes.EmplaceBack(common_permutation->vertexShaderScope); - batch.Scopes.EmplaceBack(shaderScope); - - tokenizeCode(u8"instanceIndex = gl_InstanceIndex; triangleIndex = gl_VertexIndex;", main.Tokens); - tokenizeCode(u8"worldSpacePosition = vec3f(GetInstancePosition() * GetVertexPosition()); worldSpaceNormal = vec3f(GetInstancePosition() * GetVertexNormal());", main.Tokens, GetPersistentAllocator()); - tokenizeCode(shader_json[u8"code"], main.Tokens, GetPersistentAllocator()); - - break; - } - case GTSL::Hash(u8"Surface"): { - batch.TargetSemantics = GAL::ShaderType::FRAGMENT; - batch.Scopes.EmplaceBack(common_permutation->fragmentShaderScope); - batch.Scopes.EmplaceBack(shaderScope); - - tokenizeCode(shader_json[u8"code"], main.Tokens, GetPersistentAllocator()); - - batches.PopBack(); - - break; - } - default: { - batches.PopBack(); //remove added batch as no shader was created - BE_LOG_ERROR(u8"Can't utilize this shader class in this domain.") - } - } - } - - GPipeline::ElementHandle visibilityHandle, simplePushConstant, paintPushConstant, shaderParametersHandle; - GPipeline::ElementHandle visibilityPass, countShaderGroupsShader, prefixSumShader, buildPixelBufferShader, paintPass; -}; - -inline AABB2 Make2DAABBForAABB(AABB aabb, GTSL::Matrix4& mat) { - GTSL::Vector3 vertices[8]{ aabb }; - - //back plane - vertices[0][0] *= 1; - - vertices[1][1] *= -1; - - vertices[2][0] *= -1; - vertices[2][1] *= -1; - - vertices[3][0] *= -1; - - //front plane - vertices[0][0] *= 1; - - vertices[1][1] *= -1; - - vertices[2][0] *= -1; - vertices[2][1] *= -1; - - vertices[3][0] *= -1; - - vertices[4][2] *= -1; - vertices[5][2] *= -1; - vertices[6][2] *= -1; - vertices[7][2] *= -1; - - float32 maxMagnitude = 0.0f; - GTSL::Vector3 res; - - for(uint32 i = 0; i < 8; ++i) { - auto vec = mat * aabb; - - if (auto mag = GTSL::Math::Length(vec); mag > maxMagnitude) { - maxMagnitude = mag; - res = vec; - } - } - - return { res[0], res[1] }; -} \ No newline at end of file diff --git a/src/ByteEngine/SIMDMath.ixx b/src/ByteEngine/SIMDMath.ixx deleted file mode 100644 index 93cda2f2..00000000 --- a/src/ByteEngine/SIMDMath.ixx +++ /dev/null @@ -1,715 +0,0 @@ -module; - -#include - -export module SIMDMath; - -/* SIMD (SSE1+MMX or SSE2) implementation of sin, cos, exp and log - - Inspired by Intel Approximate Math library, and based on the - corresponding algorithms of the cephes math library - - The default is to use the SSE1 version. If you define USE_SSE2 the - the SSE2 intrinsics will be used in place of the MMX intrinsics. Do - not expect any significant performance improvement with SSE2. -*/ - -/* Copyright (C) 2007 Julien Pommier - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - (this is the zlib license) -*/ - -/* yes I know, the top of this file is quite ugly */ - -#define USE_SSE2 - -#ifdef _MSC_VER /* visual c++ */ -# define ALIGN16_BEG __declspec(align(16)) -# define ALIGN16_END -#else /* gcc or icc */ -# define ALIGN16_BEG -# define ALIGN16_END __attribute__((aligned(16))) -#endif - -/* __m128 is ugly to write */ -typedef __m128 v4sf; // vector of 4 float (sse1) - -#ifdef USE_SSE2 -typedef __m128i v4si; // vector of 4 int (sse2) -#else -typedef __m64 v2si; // vector of 2 int (mmx) -#endif - -/* declare some SSE constants -- why can't I figure a better way to do that? */ -#define _PS_CONST(Name, Val) \ - static const ALIGN16_BEG float _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val } -#define _PI32_CONST(Name, Val) \ - static const ALIGN16_BEG int _pi32_##Name[4] ALIGN16_END = { Val, Val, Val, Val } -#define _PS_CONST_TYPE(Name, Type, Val) \ - static const ALIGN16_BEG Type _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val } - -_PS_CONST(1, 1.0f); -_PS_CONST(0p5, 0.5f); -/* the smallest non denormalized float number */ -_PS_CONST_TYPE(min_norm_pos, int, 0x00800000); -_PS_CONST_TYPE(mant_mask, int, 0x7f800000); -_PS_CONST_TYPE(inv_mant_mask, int, ~0x7f800000); - -_PS_CONST_TYPE(sign_mask, int, (int)0x80000000); -_PS_CONST_TYPE(inv_sign_mask, int, ~0x80000000); - -_PI32_CONST(1, 1); -_PI32_CONST(inv1, ~1); -_PI32_CONST(2, 2); -_PI32_CONST(4, 4); -_PI32_CONST(0x7f, 0x7f); - -_PS_CONST(cephes_SQRTHF, 0.707106781186547524); -_PS_CONST(cephes_log_p0, 7.0376836292E-2); -_PS_CONST(cephes_log_p1, -1.1514610310E-1); -_PS_CONST(cephes_log_p2, 1.1676998740E-1); -_PS_CONST(cephes_log_p3, -1.2420140846E-1); -_PS_CONST(cephes_log_p4, +1.4249322787E-1); -_PS_CONST(cephes_log_p5, -1.6668057665E-1); -_PS_CONST(cephes_log_p6, +2.0000714765E-1); -_PS_CONST(cephes_log_p7, -2.4999993993E-1); -_PS_CONST(cephes_log_p8, +3.3333331174E-1); -_PS_CONST(cephes_log_q1, -2.12194440e-4); -_PS_CONST(cephes_log_q2, 0.693359375); - -#ifndef USE_SSE2 -typedef union xmm_mm_union { - __m128 xmm; - __m64 mm[2]; -} xmm_mm_union; - -#define COPY_XMM_TO_MM(xmm_, mm0_, mm1_) { \ - xmm_mm_union u; u.xmm = xmm_; \ - mm0_ = u.mm[0]; \ - mm1_ = u.mm[1]; \ -} - -#define COPY_MM_TO_XMM(mm0_, mm1_, xmm_) { \ - xmm_mm_union u; u.mm[0]=mm0_; u.mm[1]=mm1_; xmm_ = u.xmm; \ - } - -#endif // USE_SSE2 - -/* natural logarithm computed for 4 simultaneous float - return NaN for x <= 0 -*/ -v4sf log_ps(v4sf x) { -#ifdef USE_SSE2 - v4si emm0; -#else - v2si mm0, mm1; -#endif - v4sf one = *(v4sf*)_ps_1; - - v4sf invalid_mask = _mm_cmple_ps(x, _mm_setzero_ps()); - - x = _mm_max_ps(x, *(v4sf*)_ps_min_norm_pos); /* cut off denormalized stuff */ - -#ifndef USE_SSE2 - /* part 1: x = frexpf(x, &e); */ - COPY_XMM_TO_MM(x, mm0, mm1); - mm0 = _mm_srli_pi32(mm0, 23); - mm1 = _mm_srli_pi32(mm1, 23); -#else - emm0 = _mm_srli_epi32(_mm_castps_si128(x), 23); -#endif - /* keep only the fractional part */ - x = _mm_and_ps(x, *(v4sf*)_ps_inv_mant_mask); - x = _mm_or_ps(x, *(v4sf*)_ps_0p5); - -#ifndef USE_SSE2 - /* now e=mm0:mm1 contain the really base-2 exponent */ - mm0 = _mm_sub_pi32(mm0, *(v2si*)_pi32_0x7f); - mm1 = _mm_sub_pi32(mm1, *(v2si*)_pi32_0x7f); - v4sf e = _mm_cvtpi32x2_ps(mm0, mm1); - _mm_empty(); /* bye bye mmx */ -#else - emm0 = _mm_sub_epi32(emm0, *(v4si*)_pi32_0x7f); - v4sf e = _mm_cvtepi32_ps(emm0); -#endif - - e = _mm_add_ps(e, one); - - /* part2: - if( x < SQRTHF ) { - e -= 1; - x = x + x - 1.0; - } else { x = x - 1.0; } - */ - v4sf mask = _mm_cmplt_ps(x, *(v4sf*)_ps_cephes_SQRTHF); - v4sf tmp = _mm_and_ps(x, mask); - x = _mm_sub_ps(x, one); - e = _mm_sub_ps(e, _mm_and_ps(one, mask)); - x = _mm_add_ps(x, tmp); - - - v4sf z = _mm_mul_ps(x, x); - - v4sf y = *(v4sf*)_ps_cephes_log_p0; - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p1); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p2); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p3); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p4); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p5); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p6); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p7); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p8); - y = _mm_mul_ps(y, x); - - y = _mm_mul_ps(y, z); - - - tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q1); - y = _mm_add_ps(y, tmp); - - - tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5); - y = _mm_sub_ps(y, tmp); - - tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q2); - x = _mm_add_ps(x, y); - x = _mm_add_ps(x, tmp); - x = _mm_or_ps(x, invalid_mask); // negative arg will be NAN - return x; -} - -_PS_CONST(exp_hi, 88.3762626647949f); -_PS_CONST(exp_lo, -88.3762626647949f); - -_PS_CONST(cephes_LOG2EF, 1.44269504088896341); -_PS_CONST(cephes_exp_C1, 0.693359375); -_PS_CONST(cephes_exp_C2, -2.12194440e-4); - -_PS_CONST(cephes_exp_p0, 1.9875691500E-4); -_PS_CONST(cephes_exp_p1, 1.3981999507E-3); -_PS_CONST(cephes_exp_p2, 8.3334519073E-3); -_PS_CONST(cephes_exp_p3, 4.1665795894E-2); -_PS_CONST(cephes_exp_p4, 1.6666665459E-1); -_PS_CONST(cephes_exp_p5, 5.0000001201E-1); - -v4sf exp_ps(v4sf x) { - v4sf tmp = _mm_setzero_ps(), fx; -#ifdef USE_SSE2 - v4si emm0; -#else - v2si mm0, mm1; -#endif - v4sf one = *(v4sf*)_ps_1; - - x = _mm_min_ps(x, *(v4sf*)_ps_exp_hi); - x = _mm_max_ps(x, *(v4sf*)_ps_exp_lo); - - /* express exp(x) as exp(g + n*log(2)) */ - fx = _mm_mul_ps(x, *(v4sf*)_ps_cephes_LOG2EF); - fx = _mm_add_ps(fx, *(v4sf*)_ps_0p5); - - /* how to perform a floorf with SSE: just below */ -#ifndef USE_SSE2 - /* step 1 : cast to int */ - tmp = _mm_movehl_ps(tmp, fx); - mm0 = _mm_cvttps_pi32(fx); - mm1 = _mm_cvttps_pi32(tmp); - /* step 2 : cast back to float */ - tmp = _mm_cvtpi32x2_ps(mm0, mm1); -#else - emm0 = _mm_cvttps_epi32(fx); - tmp = _mm_cvtepi32_ps(emm0); -#endif - /* if greater, substract 1 */ - v4sf mask = _mm_cmpgt_ps(tmp, fx); - mask = _mm_and_ps(mask, one); - fx = _mm_sub_ps(tmp, mask); - - tmp = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C1); - v4sf z = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C2); - x = _mm_sub_ps(x, tmp); - x = _mm_sub_ps(x, z); - - z = _mm_mul_ps(x, x); - - v4sf y = *(v4sf*)_ps_cephes_exp_p0; - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p1); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p2); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p3); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p4); - y = _mm_mul_ps(y, x); - y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p5); - y = _mm_mul_ps(y, z); - y = _mm_add_ps(y, x); - y = _mm_add_ps(y, one); - - /* build 2^n */ -#ifndef USE_SSE2 - z = _mm_movehl_ps(z, fx); - mm0 = _mm_cvttps_pi32(fx); - mm1 = _mm_cvttps_pi32(z); - mm0 = _mm_add_pi32(mm0, *(v2si*)_pi32_0x7f); - mm1 = _mm_add_pi32(mm1, *(v2si*)_pi32_0x7f); - mm0 = _mm_slli_pi32(mm0, 23); - mm1 = _mm_slli_pi32(mm1, 23); - - v4sf pow2n; - COPY_MM_TO_XMM(mm0, mm1, pow2n); - _mm_empty(); -#else - emm0 = _mm_cvttps_epi32(fx); - emm0 = _mm_add_epi32(emm0, *(v4si*)_pi32_0x7f); - emm0 = _mm_slli_epi32(emm0, 23); - v4sf pow2n = _mm_castsi128_ps(emm0); -#endif - y = _mm_mul_ps(y, pow2n); - return y; -} - -_PS_CONST(minus_cephes_DP1, -0.78515625); -_PS_CONST(minus_cephes_DP2, -2.4187564849853515625e-4); -_PS_CONST(minus_cephes_DP3, -3.77489497744594108e-8); -_PS_CONST(sincof_p0, -1.9515295891E-4); -_PS_CONST(sincof_p1, 8.3321608736E-3); -_PS_CONST(sincof_p2, -1.6666654611E-1); -_PS_CONST(coscof_p0, 2.443315711809948E-005); -_PS_CONST(coscof_p1, -1.388731625493765E-003); -_PS_CONST(coscof_p2, 4.166664568298827E-002); -_PS_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI - - -/* evaluation of 4 sines at onces, using only SSE1+MMX intrinsics so - it runs also on old athlons XPs and the pentium III of your grand - mother. - - The code is the exact rewriting of the cephes sinf function. - Precision is excellent as long as x < 8192 (I did not bother to - take into account the special handling they have for greater values - -- it does not return garbage for arguments over 8192, though, but - the extra precision is missing). - - Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the - surprising but correct result. - - Performance is also surprisingly good, 1.33 times faster than the - macos vsinf SSE2 function, and 1.5 times faster than the - __vrs4_sinf of amd's ACML (which is only available in 64 bits). Not - too bad for an SSE1 function (with no special tuning) ! - However the latter libraries probably have a much better handling of NaN, - Inf, denormalized and other special arguments.. - - On my core 1 duo, the execution of this function takes approximately 95 cycles. - - From what I have observed on the experiments with Intel AMath lib, switching to an - SSE2 version would improve the perf by only 10%. - - Since it is based on SSE intrinsics, it has to be compiled at -O2 to - deliver full speed. -*/ -v4sf sin_ps(v4sf x) { // any x - v4sf xmm1, xmm2 = _mm_setzero_ps(), xmm3, sign_bit, y; - -#ifdef USE_SSE2 - v4si emm0, emm2; -#else - v2si mm0, mm1, mm2, mm3; -#endif - sign_bit = x; - /* take the absolute value */ - x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask); - /* extract the sign bit (upper one) */ - sign_bit = _mm_and_ps(sign_bit, *(v4sf*)_ps_sign_mask); - - /* scale by 4/Pi */ - y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI); - -#ifdef USE_SSE2 - /* store the integer part of y in mm0 */ - emm2 = _mm_cvttps_epi32(y); - /* j=(j+1) & (~1) (see the cephes sources) */ - emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1); - emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1); - y = _mm_cvtepi32_ps(emm2); - - /* get the swap sign flag */ - emm0 = _mm_and_si128(emm2, *(v4si*)_pi32_4); - emm0 = _mm_slli_epi32(emm0, 29); - /* get the polynom selection mask - there is one polynom for 0 <= x <= Pi/4 - and another one for Pi/4 -#include -#include - -#include "ByteEngine/Id.h" -#include "ByteEngine/Application/Application.h" -#include "ByteEngine/Game/ApplicationManager.h" -#include "ByteEngine/Resources/AudioResourceManager.h" - -AudioSystem::AudioSystem(const InitializeInfo& initializeInfo) : System(initializeInfo, u8"AudioSystem"), sourceAudioDatas(16, GetPersistentAllocator()), audioBuffer(4u * 2u * 48000u, 16u, GetPersistentAllocator()) -{ - AudioDevice::CreateInfo createInfo; - - bool error = false; - - if (audioDevice.Initialize(createInfo)) { - auto bits = (uint32)BE::Application::Get()->GetUINTOption(u8"bitDepth"); - bits = GTSL::Math::Clamp(bits, 8u, 32u); - bits = GTSL::NextPowerOfTwo(bits); - - auto numChannels = (uint32)BE::Application::Get()->GetUINTOption(u8"channels"); - numChannels = GTSL::Math::Clamp(numChannels, 1u, 8u); - - auto samplesPerSecond = (uint32)BE::Application::Get()->GetUINTOption(u8"kHz"); - samplesPerSecond = GTSL::Math::Clamp(samplesPerSecond, 41000u, 96000u); - - if (samplesPerSecond != 41000 && samplesPerSecond != 48000 && samplesPerSecond != 96000 ) { - BE_LOG_WARNING(u8"User provided ", samplesPerSecond, u8" as audio system sample rate, which is invalid. Defaulting to 48KHz"); - samplesPerSecond = 48000; - } - - mixFormat.BitsPerSample = static_cast(bits); - mixFormat.NumberOfChannels = static_cast(numChannels); - mixFormat.SamplesPerSecond = samplesPerSecond; - mixFormat.bufferSamplePlacement = AudioDevice::BufferSamplePlacement::BLOCKS; - - onAudioInfoLoadHandle = GetApplicationManager()->RegisterTask(this, u8"onAudioInfoLoad", DependencyBlock(TypedDependency(u8"AudioResourceManager")), &AudioSystem::onAudioInfoLoad); - onAudioLoadHandle = GetApplicationManager()->RegisterTask(this, u8"onAudioLoad", DependencyBlock(), &AudioSystem::onAudioLoad); - - //auto preferredMixFormat = audioDevice.GetMixFormat(); - - if (audioDevice.IsMixFormatSupported(AAL::StreamShareMode::SHARED, mixFormat)) { - if (audioDevice.CreateAudioStream(AAL::StreamShareMode::SHARED, mixFormat)) { - if (audioDevice.Start()) { - if(audioDevice.GetBufferSamplePlacement() == AudioDevice::BufferSamplePlacement::INTERLEAVED) { - BE_LOG_ERROR(u8"Create audio device requires interleaved sample placment, which isn't supported. Oudio output will be disabled.") - error = true; - } - - audioBuffer.Allocate(GTSL::Byte(GTSL::MegaByte(1)).GetCount(), mixFormat.GetFrameSize()); - auto renderTaskHandle = GetApplicationManager()->RegisterTask(this, u8"renderAudio", DependencyBlock(), &AudioSystem::render, u8"RenderDo", u8"RenderEnd"); - - GetApplicationManager()->EnqueueScheduledTask(renderTaskHandle); - - BE_LOG_SUCCESS(u8"Started Audio Device\n Bits per Sample: ", (uint32)mixFormat.BitsPerSample, u8"\n Khz: ", mixFormat.SamplesPerSecond, u8"\n Channels: ", (uint32)mixFormat.NumberOfChannels) - - - mixFormat.bufferSamplePlacement = audioDevice.GetBufferSamplePlacement(); - } else { error = true; } - } else { error = true; } - } else { error = true; } - } else { error = true; } - - if (error) - BE_LOG_WARNING(u8"Unable to start audio device with requested parameters:\n Stream share mode: Shared\n Bits per sample: ", mixFormat.BitsPerSample, u8"\nNumber of channels: ", mixFormat.NumberOfChannels, u8"\nSamples per second: ", mixFormat.SamplesPerSecond); -} - -AudioSystem::~AudioSystem() { - if (!audioDevice.Stop()) { - BE_LOG_ERROR(u8"Failed to stop audio device.") - } - - audioDevice.Destroy(); -} - -AudioListenerHandle AudioSystem::CreateAudioListener() { - audioListenersLocation.EmplaceBack(); audioListenersOrientation.EmplaceBack(); - return AudioListenerHandle(audioListeners.EmplaceBack()); -} - -AudioEmitterHandle AudioSystem::CreateAudioEmitter() { - auto index = audioEmittersSettings.GetLength(); - audioEmittersSettings.EmplaceBack(); - audioEmittersLocation.EmplaceBack(); - return AudioEmitterHandle(index); -} - -void AudioSystem::BindAudio(AudioEmitterHandle audioEmitter, Id audioToPlay) { - auto* audioResourceManager = GetApplicationManager()->GetSystem(u8"AudioResourceManager"); - auto& sad = sourceAudioDatas.Emplace(GTSL::StringView(audioToPlay)); - sad.Loaded = false; - audioEmittersSettings[audioEmitter()].Name = audioToPlay; - audioResourceManager->LoadAudioInfo(audioToPlay, onAudioInfoLoadHandle); -} - -void AudioSystem::PlayAudio(AudioEmitterHandle audioEmitter) { - audioEmittersSettings[audioEmitter()].CurrentSample = 0; - if(!playingEmitters.Find(audioEmitter)) { // If emitter is already playing, don't add it to list - playingEmitters.EmplaceBack(audioEmitter); - } -} - -void AudioSystem::render(TaskInfo) { - if(!activeAudioListenerHandle) { return; } - - uint32 availableAudioFrames = 0; - if(!audioDevice.GetAvailableBufferFrames(availableAudioFrames)) { - BE_LOG_ERROR(u8"Failed to acquire audio buffer size.") - //TODO: disable audio - } - - auto* buffer = audioBuffer.GetData(); - - GTSL::SetMemory(availableAudioFrames * mixFormat.GetFrameSize(), audioBuffer.GetData(), 0); - - { - GTSL::Vector3 listenerPosition = GetPosition(activeAudioListenerHandle); - GTSL::Quaternion listenerRotation = GetOrientation(activeAudioListenerHandle); - GTSL::Vector3 listenerRightVector = listenerRotation * GTSL::Math::Right; - - for (uint32 pe = 0; pe < playingEmitters.GetLength(); ++pe) - { - GTSL::Vector3 emitterPosition = GetPosition(playingEmitters[pe]); - - auto soundDirection = GTSL::Math::DotProduct(GTSL::Math::Normalized(emitterPosition - listenerPosition), listenerRightVector); - - auto reMap = GTSL::Math::MapToRange(soundDirection, -1.0f, 1.0f, 0.0f, 1.0f); - - auto leftPercentange = GTSL::Math::InvertRange(reMap, 1.0); - auto rightPercentage = reMap; - - { - auto distanceFactor = GTSL::Math::Distance(emitterPosition, listenerPosition); - distanceFactor = GTSL::Math::Clamp(-(distanceFactor / 15) + 1, 0.0f, 1.0f); - //leftPercentange = GTSL::Math::InvertRange(leftPercentange * distanceFactor, 1.0f); rightPercentage = GTSL::Math::InvertRange(rightPercentage * distanceFactor, 1.0f); - //leftPercentange *= distanceFactor; rightPercentage *= distanceFactor; - } - - auto& emitter = audioEmittersSettings[playingEmitters[pe]()]; - - auto& sad = sourceAudioDatas[GTSL::StringView(emitter.Name)]; - - auto audioFrames = sad.FrameCount; - auto remainingFrames = audioFrames - emitter.CurrentSample; - auto clampedFrames = GTSL::Math::Limit(availableAudioFrames, remainingFrames); - auto playedSamples = emitter.CurrentSample; - - const byte* audio = sad.Buffer; - - if (sad.ChannelCount == 1) { - for (uint32 s = 0; s < clampedFrames; ++s) { //left channel - auto sample = getSample(audio, 1, s + playedSamples, 0); - - getSample(buffer, 2, s, AudioDevice::LEFT_CHANNEL) += sample * leftPercentange; - getSample(buffer, 2, s, AudioDevice::RIGHT_CHANNEL) += sample * rightPercentage; - } - } else { - for (uint32 s = 0; s < clampedFrames; ++s) { //left channel - auto lSample = getSample(audio, 2, s + playedSamples, AudioDevice::LEFT_CHANNEL); - auto rSample = getSample(audio, 2, s + playedSamples, AudioDevice::RIGHT_CHANNEL); - - getSample(buffer, 2, s, AudioDevice::LEFT_CHANNEL) += lSample * leftPercentange; - getSample(buffer, 2, s, AudioDevice::RIGHT_CHANNEL) += rSample * rightPercentage; - } - } - - if ((emitter.CurrentSample += clampedFrames) == audioFrames) { - if (!GetLooping(playingEmitters[pe])) { - playingEmitters.Pop(pe); - } - else { - emitter.CurrentSample = 0; - } - } - } - } - - { - auto audioDataCopyFunction = [&](uint32 size, void* to) - { - GTSL::MemCopy(size, audioBuffer.GetData(), to); - }; - - if(!audioDevice.PushAudioData(audioDataCopyFunction, availableAudioFrames)) { - BE_LOG_ERROR(u8"Failed to push audio data to driver.") - //TODO: disable audio - } - } -} - -void AudioSystem::onAudioInfoLoad(TaskInfo taskInfo, AudioResourceManager* audioResourceManager, AudioResourceManager::AudioInfo audioInfo) { - auto& sad = sourceAudioDatas[GTSL::StringView(audioInfo.Name)]; - GetPersistentAllocator().Allocate(audioInfo.GetAudioSize(), 16, reinterpret_cast(&sad.Buffer), &sad.Size); - audioResourceManager->LoadAudio(audioInfo, GTSL::Range(sad.Size, sad.Buffer), onAudioLoadHandle); -} - -void AudioSystem::onAudioLoad(TaskInfo taskInfo, AudioResourceManager::AudioInfo audioInfo, GTSL::Range buffer) { - GTSL::StaticVector toDelete; - - auto& sad = sourceAudioDatas[GTSL::StringView(audioInfo.Name)]; - - sad.Loaded = true; - sad.ChannelCount = audioInfo.ChannelCount; - sad.FrameCount = audioInfo.Frames; - - for(auto& e : sad.Emitters) { - playingEmitters.EmplaceBack(e); - } -} diff --git a/src/ByteEngine/Sound/AudioSystem.h b/src/ByteEngine/Sound/AudioSystem.h deleted file mode 100644 index 096ececd..00000000 --- a/src/ByteEngine/Sound/AudioSystem.h +++ /dev/null @@ -1,151 +0,0 @@ -#pragma once - -#include "ByteEngine/Handle.hpp" - -#include "ByteEngine/Game/System.hpp" - -#include "AAL/AudioDevice.h" -#if BE_PLATFORM_WINDOWS -#include "AAL/Platform/Windows/WindowsAudioDevice.h" -#endif - -#include -#include -#include - -#include "ByteEngine/Id.h" -#include "ByteEngine/Game/Tasks.h" -#include "ByteEngine/Resources/AudioResourceManager.h" - -class Sound; - -MAKE_HANDLE(uint32, AudioListener) -MAKE_HANDLE(uint32, AudioEmitter) - -class AudioSystem : public BE::System { -public: - AudioSystem(const InitializeInfo& initializeInfo); - ~AudioSystem(); - - AudioListenerHandle CreateAudioListener(); - AudioEmitterHandle CreateAudioEmitter(); - - void BindAudio(AudioEmitterHandle audioEmitter, Id audioToPlay); - void PlayAudio(AudioEmitterHandle audioEmitter); - - void SetPosition(AudioEmitterHandle audioEmitterHandle, const GTSL::Vector3 position) { audioEmittersLocation[audioEmitterHandle()] = position; } - void SetPosition(AudioListenerHandle audioListenerHandle, const GTSL::Vector3 position) { audioListenersLocation[audioListenerHandle()] = position; } - - GTSL::Vector3 GetPosition(const AudioListenerHandle audioListenerHandle) const { return audioListenersLocation[audioListenerHandle()]; } - GTSL::Vector3 GetPosition(const AudioEmitterHandle audioEmitterHandle) const { return audioEmittersLocation[audioEmitterHandle()]; } - - void SetOrientation(AudioListenerHandle audioListenerHandle, const GTSL::Quaternion orientation) { audioListenersOrientation[audioListenerHandle()] = orientation; } - GTSL::Quaternion GetOrientation(AudioListenerHandle audioListenerHandle) const { return audioListenersOrientation[audioListenerHandle()]; } - - void SetAudioListener(const AudioListenerHandle audioListenerHandle) { activeAudioListenerHandle = audioListenerHandle; } - - void SetLooping(const AudioEmitterHandle audioEmitterHandle, bool loop) { audioEmittersSettings[audioEmitterHandle()].Loop = loop; } - bool GetLooping(const AudioEmitterHandle audioEmitterHandle) { return audioEmittersSettings[audioEmitterHandle()].Loop; } - - MAKE_HANDLE(uint8, Channel); - MAKE_HANDLE(uint8, SoundSource); - -private: - using AudioDevice = AAL::AudioDevice; -#if BE_PLATFORM_WINDOWS - using AudioDevice = AAL::WindowsAudioDevice; -#elif BE_PLATFORM_LINUX -#endif - - AudioDevice audioDevice; - AudioDevice::MixFormat mixFormat; - - struct SoundSource { - byte* Data; - }; - GTSL::StaticVector soundSources; - - struct MixerChannel { - struct Effect { - - }; - GTSL::StaticVector Effects; - - GTSL::StaticVector SoundSources; - - float32 Volume = 0.0f; - }; - GTSL::StaticVector channels; - - GTSL::StaticVector audioListeners; - GTSL::StaticVector audioListenersLocation; - GTSL::StaticVector audioListenersOrientation; - - GTSL::StaticVector audioEmittersLocation; - - MAKE_HANDLE(uint32, PrivateSound); - - struct AudioEmitterSettings - { - bool Loop = false; - //PrivateSoundHandle PrivateSoundHandle; - Id Name; - // Indicates current playing sample - uint32 CurrentSample = 0; - - }; - GTSL::StaticVector audioEmittersSettings; - - GTSL::StaticVector playingEmitters; - - struct SourceAudioData { - - /** - * \brief A list of emitters currently playing this source. - */ - GTSL::StaticVector Emitters; - - bool Loaded; - - uint32 ChannelCount = 0, FrameCount = 0; - - byte* Buffer = nullptr; - uint64 Size = 0; - }; - GTSL::HashMap sourceAudioDatas; - - GTSL::Buffer audioBuffer; - TaskHandle onAudioInfoLoadHandle; - TaskHandle> onAudioLoadHandle; - - AudioListenerHandle activeAudioListenerHandle; - - template - static auto getSample(const byte* buffer, const uint8 channelCount, const uint32 sample, const uint32 channel) -> T { - return *(reinterpret_cast(buffer) + sample * channelCount + channel); - } - - template - static auto getSample(byte* buffer, const uint8 channelCount, const uint32 sample, const uint32 channel) -> T& { - return *(reinterpret_cast(buffer) + sample * channelCount + channel); - } - - void render(TaskInfo); - - void removePlayingEmitter(uint32 i) - { - audioEmittersSettings[playingEmitters[i]()].CurrentSample = 0; - playingEmitters.Pop(i); - } - - void onAudioInfoLoad(TaskInfo taskInfo, AudioResourceManager*, AudioResourceManager::AudioInfo audioInfo); - void onAudioLoad(TaskInfo taskInfo, AudioResourceManager::AudioInfo audioInfo, GTSL::Range buffer); - - bool shouldStream(const uint32 samples) { - return samples >= samplesToLoad(); //if audio is longer than 10 seconds, stream it - } - - uint32 samplesToLoad() { - return 48000 * 10; - } -}; diff --git a/src/ByteEngine/Sound/Effect.h b/src/ByteEngine/Sound/Effect.h deleted file mode 100644 index abf29d77..00000000 --- a/src/ByteEngine/Sound/Effect.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -class Effect { - -}; - -class LowPassFilter { - -}; \ No newline at end of file diff --git a/src/ByteEngine/Sound/SoundListener.h b/src/ByteEngine/Sound/SoundListener.h deleted file mode 100644 index 6c77b5a4..00000000 --- a/src/ByteEngine/Sound/SoundListener.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -/** - * \brief Describes a sound listener, which represents a point in space from which to capture 3D sound in a game world. - */ -class SoundListener -{ -public: -}; diff --git a/src/ByteEngine/Sound/SoundMixer.h b/src/ByteEngine/Sound/SoundMixer.h deleted file mode 100644 index 22d9975c..00000000 --- a/src/ByteEngine/Sound/SoundMixer.h +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include - -#include "SoundPlayer.h" -#include -#include -#include - -#include "ByteEngine/Application/AllocatorReferences.h" - -class AudioBuffer; - -class SoundMixerChannelEffect -{ - /** - * \brief Defines the effect's name. Used to refer to it. - */ - GTSL::Id64 effectName; - - /** - * \brief Determines the effects intensity when used in a channel. - */ - float effectIntensity = 0.0f; - -public: - virtual ~SoundMixerChannelEffect(); - - virtual void Process(const AudioBuffer& _AudioBuffer) = 0; -}; - -/** - * \brief Structure to specify the details of the deletion of an audio channel effect.\n - * Like the fade out time, or the fade out function. - */ -struct SoundMixerChannelEffectRemoveParameters -{ - /** - * \brief Determines the time it takes for this effect to be faded out.\n - * If KillTime is 0 the effect will be deleted immediately. - */ - float FadeOutTime = 0.0f; - - /** - * \brief Pointer to the function to be used for fading out the effect. If any fading out is applied at all. - */ - void (*FadeFunction)() = nullptr; -}; - -class SoundMixer -{ - class SoundMixerChannel - { - friend class SoundMixer; - - /** - * \brief Defines the type for a Pair holding a bool to determine whether the sound is virtualized, and a Player* to know which Player to grab the data from. - */ - using PlayingSounds = GTSL::Pair; - - - /** - * \brief Determines how strong this channel sounds. - */ - float mixVolume = 0.0f; - - /** - * \brief Defines the channel's name. Used to refer to it from the mixer. - */ - GTSL::Id64 channelName; - - /** - * \brief Holds an array of sounds which are to be played. - */ - GTSL::Vector playingSounds; - - /** - * \brief Holds the collection of effects this channel has. Every channel can have a maximum of 10 simultaneous effects running on it. - */ - GTSL::StaticVector effects; - - public: - ~SoundMixerChannel() - { - for (auto& e : effects) - { - delete e; - } - } - - void SetMixVolume(const float _MixVolume) { mixVolume = _MixVolume; } - - /** - * \brief Adds and effect to the channel. - * \tparam _T Class of effect - * \return Effect* to the newly created effect. Could be used to set parameters. - */ - template - SoundMixerChannelEffect* AddEffect() - { - SoundMixerChannelEffect* new_effect = new _T(); - effects.PushBack(new_effect); - return new_effect; - } - - void RemoveEffect(const SoundMixerChannelEffectRemoveParameters& _ERP); - }; - - /** - * \brief Stores every channel available. - */ - //HashMap channels; - -public: - void OnUpdate(); - - void RegisterNewChannel(const SoundMixerChannel& _Channel) - { - //channels.TryEmplace; - //channels.Get(0).effects; - } - - SoundMixerChannel& GetChannel(const GTSL::Id64& _Id) - { - //return channels.Get(_Id.GetID()); - } -}; diff --git a/src/ByteEngine/Sound/SoundPlayer.h b/src/ByteEngine/Sound/SoundPlayer.h deleted file mode 100644 index 6213e5a9..00000000 --- a/src/ByteEngine/Sound/SoundPlayer.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -class SoundPlayer -{ - class Sound; - - Sound* soundToPlay = nullptr; - - float intensity = 0.0f; -}; diff --git a/src/ByteEngine/Utility/AStar.cpp b/src/ByteEngine/Utility/AStar.cpp deleted file mode 100644 index 2947aa0c..00000000 --- a/src/ByteEngine/Utility/AStar.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include - -struct GraphNode { - GTSL::Vector3 Position; -}; - -void AStar() { - using TreeType = GTSL::Tree; - TreeType tree; - - auto advanceNode = [&](TreeType::Node* node, auto&& self) -> void { - TreeType::Node* shortestNode = nullptr; - - GTSL::Vector3 currentPosition; - float32 shortestLength = FLT_MAX; - - for(auto e : node->Nodes) { - if (auto len = GTSL::SquaredDistance(e->Position, currentPosition); len < shortestLength) { - shortestLength = len; - shortestNode = e; - } - } - - self(shortestNode, self); - }; - - advanceNode(&tree[0], advanceNode); -} \ No newline at end of file diff --git a/src/ByteEngine/Utility/Collision.hpp b/src/ByteEngine/Utility/Collision.hpp deleted file mode 100644 index b12c41bf..00000000 --- a/src/ByteEngine/Utility/Collision.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -using Vector3MultiRange = GTSL::MultiRange; - -template -auto Lookup(GTSL::Range range, const float32 t) { - auto index = (uint32)t; - auto index1 = GTSL::Math::Limit(index, range.ElementCount()); - return Lerp(range[index], range[index1], t - (float32)index); -} - -void AABBvAABB(Vector3MultiRange posA, Vector3MultiRange posB, Vector3MultiRange hWidthA, Vector3MultiRange hWidthB) { - return Abs(posB - posA) <= (hWidthA + hWidthB); -} - -void RemakeAABB(const GTSL::Vector3 localMax, const GTSL::Matrix4& orientation, GTSL::Vector3* newAABB) { - *newAABB = orientation * localMax; -} - -void RemakeAABB(const GTSL::Vector3 localMax, const GTSL::Quaternion& orientation, GTSL::Vector3* newAABB) { - *newAABB = orientation * localMax; -} \ No newline at end of file diff --git a/src/ByteEngine/Utility/Shapes/Box.h b/src/ByteEngine/Utility/Shapes/Box.h deleted file mode 100644 index 37ebc3ce..00000000 --- a/src/ByteEngine/Utility/Shapes/Box.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include - -class Box -{ - float width = 0; - float height = 0; - float depth = 0; - -public: - [[nodiscard]] auto& GetWidth() { return width; } - [[nodiscard]] auto& GetHeight() { return height; } - [[nodiscard]] auto& GetDepth() { return depth; } - - [[nodiscard]] auto GetWidth() const { return width; } - [[nodiscard]] auto GetHeight() const { return height; } - [[nodiscard]] auto GetDepth() const { return depth; } - - [[nodiscard]] GTSL::Pair GetExtremePoints() const - { - return GTSL::Pair(GTSL::Vector3(width / 2, height / 2, depth / 2), GTSL::Vector3(-width / 2, -height / 2, -depth / 2)); - } - - void SetWidthHeightDepth(const float _Width, const float _Height, const float _Depth) - { - width = _Width, height = _Height, depth = _Depth; - } -}; diff --git a/src/ByteEngine/Utility/Shapes/BoxWithFalloff.h b/src/ByteEngine/Utility/Shapes/BoxWithFalloff.h deleted file mode 100644 index 79941243..00000000 --- a/src/ByteEngine/Utility/Shapes/BoxWithFalloff.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "Box.h" - -struct BoxWithFalloff : public Box -{ - float falloffDistance = 0; -}; diff --git a/src/ByteEngine/Utility/Shapes/Cone.cpp b/src/ByteEngine/Utility/Shapes/Cone.cpp deleted file mode 100644 index 9e37c8f8..00000000 --- a/src/ByteEngine/Utility/Shapes/Cone.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "Cone.h" - -#include - -Cone::Cone(const float Radius, const float Length) : Radius(Radius), Length(Length) -{ -} - -float Cone::GetInnerAngle() const -{ - return GTSL::Math::ArcTangent(Radius / Length); -} diff --git a/src/ByteEngine/Utility/Shapes/Cone.h b/src/ByteEngine/Utility/Shapes/Cone.h deleted file mode 100644 index 9b697782..00000000 --- a/src/ByteEngine/Utility/Shapes/Cone.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -struct Cone -{ - Cone() = default; - - Cone(const float Radius, const float Length); - - ~Cone() = default; - - //Returns the value of Radius. - [[nodiscard]] float GetRadius() const { return Radius; } - //Returns the value of Length. - [[nodiscard]] float GetLength() const { return Length; } - - [[nodiscard]] float GetInnerAngle() const; - - //Sets Radius as NewRadius. - void SetRadius(float NewRadius) - { - Radius = NewRadius; - } - //Sets Length as NewLength. - void SetLength(float NewLength) - { - Length = NewLength; - } - -protected: - //Specifies the radius of the cone. - float Radius = 100.0f; - - //Specifies the length of the cone. - float Length = 500.0f; -}; \ No newline at end of file diff --git a/src/ByteEngine/Utility/Shapes/ConeWithFalloff.cpp b/src/ByteEngine/Utility/Shapes/ConeWithFalloff.cpp deleted file mode 100644 index 95df962b..00000000 --- a/src/ByteEngine/Utility/Shapes/ConeWithFalloff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "ConeWithFalloff.h" - -#include - -ConeWithFalloff::ConeWithFalloff(const float Radius, const float Length) : Cone(Radius, Length) -{ -} - -ConeWithFalloff::ConeWithFalloff(const float Radius, const float Length, const float ExtraRadius) : Cone(Radius, Length), ExtraRadius(ExtraRadius) -{ -} - -float ConeWithFalloff::GetOuterConeInnerRadius() const -{ - return GTSL::Math::ArcTangent((Radius + ExtraRadius) / Length); -} diff --git a/src/ByteEngine/Utility/Shapes/ConeWithFalloff.h b/src/ByteEngine/Utility/Shapes/ConeWithFalloff.h deleted file mode 100644 index 0366dae4..00000000 --- a/src/ByteEngine/Utility/Shapes/ConeWithFalloff.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "ByteEngine/Core.h" - -#include "Cone.h" - -struct ConeWithFalloff : public Cone -{ - ConeWithFalloff() = default; - ConeWithFalloff(float Radius, float Length); - ConeWithFalloff(float Radius, float Length, float ExtraRadius); - - ~ConeWithFalloff() = default; - - //Returns the value of ExtraRadius. - [[nodiscard]] float GetExtraRadius() const { return ExtraRadius; } - - //Sets Extra Radius as NewExtraRadius. - void SetExtraRadius(const float NewExtraRadius) - { - ExtraRadius = NewExtraRadius; - } - - [[nodiscard]] float GetOuterConeInnerRadius() const; - -protected: - //Determines the extra radius on top of the original radius to determine the outer radius. - float ExtraRadius = 50.0f; -}; \ No newline at end of file diff --git a/src/ByteEngine/Utility/Shapes/SphereWithFallof.h b/src/ByteEngine/Utility/Shapes/SphereWithFallof.h deleted file mode 100644 index a8a7796b..00000000 --- a/src/ByteEngine/Utility/Shapes/SphereWithFallof.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -class Vector3; - -struct SphereWithFalloff -{ - float radius = 0; - - //Additional distance from the shapes inner limit to form the outer limit. - float falloffDistance = 0; - - SphereWithFalloff(); - SphereWithFalloff(const float DistToOuterLimit); - SphereWithFalloff(const float DistToOuterLimit, const float FalloffExponent); - - float GetLinearIntensityAt(const Vector3& Position); - float GetExponentialIntensityAt(const Vector3& Position); -}; - -//float BoundingSpherewithFallout::GetLinearIntensityAt(const Vector3& Position) -//{ -// return GTM::MapToRangeClamped(GTM::VectorLengthSquared(Transform.Location, Position), 0, DistToOuterLimit * DistToOuterLimit, 0, 1); -//} diff --git a/src/ByteEngine/Utility/StringLookup.hpp b/src/ByteEngine/Utility/StringLookup.hpp deleted file mode 100644 index 0b8e9860..00000000 --- a/src/ByteEngine/Utility/StringLookup.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include "ByteEngine/Application/AllocatorReferences.h" - -class StringLookup { -public: - - void AddKey(const GTSL::Range string) { - Node* start = nullptr; - - for (auto e : string) { - start = start->in[(uint8)e]; - } - } - - template - void Lookup(const GTSL::Range string, C& container) { - Node* start = nullptr; - - for (auto e : string) { - start = start->in[(uint8)e]; - } - - auto moveThroughTree = [&](const Node* node, auto&& self) { - - }; - - moveThroughTree() - } - -private: - struct Node { - GTSL::StaticVector in; - }; - - GTSL::Tree tree; -}; \ No newline at end of file diff --git a/src/GAL/Bindings.h b/src/GAL/Bindings.h deleted file mode 100644 index 30e31b35..00000000 --- a/src/GAL/Bindings.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "RenderCore.h" - -namespace GAL -{ - class Sampler; - constexpr GTSL::uint8 MAX_BINDINGS_PER_SET = 10; - - class RenderContext; - - //struct BindingLayoutCreateInfo - //{ - // GTSL::Range BindingsSetLayout; - // GTSL::uint32 DescriptorCount = 0; - //}; - - class BindingsPool { - public: - ~BindingsPool() = default; - - struct BindingsPoolSize { - BindingType Type; - GTSL::uint32 Count = 0; - }; - }; - - struct BindingSetLayout { - struct BindingDescriptor { - BindingType Type; - ShaderStage Stage; - GTSL::uint32 BindingsCount; - BindingFlag Flags; - GTSL::Range Samplers; - }; - }; - - class BindingsSet { - public: - }; -} \ No newline at end of file diff --git a/src/GAL/Buffer.h b/src/GAL/Buffer.h deleted file mode 100644 index a77791fe..00000000 --- a/src/GAL/Buffer.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace GAL -{ - class Buffer - { - public: - Buffer() = default; - }; -} diff --git a/src/GAL/CommandList.h b/src/GAL/CommandList.h deleted file mode 100644 index ecdbc1c2..00000000 --- a/src/GAL/CommandList.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once -#include "RenderCore.h" -#include - -#undef MemoryBarrier - -namespace GAL -{ - class Buffer; - class Texture; - - class CommandList { - public: - CommandList() = default; - ~CommandList() = default; - //Starts recording of commands. - - - //Ends recording of commands. - - // COMMANDS - - // BIND COMMANDS - // BIND BUFFER COMMANDS - - //Adds a BindMesh command to the command queue. - - // BIND PIPELINE COMMANDS - - //Adds a BindBindingsSets to the command queue. - - //Adds a BindGraphicsPipeline command to the command queue. - //Adds a BindComputePipeline to the command queue. - - // DRAW COMMANDS - - //Adds a DrawIndexed command to the command queue. - - // COMPUTE COMMANDS - - //Adds a Dispatch command to the command queue. - - // RENDER PASS COMMANDS - - //Adds a BeginRenderPass command to the command queue. - - //Adds a AdvanceSubPass command to the command buffer. - - struct MemoryBarrier { - }; - - struct BufferBarrier { - const Buffer* buffer; GTSL::uint32 size; - }; - - struct TextureBarrier { - const Texture* texture; - TextureLayout CurrentLayout, TargetLayout; - FormatDescriptor Format; - }; - - enum class BarrierType : GTSL::uint8 { - MEMORY, BUFFER, TEXTURE - }; - - struct BarrierData { - BarrierData(PipelineStage sP, PipelineStage dP, AccessType sA, AccessType dA, const MemoryBarrier memoryBarrier) : SourceStage(sP), DestinationStage(dP), SourceAccess(sA), DestinationAccess(dA), Type(BarrierType::MEMORY), Memory(memoryBarrier) {} - BarrierData(PipelineStage sP, PipelineStage dP, AccessType sA, AccessType dA, const BufferBarrier bufferBarrier) : SourceStage(sP), DestinationStage(dP), SourceAccess(sA), DestinationAccess(dA), Type(BarrierType::BUFFER), Buffer(bufferBarrier) {} - BarrierData(PipelineStage sP, PipelineStage dP, AccessType sA, AccessType dA, const TextureBarrier textureBarrier) : SourceStage(sP), DestinationStage(dP), SourceAccess(sA), DestinationAccess(dA), Type(BarrierType::TEXTURE),Texture(textureBarrier) {} - - BarrierData(const BarrierData& other) : Type(other.Type) { - switch (Type) { - case BarrierType::MEMORY: Memory = other.Memory; break; - case BarrierType::BUFFER: Buffer = other.Buffer; break; - case BarrierType::TEXTURE: Texture = other.Texture; break; - } - } - - BarrierType Type; - - union { - MemoryBarrier Memory; - BufferBarrier Buffer; - TextureBarrier Texture; - }; - - AccessType SourceAccess, DestinationAccess; - PipelineStage SourceStage, DestinationStage; - - uint32 From = 0xFFFFFFFF, To = 0xFFFFFFFF; - - void SetMemoryBarrier(MemoryBarrier memoryBarrier) { Type = BarrierType::MEMORY; Memory = memoryBarrier; } - void SetTextureBarrier(TextureBarrier textureBarrier) { Type = BarrierType::TEXTURE; Texture = textureBarrier; } - void SetBufferBarrier(BufferBarrier bufferBarrier) { Type = BarrierType::BUFFER; Buffer = bufferBarrier; } - }; - - struct ShaderTableDescriptor - { - DeviceAddress Address; - - /** - * \brief Number of entries in the shader group. - */ - GTSL::uint32 Entries = 0; - - /** - * \brief Size of each entry in the shader group. - */ - GTSL::uint32 EntrySize = 0; - }; - }; -} diff --git a/src/GAL/DX12/DX12.h b/src/GAL/DX12/DX12.h deleted file mode 100644 index 2cabe936..00000000 --- a/src/GAL/DX12/DX12.h +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include "GTSL/Core.h" -#include "GTSL/Range.hpp" - -#include - -#include "GAL/RenderCore.h" -#include "GTSL/Flags.h" -#include "GTSL/StringCommon.h" - -#if (_DEBUG) -#define DX_CHECK(func) if (func < 0) { __debugbreak(); } -#else -#define DX_CHECK(func) func; -#endif - -namespace GAL -{ - template - void setName(T* handle, const GTSL::StringView name) { - if constexpr (_DEBUG) { - if (name.GetBytes() != 0) - handle->SetPrivateData(WKPDID_D3DDebugObjectName, name.GetBytes(), name.GetData()); - } - } - - inline D3D12_COMMAND_LIST_TYPE ToDX12(const QueueType queueType) { - if(queueType & QueueTypes::GRAPHICS) { - return D3D12_COMMAND_LIST_TYPE_DIRECT; - } - - if(queueType & QueueTypes::COMPUTE) { - return D3D12_COMMAND_LIST_TYPE_COMPUTE; - } - - if(queueType & QueueTypes::TRANSFER) { - return D3D12_COMMAND_LIST_TYPE_COPY; - } - } - - inline D3D12_RESOURCE_STATES ToDX12(const BufferUse bufferUses) { - GTSL::uint32 resourceStates = 0; - TranslateMask(BufferUses::STORAGE, D3D12_RESOURCE_STATE_COMMON, bufferUses, resourceStates); - TranslateMask(BufferUses::TRANSFER_SOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE, bufferUses, resourceStates); - TranslateMask(BufferUses::TRANSFER_DESTINATION, D3D12_RESOURCE_STATE_COPY_DEST, bufferUses, resourceStates); - return D3D12_RESOURCE_STATES(resourceStates); - } - - inline D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE ToD3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE(const Operations operations) { - switch (operations) { - case Operations::UNDEFINED: return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD; - case Operations::DO: return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE; - case Operations::CLEAR: return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR; - } - } - - inline D3D12_RENDER_PASS_ENDING_ACCESS_TYPE ToD3D12_RENDER_PASS_ENDING_ACCESS_TYPE(const Operations operations) { - switch (operations) { - case Operations::UNDEFINED: return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD; - case Operations::DO: return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE; - case Operations::CLEAR: return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD; - } - } - - inline DXGI_FORMAT ToDX12(const ShaderDataType type) { - switch (type) { - case ShaderDataType::FLOAT: return DXGI_FORMAT_R32_FLOAT; - case ShaderDataType::FLOAT2: return DXGI_FORMAT_R32G32_FLOAT; - case ShaderDataType::FLOAT3: return DXGI_FORMAT_R32G32B32_FLOAT; - case ShaderDataType::FLOAT4: return DXGI_FORMAT_R32G32B32A32_FLOAT; - case ShaderDataType::INT: return DXGI_FORMAT_R32_UINT; - case ShaderDataType::INT2: return DXGI_FORMAT_R32G32_UINT; - case ShaderDataType::INT3: return DXGI_FORMAT_R32G32B32_UINT; - case ShaderDataType::INT4: return DXGI_FORMAT_R32G32B32A32_UINT; - case ShaderDataType::BOOL: break; - case ShaderDataType::MAT3: break; - case ShaderDataType::MAT4: break; - case ShaderDataType::U16_SNORM: return DXGI_FORMAT_R16_SNORM; - case ShaderDataType::U16_SNORM2: return DXGI_FORMAT_R16G16_SNORM; - //case ShaderDataType::U16_SNORM3: return DXGI_FORMAT_R16G16B16_SNORM; - case ShaderDataType::U16_SNORM4: return DXGI_FORMAT_R16G16B16A16_SNORM; - case ShaderDataType::U16_UNORM: return DXGI_FORMAT_R16_UNORM; - case ShaderDataType::U16_UNORM2: return DXGI_FORMAT_R16G16_UNORM; - //case ShaderDataType::U16_SNORM3: return DXGI_FORMAT_R16G16B16_SNORM; - case ShaderDataType::U16_UNORM4: return DXGI_FORMAT_R16G16B16A16_UNORM; - default: return DXGI_FORMAT_UNKNOWN; - } - } - - inline DXGI_FORMAT ToDX12(const IndexType indexType) { - switch (indexType) { - case IndexType::UINT8: return DXGI_FORMAT_R8_UINT; - case IndexType::UINT16: return DXGI_FORMAT_R16_UINT; - case IndexType::UINT32: return DXGI_FORMAT_R32_UINT; - default: return DXGI_FORMAT_UNKNOWN; - } - } - - inline DXGI_FORMAT ToDX12(const Format format) { - switch (format) { - case Format::RGB_I8: return DXGI_FORMAT_UNKNOWN; - case Format::RGBA_I8: return DXGI_FORMAT_R8G8B8A8_UNORM; - case Format::RGBA_F16: return DXGI_FORMAT_R16G16B16A16_FLOAT; - case Format::BGRA_I8: return DXGI_FORMAT_B8G8R8A8_UNORM; - case Format::DEPTH32: return DXGI_FORMAT_D32_FLOAT; - case Format::RG_I32: return DXGI_FORMAT_R32G32_UINT; - default: return DXGI_FORMAT_UNKNOWN; - } - } - - inline DXGI_FORMAT ToDX12(const FormatDescriptor format) { - return ToDX12(MakeFormatFromFormatDescriptor(format)); - } - - inline D3D12_RESOURCE_DIMENSION ToDX12Type(const GTSL::Extent3D extent) - { - if (extent.Height != 1) { - if (extent.Depth != 1) { return D3D12_RESOURCE_DIMENSION_TEXTURE3D; } - return D3D12_RESOURCE_DIMENSION_TEXTURE2D; - } - - return D3D12_RESOURCE_DIMENSION_TEXTURE1D; - } - - inline D3D12_TEXTURE_LAYOUT ToDX12(const Tiling tiling) { - switch (tiling) { - case Tiling::OPTIMAL: return D3D12_TEXTURE_LAYOUT_UNKNOWN; - case Tiling::LINEAR: return D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - } - } - - inline D3D12_RESOURCE_STATES ToDX12(const TextureUse uses, const FormatDescriptor formatDescriptor) { - GTSL::uint32 resourceStates = 0; - - if (uses & TextureUses::ATTACHMENT) { - switch (formatDescriptor.Type) - { - case TextureType::COLOR: resourceStates |= D3D12_RESOURCE_STATE_RENDER_TARGET; break; - case TextureType::DEPTH: resourceStates |= D3D12_RESOURCE_STATE_RENDER_TARGET; break; - } - } - - //TranslateMask(uses, resourceStates); - //TranslateMask(uses, resourceStates); - //TranslateMask(uses, resourceStates); - TranslateMask(TextureUses::TRANSFER_DESTINATION, D3D12_RESOURCE_STATE_COPY_DEST, uses, resourceStates); - TranslateMask(TextureUses::TRANSFER_SOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE, uses, resourceStates); - //TranslateMask(uses, resourceStates); - - return D3D12_RESOURCE_STATES(resourceStates); - } - - inline D3D12_SHADER_VISIBILITY ToDX12(const ShaderStage shaderStage) { - D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - //TranslateMask(ShaderStages::VERTEX, D3D12_SHADER_VISIBILITY_VERTEX, shaderStage, shaderVisibility); - //TranslateMask(ShaderStages::FRAGMENT, D3D12_SHADER_VISIBILITY_PIXEL, shaderStage, shaderVisibility); - //TranslateMask(ShaderStages::COMPUTE, D3D12_SHADER_VISIBILITY_DOMAIN, shaderStage, shaderVisibility); - return D3D12_SHADER_VISIBILITY(shaderVisibility); - } -} \ No newline at end of file diff --git a/src/GAL/DX12/DX12AccelerationStructure.hpp b/src/GAL/DX12/DX12AccelerationStructure.hpp deleted file mode 100644 index b1e254a2..00000000 --- a/src/GAL/DX12/DX12AccelerationStructure.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "DX12.h" -#include - -namespace GAL -{ - class DX12AccelerationStructure - { - public: - DX12AccelerationStructure(const DX12RenderDevice* renderDevice) { - //renderDevice->GetID3D12Device2()->CreateAcc - ID3D12Device8* d; - } - - ID3D12Resource* GetID3D12Resource() { return nullptr; } - - private: - - }; -} diff --git a/src/GAL/DX12/DX12Bindings.h b/src/GAL/DX12/DX12Bindings.h deleted file mode 100644 index 3ccd0c9b..00000000 --- a/src/GAL/DX12/DX12Bindings.h +++ /dev/null @@ -1,244 +0,0 @@ -#pragma once - -#include "DX12.h" -#include "DX12AccelerationStructure.hpp" -#include "DX12Buffer.h" -#include "DX12Texture.h" -#include "GAL/Bindings.h" -#include "GAL/DX12/DX12RenderDevice.h" - -namespace GAL { - class DX12BindingsSet final { - public: - private: - }; - - class DX12BindingsSetLayout final : BindingSetLayout { - public: - struct BindingDescriptor { - BindingType BindingType; - ShaderStage ShaderStage; - GTSL::uint32 BindingsCount; - BindingFlag Flags; - GTSL::Range Samplers; - }; - - DX12BindingsSetLayout(const DX12RenderDevice* renderDevice, GTSL::Range bindingsDescriptors) { - GTSL::StaticVector parameters; - GTSL::StaticVector staticSamplers; - - for(uint32 i = 0; i < bindingsDescriptors.ElementCount(); ++i) { - const auto& bd = bindingsDescriptors[i]; - - auto& parameter = parameters.EmplaceBack(); - parameter.ShaderVisibility = ToDX12(bd.ShaderStage); - - if(!bd.Samplers.ElementCount()) { - switch (bd.BindingType) { - case BindingType::SAMPLER: break; - case BindingType::COMBINED_IMAGE_SAMPLER: break; - case BindingType::SAMPLED_IMAGE: { - parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; - break; - } - case BindingType::STORAGE_IMAGE: { - parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; - break; - } - case BindingType::UNIFORM_BUFFER: break; - case BindingType::STORAGE_BUFFER: { - parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - parameter.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE; - break; - } - case BindingType::INPUT_ATTACHMENT: break; - case BindingType::ACCELERATION_STRUCTURE: break; - } - } else { - auto& ss = staticSamplers.EmplaceBack(); - ss.ShaderVisibility = parameter.ShaderVisibility; - ss.ShaderRegister = 0u; ss.RegisterSpace = 0u; - ss.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; ss.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; ss.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - ss.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; - ss.ComparisonFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; - ss.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; - ss.MaxAnisotropy = 8u; - ss.MinLOD = 0u; ss.MaxLOD = 0u; - ss.MipLODBias = 0.0f; - } - - } - - { - auto& pc = parameters.EmplaceBack(); - pc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - pc.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - pc.Constants.Num32BitValues = 128 / 4; - pc.Constants.RegisterSpace = 0u; pc.Constants.ShaderRegister = 0u; - } - - D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc{ D3D_ROOT_SIGNATURE_VERSION_1_1 }; - rootSignatureDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE | D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; - rootSignatureDesc.Desc_1_1.NumParameters = parameters.GetLength(); - rootSignatureDesc.Desc_1_1.pParameters = parameters.GetData(); - rootSignatureDesc.Desc_1_1.NumStaticSamplers = staticSamplers.GetLength(); - rootSignatureDesc.Desc_1_1.pStaticSamplers = staticSamplers.GetData(); - - ID3DBlob* rootSignatureBlob, * errorBlob; - - D3D12SerializeVersionedRootSignature(&rootSignatureDesc, &rootSignatureBlob, &errorBlob); - - renderDevice->GetID3D12Device2()->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), __uuidof(ID3D12RootSignature), reinterpret_cast(&rootSignature)); - } - - private: - ID3D12RootSignature* rootSignature = nullptr; - }; - - class DX12BindingsPool final : BindingsPool { - public: - void Initialize(const DX12RenderDevice* renderDevice, GTSL::Range bindingsPoolSizes, GTSL::uint32 maxSets) { - D3D12_DESCRIPTOR_HEAP_DESC descHeapCbvSrv = {}, descHeapSampler = {}, descHeapRTV = {}, descHeapDSV = {}; - - for (auto& e : bindingsPoolSizes) { - switch(e.BindingType) { - case BindingType::INPUT_ATTACHMENT: { - descHeapRTV.NumDescriptors += e.Count; - descHeapRTV.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - descHeapRTV.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - descHeapRTV.NodeMask; - break; - } - case BindingType::UNIFORM_BUFFER: - case BindingType::STORAGE_BUFFER: - case BindingType::SAMPLED_IMAGE: { - descHeapSampler.NumDescriptors += e.Count; - descHeapSampler.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - descHeapSampler.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - descHeapSampler.NodeMask; - break; - } - case BindingType::SAMPLER: { - descHeapSampler.NumDescriptors += e.Count; - descHeapSampler.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - descHeapSampler.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; - descHeapSampler.NodeMask; - break; - } - } - } - - renderDevice->GetID3D12Device2()->CreateDescriptorHeap(&descHeapCbvSrv, __uuidof(ID3D12DescriptorHeap), reinterpret_cast(&descriptorHeapCBV_SRV_UAV)); - renderDevice->GetID3D12Device2()->CreateDescriptorHeap(&descHeapSampler, __uuidof(ID3D12DescriptorHeap), reinterpret_cast(&samplerDescriptorHeap)); - renderDevice->GetID3D12Device2()->CreateDescriptorHeap(&descHeapRTV, __uuidof(ID3D12DescriptorHeap), reinterpret_cast(&rtvDescriptorHeap)); - renderDevice->GetID3D12Device2()->CreateDescriptorHeap(&descHeapDSV, __uuidof(ID3D12DescriptorHeap), reinterpret_cast(&dsvDescriptorHeap)); - } - - //ID3D12DescriptorHeap* GetID3D12DescriptorHeap() const { return descriptorHeap; } - - struct TextureBindingUpdateInfo { - DX12Sampler Sampler; - DX12Texture Texture; - DX12TextureView TextureView; - TextureLayout TextureLayout; - FormatDescriptor FormatDescriptor; - }; - - struct BufferBindingUpdateInfo { - DX12Buffer Buffer; - GTSL::uint64 Offset, Range; - }; - - struct AccelerationStructureBindingUpdateInfo { - DX12AccelerationStructure AccelerationStructure; - }; - - union BindingUpdateInfo - { - BindingUpdateInfo(TextureBindingUpdateInfo info) : TextureBindingUpdateInfo(info) {} - BindingUpdateInfo(BufferBindingUpdateInfo info) : BufferBindingUpdateInfo(info) {} - BindingUpdateInfo(AccelerationStructureBindingUpdateInfo info) : AccelerationStructureBindingUpdateInfo(info) {} - - TextureBindingUpdateInfo TextureBindingUpdateInfo; - BufferBindingUpdateInfo BufferBindingUpdateInfo; - AccelerationStructureBindingUpdateInfo AccelerationStructureBindingUpdateInfo; - }; - - struct BindingsUpdateInfo - { - BindingType Type; - GTSL::uint32 SubsetIndex = 0, BindingIndex = 0; - GTSL::Range BindingUpdateInfos; - }; - - template - void Update(const DX12RenderDevice* renderDevice, const DX12BindingsSet* bindingsSet, GTSL::Range bindingsUpdateInfos, const ALLOCATOR& allocator) { - auto sbv_srv_uav_size = renderDevice->GetID3D12Device2()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - auto rtvHeapSize = renderDevice->GetID3D12Device2()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - auto dsvHeapSize = renderDevice->GetID3D12Device2()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - auto samplerHandleSize = renderDevice->GetID3D12Device2()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - - auto sbv_srv_uav_handle = descriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(); - - for (GTSL::uint32 index = 0; index < static_cast(bindingsUpdateInfos.ElementCount()); ++index) { - auto& info = bindingsUpdateInfos[index]; - - switch (info.Type) { - case BindingType::SAMPLER: { - for (auto e : info.BindingUpdateInfos) { - sbv_srv_uav_handle.ptr += sbv_srv_uav_size; - } - break; - } - case BindingType::COMBINED_IMAGE_SAMPLER: - case BindingType::SAMPLED_IMAGE: - case BindingType::STORAGE_IMAGE: - case BindingType::INPUT_ATTACHMENT: { - for (auto e : info.BindingUpdateInfos) { - D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; - resourceViewDesc.Texture2D.MipLevels = 1; - resourceViewDesc.Texture2D.MostDetailedMip = 0u; - resourceViewDesc.Texture2D.PlaneSlice = 0u; - resourceViewDesc.Texture2D.ResourceMinLODClamp = 0.0f; - renderDevice->GetID3D12Device2()->CreateShaderResourceView(e.TextureBindingUpdateInfo.Texture.GetID3D12Resource(), &resourceViewDesc, sbv_srv_uav_handle); - sbv_srv_uav_handle.ptr += sbv_srv_uav_size; - } - - break; - } - case BindingType::UNIFORM_TEXEL_BUFFER: GAL_DEBUG_BREAK; - case BindingType::STORAGE_TEXEL_BUFFER: GAL_DEBUG_BREAK; - case BindingType::UNIFORM_BUFFER: - case BindingType::STORAGE_BUFFER: - case BindingType::UNIFORM_BUFFER_DYNAMIC: - case BindingType::STORAGE_BUFFER_DYNAMIC: { - for (auto e : info.BindingUpdateInfos) { - D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; - resourceViewDesc.Buffer.FirstElement; - resourceViewDesc.Buffer.Flags; - resourceViewDesc.Buffer.NumElements; - resourceViewDesc.Buffer.StructureByteStride; - renderDevice->GetID3D12Device2()->CreateUnorderedAccessView(e.BufferBindingUpdateInfo.Buffer.GetID3D12Resource(), &resourceViewDesc, sbv_srv_uav_handle); - sbv_srv_uav_handle.ptr += sbv_srv_uav_size; - } - - break; - } - case BindingType::ACCELERATION_STRUCTURE: { - for (auto e : info.BindingUpdateInfos) { - D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; - resourceViewDesc.RaytracingAccelerationStructure.Location; - renderDevice->GetID3D12Device2()->CreateUnorderedAccessView(e.AccelerationStructureBindingUpdateInfo.AccelerationStructure.GetID3D12Resource(), nullptr, sbv_srv_uav_handle); - sbv_srv_uav_handle.ptr += sbv_srv_uav_size; - } - - break; - } - } - } - } - - private: - ID3D12DescriptorHeap* descriptorHeapCBV_SRV_UAV = nullptr, *samplerDescriptorHeap = nullptr, *rtvDescriptorHeap = nullptr, *dsvDescriptorHeap = nullptr; - }; -} diff --git a/src/GAL/DX12/DX12Buffer.h b/src/GAL/DX12/DX12Buffer.h deleted file mode 100644 index 043a9b32..00000000 --- a/src/GAL/DX12/DX12Buffer.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "GAL/RenderCore.h" - -#include "DX12.h" -#include "DX12Memory.h" -#include "DX12RenderDevice.h" - -namespace GAL -{ - struct MemoryRequirements; - - class DX12Buffer final { - public: - DX12Buffer() = default; - - void GetMemoryRequirements(const DX12RenderDevice* renderDevice, GTSL::uint32 size, BufferUse bufferType, MemoryRequirements* memoryRequirements) { - D3D12_RESOURCE_DESC resourceDesc; - resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - resourceDesc.Width = size; - resourceDesc.Height = 1; - resourceDesc.DepthOrArraySize = 1; - - D3D12_RESOURCE_ALLOCATION_INFO allocInfo = renderDevice->GetID3D12Device2()->GetResourceAllocationInfo(0, 1, &resourceDesc); - - memoryRequirements->Alignment = static_cast(allocInfo.Alignment); - memoryRequirements->Size = static_cast(allocInfo.SizeInBytes); - memoryRequirements->MemoryTypes = 0; - } - - void Initialize(const DX12RenderDevice* renderDevice, const MemoryRequirements& memoryRequirements, DX12Memory memory, BufferUse bufferType, GTSL::uint32 offset) { - D3D12_RESOURCE_DESC resourceDesc; - resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - resourceDesc.Width = memoryRequirements.Size; - resourceDesc.Height = 1; - resourceDesc.DepthOrArraySize = 1; - renderDevice->GetID3D12Device2()->CreatePlacedResource(memory.GetID3D12Heap(), offset, &resourceDesc, ToDX12(bufferType), nullptr, __uuidof(ID3D12Resource), reinterpret_cast(&resource)); - } - - [[nodiscard]] ID3D12Resource* GetID3D12Resource() const { return resource; } - GTSL::uint64 GetAddress() const { return static_cast(resource->GetGPUVirtualAddress()); } - GTSL::uint64 GetHandle() const { return reinterpret_cast(resource); } - - void Destroy(const DX12RenderDevice* renderDevice) { - resource->Release(); - debugClear(resource); - } - - ~DX12Buffer() = default; - - private: - ID3D12Resource* resource = nullptr; - }; -} diff --git a/src/GAL/DX12/DX12CommandList.h b/src/GAL/DX12/DX12CommandList.h deleted file mode 100644 index 787fb88c..00000000 --- a/src/GAL/DX12/DX12CommandList.h +++ /dev/null @@ -1,304 +0,0 @@ -#pragma once - -#include "DX12.h" -#include "DX12Buffer.h" -#include "DX12Framebuffer.h" -#include "DX12Pipelines.h" -#include "DX12Texture.h" -#include "DX12RenderDevice.h" -#include "GAL/CommandList.h" - -//#include - -#include "GAL/RenderCore.h" - -#include -#include - -#undef MemoryBarrier - -namespace GAL { - class DX12PipelineLayout; - struct BuildAccelerationStructuresInfo; - class DX12Pipeline; - class DX12Queue; - - class DX12CommandList final : public CommandList { - public: - DX12CommandList() = default; - - void BeginRecording(const DX12RenderDevice* renderDevice) { DX_CHECK(commandAllocator->Reset()) } - - void EndRecording(const DX12RenderDevice* renderDevice) { commandList->Close(); } - - void BeginRenderPass(const DX12RenderDevice* renderDevice, DX12RenderPass renderPass, DX12Framebuffer framebuffer, - GTSL::Extent2D renderArea, GTSL::Range renderPassTargetDescriptions) { - GTSL::StaticVector renderPassRenderTargetDescs; - D3D12_RENDER_PASS_DEPTH_STENCIL_DESC renderPassDepthStencilDesc; - - for(GTSL::uint8 i = 0; i < renderPassTargetDescriptions.ElementCount(); ++i) { - if (renderPassTargetDescriptions[i].FormatDescriptor.Type == TextureType::COLOR) { - auto& e = renderPassRenderTargetDescs.EmplaceBack(); - e.BeginningAccess.Type = ToD3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE(renderPassTargetDescriptions[i].LoadOperation); - e.BeginningAccess.Clear.ClearValue.Format = ToDX12(MakeFormatFromFormatDescriptor(renderPassTargetDescriptions[i].FormatDescriptor)); - e.BeginningAccess.Clear.ClearValue.Color[0] = renderPassTargetDescriptions[i].ClearValue.R(); - e.BeginningAccess.Clear.ClearValue.Color[1] = renderPassTargetDescriptions[i].ClearValue.G(); - e.BeginningAccess.Clear.ClearValue.Color[2] = renderPassTargetDescriptions[i].ClearValue.B(); - e.BeginningAccess.Clear.ClearValue.Color[3] = renderPassTargetDescriptions[i].ClearValue.A(); - - e.EndingAccess.Type = ToD3D12_RENDER_PASS_ENDING_ACCESS_TYPE(renderPassTargetDescriptions[i].StoreOperation); - - e.cpuDescriptor; - } else { - renderPassDepthStencilDesc.DepthBeginningAccess.Type = ToD3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE(renderPassTargetDescriptions[i].LoadOperation); - - renderPassDepthStencilDesc.DepthBeginningAccess.Clear.ClearValue.Format = ToDX12(MakeFormatFromFormatDescriptor(renderPassTargetDescriptions[i].FormatDescriptor)); - renderPassDepthStencilDesc.DepthBeginningAccess.Clear.ClearValue.DepthStencil.Depth = renderPassTargetDescriptions[i].ClearValue.R(); - - renderPassDepthStencilDesc.DepthEndingAccess.Type = ToD3D12_RENDER_PASS_ENDING_ACCESS_TYPE(renderPassTargetDescriptions[i].StoreOperation); - - renderPassDepthStencilDesc.cpuDescriptor; - } - } - - commandList->BeginRenderPass(renderPassRenderTargetDescs.GetLength(), renderPassRenderTargetDescs.begin(), &renderPassDepthStencilDesc, D3D12_RENDER_PASS_FLAG_NONE); - } - - void EndRenderPass(const DX12RenderDevice* renderDevice) { - commandList->EndRenderPass(); - } - - void ExecuteCommandLists(const DX12RenderDevice* render_device, const GTSL::Range command_lists) { - for(const auto& e : command_lists) { - commandList->ExecuteBundle(e.GetID3D12CommandList()); - } - } - - struct MemoryBarrier { - GTSL::uint32 SourceAccessFlags, DestinationAccessFlags; - }; - - struct BufferBarrier { - DX12Buffer Buffer; - AccessType SourceAccessFlags, DestinationAccessFlags; - }; - - struct TextureBarrier { - DX12Texture Texture; - - TextureLayout CurrentLayout, TargetLayout; - AccessType SourceAccessFlags, DestinationAccessFlags; - }; - - template - void AddPipelineBarrier(const DX12RenderDevice* renderDevice, GTSL::Range barriers, ShaderStage initialStage, ShaderStage finalStage, const ALLOCATOR& allocator) { - GTSL::StaticVector resourceBarriers; - - for(auto& e : barriers) { - switch (e.Type) { - case BarrierType::MEMORY: { - break; - } - case BarrierType::BUFFER: { - resourceBarriers.EmplaceBack(); - auto& resourceBarrier = resourceBarriers.back(); - - resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - - resourceBarrier.Transition.StateBefore = ToDX12(e.Barrier.BufferBarrier.SourceAccessFlags); - resourceBarrier.Transition.StateAfter = ToDX12(e.Barrier.BufferBarrier.DestinationAccessFlags); - resourceBarrier.Transition.Subresource = 0; - resourceBarrier.Transition.pResource = static_cast(e.Barrier.BufferBarrier.Buffer)->GetID3D12Resource(); - break; - } - case BarrierType::TEXTURE: { - resourceBarriers.EmplaceBack(); - auto& resourceBarrier = resourceBarriers.back(); - - resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - - resourceBarrier.Transition.StateBefore = ToDX12(e.Barrier.TextureBarrier.CurrentLayout); - resourceBarrier.Transition.StateAfter = ToDX12(e.Barrier.TextureBarrier.TargetLayout); - resourceBarrier.Transition.Subresource = 0; - resourceBarrier.Transition.pResource = static_cast(e.Barrier.TextureBarrier.Texture)->GetID3D12Resource(); - break; - } - } - } - - commandList->ResourceBarrier(resourceBarriers.GetLength(), resourceBarriers.begin()); - } - - void BindPipeline(const DX12RenderDevice* renderDevice, DX12Pipeline pipeline, ShaderStage shaderStage) const { - commandList->SetPipelineState(pipeline.GetID3D12PipelineState()); - } - - void BindIndexBuffer(const DX12RenderDevice* renderDevice, DX12Buffer buffer, const GTSL::uint32 offset, const GTSL::uint32 indexCount, IndexType indexType) const { - D3D12_INDEX_BUFFER_VIEW indexBufferView; - indexBufferView.Format = ToDX12(indexType); - indexBufferView.BufferLocation = buffer.GetID3D12Resource()->GetGPUVirtualAddress() + offset; - indexBufferView.SizeInBytes = GAL::IndexSize(indexType); - commandList->IASetIndexBuffer(&indexBufferView); - } - - void BindVertexBuffer(const DX12RenderDevice* renderDevice, const DX12Buffer buffer, const GTSL::uint32 size, const GTSL::uint32 offset, const GTSL::uint32 stride) const { - D3D12_VERTEX_BUFFER_VIEW vertexBufferView; - vertexBufferView.SizeInBytes = size; - vertexBufferView.BufferLocation = buffer.GetID3D12Resource()->GetGPUVirtualAddress() + offset; - vertexBufferView.StrideInBytes = stride; - commandList->IASetVertexBuffers(0, 1, &vertexBufferView); - } - - void UpdatePushConstant(const DX12RenderDevice* renderDevice, DX12PipelineLayout pipelineLayout, GTSL::uint32 offset, GTSL::Range data, ShaderStage shaderStages) { - if (shaderStages & (ShaderStages::VERTEX | ShaderStages::FRAGMENT | ShaderStages::RAY_GEN)) { - commandList->SetGraphicsRoot32BitConstants(0, data.Bytes() / 4, data.begin(), offset / 4); - return; - } - - if (shaderStages & (ShaderStages::COMPUTE)) { - commandList->SetComputeRoot32BitConstants(0, data.Bytes() / 4, data.begin(), offset / 4); - return; - } - } - - void DrawIndexed(const DX12RenderDevice* renderDevice, uint32_t indexCount, uint32_t instanceCount = 1) const { - commandList->DrawIndexedInstanced(indexCount, instanceCount, 0, 0, 0); - } - - void TraceRays(const DX12RenderDevice* renderDevice, GTSL::StaticVector shaderTableDescriptors, GTSL::Extent3D dispatchSize) { - D3D12_DISPATCH_RAYS_DESC dispatchRaysDesc; - dispatchRaysDesc.Width = dispatchSize.Width; dispatchRaysDesc.Height = dispatchSize.Height; dispatchRaysDesc.Depth = dispatchSize.Depth; - - dispatchRaysDesc.RayGenerationShaderRecord.StartAddress = static_cast(shaderTableDescriptors[GAL::RAY_GEN_TABLE_INDEX].Address); - dispatchRaysDesc.RayGenerationShaderRecord.SizeInBytes = static_cast(shaderTableDescriptors[GAL::RAY_GEN_TABLE_INDEX].Entries * shaderTableDescriptors[GAL::RAY_GEN_TABLE_INDEX].EntrySize); - - dispatchRaysDesc.HitGroupTable.StartAddress = static_cast(shaderTableDescriptors[GAL::HIT_TABLE_INDEX].Address); - dispatchRaysDesc.HitGroupTable.SizeInBytes = static_cast(shaderTableDescriptors[GAL::HIT_TABLE_INDEX].Entries * shaderTableDescriptors[GAL::HIT_TABLE_INDEX].EntrySize); - dispatchRaysDesc.HitGroupTable.StrideInBytes = static_cast(shaderTableDescriptors[GAL::HIT_TABLE_INDEX].EntrySize); - - dispatchRaysDesc.MissShaderTable.StartAddress = static_cast(shaderTableDescriptors[GAL::MISS_TABLE_INDEX].Address); - dispatchRaysDesc.MissShaderTable.SizeInBytes = static_cast(shaderTableDescriptors[GAL::MISS_TABLE_INDEX].Entries * shaderTableDescriptors[GAL::MISS_TABLE_INDEX].EntrySize); - dispatchRaysDesc.MissShaderTable.StrideInBytes = static_cast(shaderTableDescriptors[GAL::MISS_TABLE_INDEX].EntrySize); - - dispatchRaysDesc.CallableShaderTable.StartAddress = static_cast(shaderTableDescriptors[GAL::CALLABLE_TABLE_INDEX].Address); - dispatchRaysDesc.CallableShaderTable.SizeInBytes = static_cast(shaderTableDescriptors[GAL::CALLABLE_TABLE_INDEX].Entries * shaderTableDescriptors[GAL::CALLABLE_TABLE_INDEX].EntrySize); - dispatchRaysDesc.CallableShaderTable.StrideInBytes = static_cast(shaderTableDescriptors[GAL::CALLABLE_TABLE_INDEX].EntrySize); - - commandList->DispatchRays(&dispatchRaysDesc); - } - - void AddLabel(const DX12RenderDevice* renderDevice, GTSL::Range name) {} - - void BeginRegion(const DX12RenderDevice* renderDevice) const {} - - void EndRegion(const DX12RenderDevice* renderDevice) const {} - - void Dispatch(const DX12RenderDevice* renderDevice, GTSL::Extent3D workGroups) { - commandList->Dispatch(workGroups.Width, workGroups.Height, workGroups.Depth); - } - - void BindBindingsSets(const DX12RenderDevice* renderDevice) { - commandList->SetComputeRootDescriptorTable(0, { 0 }); - commandList->SetComputeRootUnorderedAccessView(0, 0); - commandList->SetComputeRootConstantBufferView(0, 0); - commandList->SetComputeRootShaderResourceView(0, 0); - commandList->SetComputeRootSignature(nullptr); - - commandList->SetGraphicsRootDescriptorTable(0, { 0 }); - commandList->SetGraphicsRootUnorderedAccessView(0, 0); - commandList->SetGraphicsRootConstantBufferView(0, 0); - commandList->SetGraphicsRootShaderResourceView(0, 0); - commandList->SetGraphicsRootSignature(nullptr); - } - - void CopyTextureToTexture(const DX12RenderDevice* renderDevice, const DX12Texture source, const DX12Texture destination, const GTSL::Extent3D extent, const FormatDescriptor format) { - D3D12_TEXTURE_COPY_LOCATION sourceTextureCopyLocation, destinationTextureCopyLocation; - sourceTextureCopyLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - sourceTextureCopyLocation.pResource = source.GetID3D12Resource(); - sourceTextureCopyLocation.PlacedFootprint.Footprint.Width = extent.Width; - sourceTextureCopyLocation.PlacedFootprint.Footprint.Height = extent.Height; - sourceTextureCopyLocation.PlacedFootprint.Footprint.Depth = extent.Depth; - sourceTextureCopyLocation.PlacedFootprint.Footprint.Format = ToDX12(MakeFormatFromFormatDescriptor(format)); - sourceTextureCopyLocation.PlacedFootprint.Footprint.RowPitch = 0; - sourceTextureCopyLocation.PlacedFootprint.Offset = 0; - - destinationTextureCopyLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - destinationTextureCopyLocation.pResource = destination.GetID3D12Resource(); - destinationTextureCopyLocation.PlacedFootprint.Footprint.Width = extent.Width; - destinationTextureCopyLocation.PlacedFootprint.Footprint.Height = extent.Height; - destinationTextureCopyLocation.PlacedFootprint.Footprint.Depth = extent.Depth; - destinationTextureCopyLocation.PlacedFootprint.Footprint.Format = ToDX12(MakeFormatFromFormatDescriptor(format)); - destinationTextureCopyLocation.PlacedFootprint.Footprint.RowPitch = 0; - destinationTextureCopyLocation.PlacedFootprint.Offset = 0; - - D3D12_BOX box; - box.back; - box.bottom; - box.front; - box.left; - box.right; - box.top; - - commandList->CopyTextureRegion(&destinationTextureCopyLocation, 0, 0, 0, &sourceTextureCopyLocation, &box); - } - - void CopyBufferToTexture(const DX12RenderDevice* renderDevice, const DX12Buffer source, const DX12Texture destination, const GTSL::uint32 size) { - commandList->CopyResource(destination.GetID3D12Resource(), source.GetID3D12Resource()); - } - - void CopyBuffers(const DX12RenderDevice* renderDevice, const DX12Buffer source, const DX12Buffer destination, const GTSL::uint32 size) { - commandList->CopyBufferRegion(destination.GetID3D12Resource(), 0, source.GetID3D12Resource(), 0, size); - } - - template - void BuildAccelerationStructure(const DX12RenderDevice* renderDevice, const BuildAccelerationStructuresInfo& info) const { - D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC desc; - UINT NumPostbuildInfoDescs = 0; - D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC postbuildInfoDescs; - - GTSL::Vector geomDesc; - - desc.DestAccelerationStructureData; - desc.Inputs.DescsLayout; - desc.Inputs.Flags; - desc.Inputs.InstanceDescs; - desc.Inputs.NumDescs = geomDesc.GetLength(); - desc.Inputs.pGeometryDescs = geomDesc.GetData(); - desc.Inputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; - desc.ScratchAccelerationStructureData; - desc.SourceAccelerationStructureData; - - postbuildInfoDescs.DestBuffer; - postbuildInfoDescs.InfoType; - - commandList->BuildRaytracingAccelerationStructure(&desc, NumPostbuildInfoDescs, &postbuildInfoDescs); - } - - ~DX12CommandList() = default; - - void Initialize(const DX12RenderDevice* renderDevice, DX12RenderDevice::QueueKey queue, bool isPrimary = true) { - const D3D12_COMMAND_LIST_TYPE type = isPrimary ? D3D12_COMMAND_LIST_TYPE_DIRECT : D3D12_COMMAND_LIST_TYPE_BUNDLE; - - DX_CHECK(renderDevice->GetID3D12Device2()->CreateCommandAllocator(type, __uuidof(ID3D12CommandAllocator), reinterpret_cast(commandAllocator))) - DX_CHECK(renderDevice->GetID3D12Device2()->CreateCommandList(0, type, commandAllocator, nullptr, __uuidof(ID3D12CommandList), reinterpret_cast(&commandList))) - - //setName(commandAllocator, info); - } - - [[nodiscard]] ID3D12CommandAllocator* GetID3D12CommandAllocator() const { return commandAllocator; } - [[nodiscard]] ID3D12GraphicsCommandList5* GetID3D12CommandList() const { return commandList; } - - void Destroy(const DX12RenderDevice* renderDevice) { - commandAllocator->Release(); - commandList->Release(); - debugClear(commandAllocator); - debugClear(commandList); - } - - private: - ID3D12CommandAllocator* commandAllocator = nullptr; - ID3D12GraphicsCommandList5* commandList = nullptr; - }; -} diff --git a/src/GAL/DX12/DX12Memory.h b/src/GAL/DX12/DX12Memory.h deleted file mode 100644 index af3d32e3..00000000 --- a/src/GAL/DX12/DX12Memory.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "DX12.h" -#include "DX12RenderDevice.h" - -namespace GAL -{ - class DX12Memory final - { - public: - DX12Memory() = default; - - void Initialize(const DX12RenderDevice* renderDevice, const GTSL::Range name, AllocationFlag flags, GTSL::uint32 size, MemoryType memoryType) { - D3D12_HEAP_DESC heapDesc; - heapDesc.Flags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED; - heapDesc.Alignment = 1024; - heapDesc.SizeInBytes = size; - heapDesc.Properties.CreationNodeMask = 0; - heapDesc.Properties.VisibleNodeMask = 0; - heapDesc.Properties.Type = memoryType & MemoryTypes::GPU ? D3D12_HEAP_TYPE_DEFAULT : D3D12_HEAP_TYPE_UPLOAD; - heapDesc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - heapDesc.Properties.MemoryPoolPreference = !(memoryType & MemoryTypes::HOST_VISIBLE) ? D3D12_MEMORY_POOL_L1 : D3D12_MEMORY_POOL_L0; - - DX_CHECK(renderDevice->GetID3D12Device2()->CreateHeap(&heapDesc, __uuidof(ID3D12Heap), reinterpret_cast(&heap))); - setName(heap, name); - } - - void Destroy(const DX12RenderDevice* renderDevice) { - heap->Release(); - debugClear(heap); - } - - [[nodiscard]] ID3D12Heap* GetID3D12Heap() const { return heap; } - - ~DX12Memory() = default; - - private: - ID3D12Heap* heap = nullptr; - }; -} diff --git a/src/GAL/DX12/DX12Pipelines.h b/src/GAL/DX12/DX12Pipelines.h deleted file mode 100644 index f6fbf75b..00000000 --- a/src/GAL/DX12/DX12Pipelines.h +++ /dev/null @@ -1,219 +0,0 @@ -#pragma once - -#include "DX12.h" -#include "DX12RenderDevice.h" -#include "GAL/Pipelines.h" -#include "GAL/RenderCore.h" - -#include -#include - -#include "GTSL/Vector.hpp" - -namespace GAL -{ - class DX12Buffer; - class DX12Sampler; - class DX12TextureView; - - struct DX12PipelineDescriptor - { - CullMode CullMode = CullMode::CULL_NONE; - bool DepthClampEnable = false; - bool BlendEnable = false; - BlendOperation ColorBlendOperation = BlendOperation::ADD; - SampleCount RasterizationSamples = SampleCount::SAMPLE_COUNT_1; - bool DepthTest = false; - bool DepthWrite = false; - CompareOperation DepthCompareOperation = CompareOperation::NEVER; - bool StencilTest = false; - StencilOperations StencilOperations; - }; - - struct DX12ShaderInfo - { - ShaderType Type; - const class DX12Shader* Shader = nullptr; - GTSL::Range ShaderData; - }; - - class DX12PipelineLayout final { - public: - DX12PipelineLayout() = default; - - struct BindingDescriptor - { - BindingType BindingType; - ShaderStage ShaderStage; - GTSL::uint32 UniformCount = 0; - BindingFlag Flags; - }; - - struct ImageBindingDescriptor : BindingDescriptor - { - GTSL::Range ImageViews; - GTSL::Range Samplers; - GTSL::Range Layouts; - }; - - struct BufferBindingDescriptor : BindingDescriptor - { - GTSL::Range Buffers; - GTSL::Range Offsets; - GTSL::Range Sizes; - }; - - void Initialize(const DX12RenderDevice* renderDevice, const PushConstant* pushConstant, const GTSL::Range bindingsSetLayouts) { - GTSL::StaticVector rootParameters; - - //if (pushConstant) { - // auto& pushConstant = rootParameters.EmplaceBack(); - // pushConstant.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - // pushConstant.ShaderVisibility = ToDX12(pushConstant->Stage); - // pushConstant.Constants.Num32BitValues = pushConstant->NumberOf4ByteSlots; - // pushConstant.Constants.RegisterSpace = 0; - // pushConstant.Constants.ShaderRegister = 0; - //} - // - //for (GTSL::uint32 i = 0; i < info.BindingsDescriptors.ElementCount(); ++i) { - // D3D12_ROOT_PARAMETER rootParameter; - // rootParameter.ParameterType; - // rootParameter.ShaderVisibility; - // rootParameter.Constants; - // rootParameter.Descriptor; - // rootParameter.DescriptorTable; - // rootParameters.EmplaceBack(rootParameter); - //} - - D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc; - rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; - rootSignatureDesc.NumParameters = rootParameters.GetLength(); - rootSignatureDesc.pParameters = rootParameters.begin(); - rootSignatureDesc.NumStaticSamplers = 0; - rootSignatureDesc.pStaticSamplers = nullptr; - DX_CHECK(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1_1, nullptr, nullptr)); - DX_CHECK(renderDevice->GetID3D12Device2()->CreateRootSignature(0, nullptr, 0, __uuidof(ID3D12RootSignature), nullptr)); - setName(rootSignature, {}); - } - - void Destroy(const DX12RenderDevice* renderDevice) { - rootSignature->Release(); - debugClear(rootSignature); - } - - ~DX12PipelineLayout() = default; - - private: - ID3D12RootSignature* rootSignature = nullptr; - }; - - class DX12PipelineCache : public PipelineCache { - - }; - - class DX12Pipeline : public Pipeline { - public: - void Destroy(const DX12RenderDevice* renderDevice) { - pipelineState->Release(); - debugClear(pipelineState); - } - - [[nodiscard]] ID3D12PipelineState* GetID3D12PipelineState() const { return pipelineState; } - - protected: - ID3D12PipelineState* pipelineState = nullptr; - }; - - class DX12RasterPipeline final : public DX12Pipeline - { - public: - DX12RasterPipeline() = default; - - struct CreateInfo final { - const class VulkanRenderPass* RenderPass = nullptr; - GTSL::Extent2D SurfaceExtent; - GTSL::Range VertexDescriptor; - DX12PipelineDescriptor PipelineDescriptor; - GTSL::Range Stages; - bool IsInheritable = false; - const DX12PipelineLayout* PipelineLayout = nullptr; - const DX12RasterPipeline* ParentPipeline = nullptr; - const class DX12PipelineCache* PipelineCache = nullptr; - GTSL::uint32 SubPass = 0; - }; - void Initialize(const DX12RenderDevice* render_device, const CreateInfo& info) { - GTSL::Buffer> buffer(1024, 16); - //buffer.Allocate(1024, 8, allocator); - - GTSL::StaticVector vertexElements; - - D3D12_PIPELINE_STATE_SUBOBJECT_TYPE type; - - { - { - for (GTSL::uint32 i = 0; i < info.Stages.ElementCount(); ++i) - { - switch (info.Stages[i].Type) - { - case ShaderType::VERTEX: type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS; break; - case ShaderType::TESSELLATION_CONTROL: type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS; break; - case ShaderType::TESSELLATION_EVALUATION: type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS; break; - case ShaderType::GEOMETRY: type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS; break; - case ShaderType::FRAGMENT: type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS; break; - case ShaderType::COMPUTE: type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS; break; - default: type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID; - } - - buffer.CopyBytes(sizeof(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE), reinterpret_cast(&type)); - D3D12_SHADER_BYTECODE bytecode; - bytecode.BytecodeLength = info.Stages[i].ShaderData.ElementCount(); - bytecode.pShaderBytecode = info.Stages[i].ShaderData.begin(); - buffer.CopyBytes(sizeof(D3D12_SHADER_BYTECODE), reinterpret_cast(&bytecode)); - } - } - - { - type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT; - buffer.CopyBytes(sizeof(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE), reinterpret_cast(&type)); - - D3D12_INPUT_LAYOUT_DESC inputLayoutDesc; - inputLayoutDesc.NumElements = static_cast(info.VertexDescriptor.ElementCount()); - - GTSL::uint32 offset = 0; - - for (GTSL::uint32 i = 0; i < inputLayoutDesc.NumElements; ++i) - { - - D3D12_INPUT_ELEMENT_DESC elementDesc; - elementDesc.Format = ToDX12(info.VertexDescriptor[i].Type); - elementDesc.AlignedByteOffset = offset; - elementDesc.SemanticIndex = 0; - elementDesc.InputSlot = i; - elementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; - elementDesc.InstanceDataStepRate = 0; - - offset += ShaderDataTypesSize(info.VertexDescriptor[i].Type); - - elementDesc.SemanticName = reinterpret_cast(info.VertexDescriptor[i].Identifier.begin()); - vertexElements.EmplaceBack(elementDesc); - } - - inputLayoutDesc.pInputElementDescs = vertexElements.begin(); - buffer.CopyBytes(sizeof(D3D12_INPUT_LAYOUT_DESC), reinterpret_cast(&inputLayoutDesc)); - } - } - - D3D12_PIPELINE_STATE_STREAM_DESC pipelineStateStream; - pipelineStateStream.SizeInBytes = buffer.GetLength(); - pipelineStateStream.pPipelineStateSubobjectStream = buffer.GetData(); - - render_device->GetID3D12Device2()->CreatePipelineState(&pipelineStateStream, __uuidof(ID3D12PipelineState), reinterpret_cast(&pipelineState)); - //setName(pipelineState, info.Name); - } - - ~DX12RasterPipeline() = default; - - private: - - }; -} diff --git a/src/GAL/DX12/DX12QueryPool.h b/src/GAL/DX12/DX12QueryPool.h deleted file mode 100644 index 2aef017f..00000000 --- a/src/GAL/DX12/DX12QueryPool.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace GAL { - class DX12QueryPool { - - }; -} \ No newline at end of file diff --git a/src/GAL/DX12/DX12Queue.h b/src/GAL/DX12/DX12Queue.h deleted file mode 100644 index 36787e69..00000000 --- a/src/GAL/DX12/DX12Queue.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "GAL/Queue.h" -#include "DX12CommandList.h" -#include "DX12Synchronization.h" - -namespace GAL { - class DX12Queue final : public Queue - { - public: - DX12Queue() = default; - - void Initialize(const DX12RenderDevice* renderDevice, DX12RenderDevice::QueueKey queueKey) { - D3D12_COMMAND_QUEUE_DESC desc; - desc.Type = ToDX12(queueKey.Type); - desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH; - desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - desc.NodeMask = 0; - - DX_CHECK(renderDevice->GetID3D12Device2()->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue), reinterpret_cast(&commandQueue))); - } - - void Submit(const GTSL::Range*> submitInfos, const DX12Fence fence) const { - for(auto& s : submitInfos) { - GTSL::StaticVector commandLists; - - for(auto& e : s) { - commandLists.EmplaceBack(static_cast(e.CommandBuffer)->GetID3D12CommandList()); - } - - commandQueue->ExecuteCommandLists(commandLists.GetLength(), commandLists.begin()); - } - } - - void Wait(const DX12RenderDevice* renderDevice) const { - ID3D12Fence* fence; - - renderDevice->GetID3D12Device2()->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), - reinterpret_cast(&fence)); - - commandQueue->Wait(fence, 1); - - fence->Release(); - } - - ~DX12Queue() { - commandQueue->Release(); - debugClear(commandQueue); - } - - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(commandQueue); } - [[nodiscard]] ID3D12CommandQueue* GetID3D12CommandQueue() const { return commandQueue; } - - private: - ID3D12CommandQueue* commandQueue = nullptr; - - friend class DX12RenderDevice; - }; -} diff --git a/src/GAL/DX12/DX12RenderContext.h b/src/GAL/DX12/DX12RenderContext.h deleted file mode 100644 index f2e86490..00000000 --- a/src/GAL/DX12/DX12RenderContext.h +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include "DX12.h" -#include - -#include "DX12Queue.h" -#include "GAL/RenderContext.h" -#include "GAL/RenderCore.h" -#include "GTSL/Extent.h" -#include "GAL/DX12/DX12RenderDevice.h" -#include - -#include "GTSL/Application.h" -#include "GTSL/Window.h" - -namespace GAL -{ - class DX12Queue; - - class DX12Surface - { - public: - void Initialize(const DX12RenderDevice* render_device, const GTSL::Application& application, const GTSL::Window& window) { - handle = window.GetHWND(); - } - - [[nodiscard]] HWND GetHWND() const { return handle; } - private: - HWND handle = nullptr; - }; - - class DX12RenderContext - { - public: - DX12RenderContext() = default; - - bool InitializeOrRecreate(const DX12RenderDevice* renderDevice, const DX12Queue queue, const DX12Surface surface, GTSL::Extent2D extent, FormatDescriptor format, ColorSpace colorSpace, - TextureUse textureUse, PresentModes presentMode, GTSL::uint8 desiredFramesInFlight) { - - if(swapChain4) { - return swapChain4->ResizeBuffers(desiredFramesInFlight, extent.Width, extent.Height, ToDX12(format), tear ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0) == S_OK; - } - - IDXGIFactory4* factory4; GTSL::uint32 factoryFlags = 0; - - if constexpr (_DEBUG) { - factoryFlags |= DXGI_CREATE_FACTORY_DEBUG; - } - - DX_CHECK(CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory4), reinterpret_cast(&factory4))); - - BOOL allowTearing = false; - - { - IDXGIFactory5* factory5; - - if (factory4->QueryInterface(__uuidof(IDXGIFactory5), reinterpret_cast(&factory5)) >= 0) { - factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing)); - } - - factory5->Release(); - } - - vSync = presentMode == PresentModes::SWAP ? true : false; - tear = static_cast(allowTearing); - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc{}; - swapChainDesc.Width = extent.Width; - swapChainDesc.Height = extent.Height; - swapChainDesc.Format = ToDX12(format); - swapChainDesc.Stereo = FALSE; - swapChainDesc.SampleDesc = { 1, 0 }; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.BufferCount = desiredFramesInFlight; - swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; - // It is recommended to always allow tearing if tearing support is available. - swapChainDesc.Flags |= tear ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; - - IDXGISwapChain1* swapChain1; - - DX_CHECK(factory4->CreateSwapChainForHwnd(queue.GetID3D12CommandQueue(), static_cast(surface.GetHWND()), &swapChainDesc, nullptr, nullptr, &swapChain1)) - - DX_CHECK(factory4->MakeWindowAssociation(static_cast(surface.GetHWND()), DXGI_MWA_NO_ALT_ENTER)) - - DX_CHECK(swapChain1->QueryInterface(__uuidof(IDXGISwapChain4), reinterpret_cast(&swapChain4))) - - swapChain1->Release(); - - factory4->Release(); - - return true; - } - - void Destroy(const DX12RenderDevice* renderDevice) { - swapChain4->Release(); - debugClear(swapChain4); - } - - //When you call IDXGISwapChain1::Present1 on a full - screen application, the swap chain flips(as opposed to blits) the contents of the back buffer - //to the front buffer.This requires that the swap chain was created by using an enumerated display mode(specified in DXGI_SWAP_CHAIN_DESC1). - //If you fail to enumerate display modes, or incorrectly specify the display mode in the description, the swap chain may perform a bit - block transfer(bitblt) instead. - //The bitblt causes an extra stretching copy as well as some increased video memory usage, and is difficult to detect.To avoid this problem, enumerate display modes, - //and initialize the swap chain description correctly before you create the swap chain.This will ensure maximum performance when flipping in full - screen mode - //and avoid the extra memory overhead. - void Present(const DX12RenderDevice* renderDevice, GTSL::Range waitSemaphores, GTSL::uint32 imageIndex, DX12Queue queue) { - UINT flags = 0; flags |= tear ? DXGI_PRESENT_ALLOW_TEARING : 0; - - RECT rect; - - HWND hwnd; - swapChain4->GetHwnd(&hwnd); - - GetClientRect(hwnd, &rect); - - DXGI_PRESENT_PARAMETERS presentParameters; - presentParameters.DirtyRectsCount = 1; - presentParameters.pDirtyRects = ▭ - presentParameters.pScrollOffset = nullptr; - presentParameters.pScrollRect = nullptr; - - swapChain4->Present1(vSync && !tear, flags, &presentParameters); - } - private: - IDXGISwapChain4* swapChain4 = nullptr; bool vSync = false; bool tear = false; - }; -} diff --git a/src/GAL/DX12/DX12RenderDevice.h b/src/GAL/DX12/DX12RenderDevice.h deleted file mode 100644 index aa71c58f..00000000 --- a/src/GAL/DX12/DX12RenderDevice.h +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include "GAL/RenderDevice.h" - -#include "DX12.h" - -#include "GTSL/Delegate.hpp" -#include "GTSL/Range.hpp" -#include - -namespace GAL -{ - class DX12RenderDevice : public RenderDevice - { - public: - void Initialize(const CreateInfo& info) { - IDXGIFactory4* factory4; GTSL::uint32 factoryFlags = 0; - - if constexpr (_DEBUG) { - if (info.Debug) { - factoryFlags |= DXGI_CREATE_FACTORY_DEBUG; - } - } - - DX_CHECK(CreateDXGIFactory2(factoryFlags, IID_IDXGIFactory4, reinterpret_cast(&factory4))) - - IDXGIAdapter1* adapter1 = nullptr; - - { - SIZE_T maxDedicatedVideoMemory = 0; - for (UINT i = 0; factory4->EnumAdapters1(i, &adapter1) != DXGI_ERROR_NOT_FOUND; ++i) { - DXGI_ADAPTER_DESC1 dxgiAdapterDesc1; - adapter1->GetDesc1(&dxgiAdapterDesc1); - - // Check to see if the adapter can create a D3D12 device without actually - // creating it. The adapter with the largest dedicated video memory - // is favored. - if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 && SUCCEEDED(D3D12CreateDevice(adapter1, D3D_FEATURE_LEVEL_12_1, IID_ID3D12Device2, nullptr)) && dxgiAdapterDesc1.DedicatedVideoMemory > maxDedicatedVideoMemory) { - maxDedicatedVideoMemory = dxgiAdapterDesc1.DedicatedVideoMemory; - } - } - - adapter1->QueryInterface(__uuidof(IDXGIAdapter4), reinterpret_cast(&adapter4)); - DX_CHECK(D3D12CreateDevice(adapter4, D3D_FEATURE_LEVEL_12_1, IID_ID3D12Device2, reinterpret_cast(&device))) - //setName(device, info); - } - - if constexpr (_DEBUG) { - ID3D12InfoQueue* infoQueue; - DX_CHECK(device->QueryInterface(IID_ID3D12InfoQueue, reinterpret_cast(&infoQueue))); - - infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); - infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); - infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true); - - // Suppress whole categories of messages - //D3D12_MESSAGE_CATEGORY Categories[] = {}; - - // Suppress messages based on their severity level - D3D12_MESSAGE_SEVERITY severities[] = { - D3D12_MESSAGE_SEVERITY_INFO - }; - - // Suppress individual messages by their ID - D3D12_MESSAGE_ID denyIds[] = { - D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE, // I'm really not sure how to avoid this message. - D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, // This warning occurs when using capture frame while graphics debugging. - D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE, // This warning occurs when using capture frame while graphics debugging. - }; - - D3D12_INFO_QUEUE_FILTER infoQueueFilter = {}; - //NewFilter.DenyList.NumCategories = _countof(Categories); - //NewFilter.DenyList.pCategoryList = Categories; - infoQueueFilter.DenyList.NumSeverities = _countof(severities); - infoQueueFilter.DenyList.pSeverityList = severities; - infoQueueFilter.DenyList.NumIDs = _countof(denyIds); - infoQueueFilter.DenyList.pIDList = denyIds; - - DX_CHECK(infoQueue->PushStorageFilter(&infoQueueFilter)) - - infoQueue->Release(); - } - - for (GTSL::uint32 i = 0; i < info.QueueKeys.ElementCount(); ++i) { - info.QueueKeys[i].Type = info.Queues[i]; - } - } - - GPUInfo GetInfo() { - DXGI_ADAPTER_DESC3 dxgiAdapterDesc3; - adapter4->GetDesc3(&dxgiAdapterDesc3); - - GPUInfo result; - - result.APIVersion = (uint32)dxgiAdapterDesc3.AdapterLuid.HighPart; - result.DriverVersion = dxgiAdapterDesc3.DeviceId; - - char8_t name[512]{ u8'\0' }; - - WideCharToMultiByte(CP_UTF8, 0, dxgiAdapterDesc3.Description, 0, reinterpret_cast(name), 512, 0, 0); - result.GPUName = name; - result.PipelineCacheUUID[0] = static_cast(dxgiAdapterDesc3.DeviceId << 0); - result.PipelineCacheUUID[1] = static_cast(dxgiAdapterDesc3.DeviceId << 8); - result.PipelineCacheUUID[2] = static_cast(dxgiAdapterDesc3.DeviceId << 16); - result.PipelineCacheUUID[3] = static_cast(dxgiAdapterDesc3.DeviceId << 24); - - return result; - } - - ~DX12RenderDevice() { - device->Release(); - debug->Release(); - adapter4->Release(); - - debugClear(device); - - if constexpr (_DEBUG) { - debugClear(debug); - } - } - - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(device); } - [[nodiscard]] ID3D12Device2* GetID3D12Device2() const { return device; } - - private: - ID3D12Device2* device = nullptr; - IDXGIAdapter4* adapter4 = nullptr; - -#if (_DEBUG) - ID3D12Debug* debug = nullptr; -#endif - }; -} diff --git a/src/GAL/DX12/DX12RenderPass.h b/src/GAL/DX12/DX12RenderPass.h deleted file mode 100644 index 7acebe6f..00000000 --- a/src/GAL/DX12/DX12RenderPass.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "GAL/RenderPass.h" - -namespace GAL { - class DX12RenderDevice; - - class DX12RenderPass final : public RenderPass { - void Initialize(const DX12RenderDevice* renderDevice, GTSL::Range renderPassAttachments, - GTSL::Range subPasses, const GTSL::Range subPassDependencies) { - } - - void Destroy(const DX12RenderDevice* renderDevice) {} - }; -} diff --git a/src/GAL/DX12/DX12Synchronization.h b/src/GAL/DX12/DX12Synchronization.h deleted file mode 100644 index cc97750c..00000000 --- a/src/GAL/DX12/DX12Synchronization.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "DX12.h" -#include "DX12RenderDevice.h" - -#include "GAL/Synchronization.h" - -namespace GAL { - class DX12Synchronizer : public Synchronizer { - public: - DX12Synchronizer() = default; - - void Initialize(const DX12RenderDevice* renderDevice, Type syncType, bool isSignaled = false, uint64_t initialValue = ~0ULL) { - SyncType = syncType; - - renderDevice->GetID3D12Device2()->CreateFence(initialValue, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), reinterpret_cast(&fence)); - } - - void Wait(const DX12RenderDevice* renderDevice) const { - const auto event = CreateEventA(nullptr, false, false, nullptr); - fence->SetEventOnCompletion(1, event); - - WaitForSingleObject(event, 0xFFFFFFFF); - } - - void Destroy(const DX12RenderDevice* renderDevice) { - fence->Release(); - debugClear(fence); - } - - private: - Type SyncType; - ID3D12Fence* fence = nullptr; - - }; -} diff --git a/src/GAL/DX12/DX12Texture.h b/src/GAL/DX12/DX12Texture.h deleted file mode 100644 index a89c3116..00000000 --- a/src/GAL/DX12/DX12Texture.h +++ /dev/null @@ -1,125 +0,0 @@ -#pragma once - -#include "GAL/RenderCore.h" - -#include "DX12.h" -#include -#include "DX12Memory.h" -#include "DX12RenderDevice.h" -#include "GAL/Texture.h" - -namespace GAL -{ - class DX12Texture final : public Texture - { - public: - DX12Texture() = default; - - void GetMemoryRequirements(const DX12RenderDevice* renderDevice, MemoryRequirements* memoryRequirements, TextureLayout initialLayout, TextureUse uses, - FormatDescriptor format, const GTSL::Extent3D extent, const Tiling tiling, GTSL::uint8 mipLevels) { - D3D12_RESOURCE_DESC resourceDesc; - resourceDesc.Width = extent.Width; resourceDesc.Height = extent.Height; resourceDesc.DepthOrArraySize = extent.Depth; - resourceDesc.Dimension = ToDX12Type(extent); - resourceDesc.Layout = ToDX12(tiling); - resourceDesc.Format = ToDX12(MakeFormatFromFormatDescriptor(format)); - resourceDesc.MipLevels = mipLevels; - resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; - - const auto allocInfo = renderDevice->GetID3D12Device2()->GetResourceAllocationInfo(0, 1, &resourceDesc); - - memoryRequirements->Alignment = static_cast(allocInfo.Alignment); - memoryRequirements->Size = static_cast(allocInfo.SizeInBytes); - memoryRequirements->MemoryTypes = 0; - } - - void Initialize(const DX12RenderDevice* renderDevice, const MemoryRequirements& memoryRequirements, - const DX12Memory deviceMemory, const GTSL::Extent3D extent, const TextureUse uses, - const FormatDescriptor format, const Tiling tiling, const GTSL::uint32 offset) { - D3D12_RESOURCE_DESC resourceDesc; - resourceDesc.Width = extent.Width; - resourceDesc.Height = extent.Height; - resourceDesc.DepthOrArraySize = extent.Depth; - resourceDesc.Dimension = ToDX12Type(extent); - resourceDesc.Layout = ToDX12(tiling); - resourceDesc.Format = ToDX12(MakeFormatFromFormatDescriptor(format)); - resourceDesc.Alignment = memoryRequirements.Alignment; - resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; - - resourceDesc.SampleDesc.Count = 1; - resourceDesc.SampleDesc.Quality = 0; - - DX_CHECK(renderDevice->GetID3D12Device2()->CreatePlacedResource(deviceMemory.GetID3D12Heap(), offset, & - resourceDesc, ToDX12(uses, format), nullptr, __uuidof(ID3D12Resource), reinterpret_cast(&resource))); - //setName(resource, info); - } - - void Destroy(const DX12RenderDevice* renderDevice) { - resource->Release(); - debugClear(resource); - } - - [[nodiscard]] ID3D12Resource* GetID3D12Resource() const { return resource; } - - ~DX12Texture() = default; - - private: - ID3D12Resource* resource = nullptr; - }; - - class DX12TextureView final { - public: - DX12TextureView() = default; - - void Initialize(const DX12RenderDevice* renderDevice, const GTSL::Range name, const DX12Texture texture, const FormatDescriptor formatDescriptor, const GTSL::Extent3D extent, const GTSL::uint8 mipLevels) { - D3D12_CPU_DESCRIPTOR_HANDLE cpu_descriptor_handle; - - D3D12_UNORDERED_ACCESS_VIEW_DESC unordered_access_view_desc; - unordered_access_view_desc.Format = ToDX12(MakeFormatFromFormatDescriptor(formatDescriptor)); - unordered_access_view_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - unordered_access_view_desc.Texture2D.MipSlice = 0; - unordered_access_view_desc.Texture2D.PlaneSlice = 0; - renderDevice->GetID3D12Device2()->CreateUnorderedAccessView(nullptr, nullptr, &unordered_access_view_desc, cpu_descriptor_handle); - - D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc; - shader_resource_view_desc.Format = ToDX12(MakeFormatFromFormatDescriptor(formatDescriptor)); - shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - shader_resource_view_desc.Texture2D.PlaneSlice = 0; - shader_resource_view_desc.Texture2D.MipLevels = 1; - shader_resource_view_desc.Texture2D.MostDetailedMip = 0; - shader_resource_view_desc.Texture2D.ResourceMinLODClamp = 0.0f; - - renderDevice->GetID3D12Device2()->CreateShaderResourceView(texture.GetID3D12Resource(), &shader_resource_view_desc, {}); - } - - - - private: - ID3D12Resource* tex_2d = nullptr; - }; - - class DX12Sampler final { - public: - DX12Sampler() = default; - - void Initialize(const DX12RenderDevice* renderDevice, const GTSL::uint8 anisotropy) { - D3D12_SAMPLER_DESC samplerDesc; - samplerDesc.MaxAnisotropy = anisotropy; - samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; - samplerDesc.Filter = D3D12_FILTER_ANISOTROPIC; - samplerDesc.MaxLOD = 0.0f; - samplerDesc.MinLOD = 0.0f; - samplerDesc.MipLODBias = 0.0f; - renderDevice->GetID3D12Device2()->CreateSampler(&samplerDesc, sampler); - } - - private: - D3D12_CPU_DESCRIPTOR_HANDLE sampler; - }; -} diff --git a/src/GAL/Framebuffer.h b/src/GAL/Framebuffer.h deleted file mode 100644 index fc3a92ca..00000000 --- a/src/GAL/Framebuffer.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -namespace GAL -{ - class Framebuffer - { - public: - Framebuffer() = default; - - ~Framebuffer() = default; - }; -} diff --git a/src/GAL/Memory.h b/src/GAL/Memory.h deleted file mode 100644 index 4dd1d6a1..00000000 --- a/src/GAL/Memory.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace GAL -{ - class DeviceMemory - { - public: - DeviceMemory() = default; - }; -} diff --git a/src/GAL/Pipelines.h b/src/GAL/Pipelines.h deleted file mode 100644 index 6ae2200d..00000000 --- a/src/GAL/Pipelines.h +++ /dev/null @@ -1,283 +0,0 @@ -#pragma once - -#include "RenderCore.h" -#include -#include -#include -#include - -#include "GTSL/Buffer.hpp" -#include "GTSL/ShortString.hpp" - -#if BE_PLATFORM_WINDOWS -#include -#include -#endif - -namespace GAL -{ - struct StencilOperations - { - struct StencilState - { - StencilCompareOperation FailOperation = StencilCompareOperation::ZERO; - StencilCompareOperation PassOperation = StencilCompareOperation::ZERO; - StencilCompareOperation DepthFailOperation = StencilCompareOperation::ZERO; - CompareOperation compareOperation = CompareOperation::NEVER; - GTSL::uint32 CompareMask; - GTSL::uint32 WriteMask; - GTSL::uint32 Reference; - } Front, Back; - }; - - class Shader - { - public: - }; - - class RenderPass; - - struct PushConstant { - GTSL::uint32 NumberOf4ByteSlots = 0; - ShaderStage Stage; - }; - - class Pipeline { - public: - - static constexpr GTSL::uint8 MAX_VERTEX_ELEMENTS = 20; - - struct VertexElement { - GTSL::ShortString<32> Identifier; - ShaderDataType Type; - uint8 Location = 0xFF; - }; - - static constexpr auto POSITION = GTSL::ShortString<32>(u8"POSITION"); - static constexpr auto NORMAL = GTSL::ShortString<32>(u8"NORMAL"); - static constexpr auto TANGENT = GTSL::ShortString<32>(u8"TANGENT"); - static constexpr auto BITANGENT = GTSL::ShortString<32>(u8"BITANGENT"); - static constexpr auto TEXTURE_COORDINATES = GTSL::ShortString<32>(u8"TEXTURE_COORDINATES"); - static constexpr auto COLOR = GTSL::ShortString<32>(u8"COLOR"); - - struct RayTraceGroup { - static constexpr GTSL::uint32 SHADER_UNUSED = (~0U); - - ShaderGroupType ShaderGroup; - GTSL::uint32 GeneralShader = SHADER_UNUSED; - GTSL::uint32 ClosestHitShader = SHADER_UNUSED; - GTSL::uint32 AnyHitShader = SHADER_UNUSED; - GTSL::uint32 IntersectionShader = SHADER_UNUSED; - }; - - struct PipelineStateBlock { - struct ViewportState { - GTSL::uint8 ViewportCount = 0; - }; - - struct RasterState { - WindingOrder windingOrder = WindingOrder::CLOCKWISE; - CullMode cullMode = CullMode::CULL_BACK; - }; - - struct DepthState { - CompareOperation compareOperation = CompareOperation::LESS; - }; - - struct RenderContext { - struct AttachmentState { - FormatDescriptor Format; - bool BlendEnable = true; - }; - - GTSL::Range Attachments; - //const RenderPass* RenderPass = nullptr; - //GTSL::uint8 SubPassIndex = 0; - }; - - struct VertexState { - GTSL::Range*> VertexStreams; - }; - - struct RayTracingState { - GTSL::Range Groups; - GTSL::uint8 MaxRecursionDepth; - }; - - struct SpecializationData { - struct SpecializationEntry { - uint64 Size, Offset, ID; - }; - - GTSL::Range Entries; - GTSL::Range Data; - }; - - union { - ViewportState Viewport; - RasterState Raster; - DepthState Depth; - RenderContext Context; - VertexState Vertex; - RayTracingState RayTracing; - SpecializationData Specialization; - }; - - enum class StateType { - VIEWPORT_STATE, RASTER_STATE, DEPTH_STATE, COLOR_BLEND_STATE, VERTEX_STATE, RAY_TRACE_GROUPS, SPECIALIZATION - } Type; - - PipelineStateBlock() = default; - PipelineStateBlock(const RasterState& rasterState) : Raster(rasterState), Type(StateType::RASTER_STATE) {} - PipelineStateBlock(const DepthState& depth) : Depth(depth), Type(StateType::DEPTH_STATE) {} - PipelineStateBlock(const RenderContext& renderContext) : Context(renderContext), Type(StateType::COLOR_BLEND_STATE) {} - PipelineStateBlock(const VertexState& vertexState) : Vertex(vertexState), Type(StateType::VERTEX_STATE) {} - PipelineStateBlock(const ViewportState& viewportState) : Viewport(viewportState), Type(StateType::VIEWPORT_STATE) {} - PipelineStateBlock(const RayTracingState& rayTracingGroups) : RayTracing(rayTracingGroups), Type(StateType::RAY_TRACE_GROUPS) {} - PipelineStateBlock(const SpecializationData& specialization_data) : Specialization(specialization_data), Type(StateType::SPECIALIZATION) {} - }; - - //struct ShaderInfo - //{ - // ShaderType Type = ShaderType::VERTEX_SHADER; - // const Shader* Shader = nullptr; - //}; - }; - - class PipelineCache { - public: - private: - }; - - class GraphicsPipeline : public Pipeline { - public: - - GraphicsPipeline() = default; - - static GTSL::uint32 GetVertexSize(GTSL::Range vertex) { - GTSL::uint32 size{ 0 }; for (const auto& e : vertex) { size += ShaderDataTypesSize(e); } return size; - } - - static GTSL::uint32 GetByteOffsetToMember(const GTSL::uint8 member, GTSL::Range vertex) { - GTSL::uint32 offset{ 0 }; - for (GTSL::uint8 i = 0; i < member; ++i) { offset += ShaderDataTypesSize(vertex[i]); } - return offset; - } - }; - - class ComputePipeline : public Pipeline { - public: - }; - - template - std::tuple, GTSL::Buffer> CompileShader2(GTSL::Range code, GTSL::Range shaderName, ShaderType shaderType, ShaderLanguage shaderLanguage, const ALLOCATOR& allocator) { -#if BE_PLATFORM_WINDOWS - IDxcUtils* pUtils; - DxcCreateInstance(CLSID_DxcUtils, __uuidof(IDxcUtils), reinterpret_cast(&pUtils)); - IDxcBlobEncoding* pSource; - //pUtils->CreateBlob(pShaderSource, shaderSourceSize, CP_UTF8, pSource.GetAddressOf()); - - GTSL::Vector arguments; - //-E for the entry point (eg. PSMain) - arguments.EmplaceBack(L"-E"); - arguments.EmplaceBack(L"main"); - - //-T for the target profile (eg. ps_6_2) - arguments.EmplaceBack(L"-T"); - - switch (shaderType) { - case ShaderType::VERTEX: arguments.EmplaceBack(L"vs_6_5"); break; - case ShaderType::TESSELLATION_CONTROL: break; - case ShaderType::TESSELLATION_EVALUATION: break; - case ShaderType::GEOMETRY: break; - case ShaderType::FRAGMENT: arguments.EmplaceBack(L"ps_6_5"); break; - case ShaderType::COMPUTE: arguments.EmplaceBack(L"cs_6_5"); break; - case ShaderType::TASK: arguments.EmplaceBack(L"ts_6_2"); break; - case ShaderType::MESH: arguments.EmplaceBack(L"ms_6_2"); break; - case ShaderType::RAY_GEN: arguments.EmplaceBack(L"lib_6_5"); break; - case ShaderType::CLOSEST_HIT: arguments.EmplaceBack(L"chs_6_2"); break; - case ShaderType::ANY_HIT: arguments.EmplaceBack(L"ahs_6_2"); break; - case ShaderType::INTERSECTION: arguments.EmplaceBack(L"is_6_2"); break; - case ShaderType::MISS: arguments.EmplaceBack(L"ms_6_2"); break; - case ShaderType::CALLABLE: break; - default: ; - } - - //Strip reflection data and pdbs (see later) - arguments.EmplaceBack(L"-Qstrip_debug"); - arguments.EmplaceBack(L"-Qstrip_reflect"); - - arguments.EmplaceBack(DXC_ARG_WARNINGS_ARE_ERRORS); //-WX - arguments.EmplaceBack(DXC_ARG_DEBUG); //-Zi - arguments.EmplaceBack(DXC_ARG_PACK_MATRIX_ROW_MAJOR); //-Zp - - IDxcCompiler3* compiler3; - DxcCreateInstance(CLSID_DxcCompiler, __uuidof(IDxcCompiler3), reinterpret_cast(&compiler3)); - - IDxcResult* result; - - DxcBuffer dxc_buffer; - dxc_buffer.Size = code.GetBytes(); - dxc_buffer.Encoding = DXC_CP_UTF8; - dxc_buffer.Ptr = code.GetData(); - compiler3->Compile(&dxc_buffer, arguments.GetData(), arguments.GetLength(), nullptr, __uuidof(IDxcResult), reinterpret_cast(&result)); -#endif - return { false, GTSL::String(allocator), GTSL::Buffer(allocator) }; - } - - struct ShaderCompiler { - ShaderCompiler() { - shaderc_compile_options.SetTargetSpirv(shaderc_spirv_version_1_5); - shaderc_compile_options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); - shaderc_compile_options.SetOptimizationLevel(shaderc_optimization_level_performance); - shaderc_compile_options.SetGenerateDebugInfo(); - } - - template - std::tuple, GTSL::Buffer> Compile(GTSL::Range code, GTSL::Range shaderName, ShaderType shaderType, ShaderLanguage shaderLanguage, bool is_debug, const ALLOCATOR& allocator) { - shaderc_shader_kind shaderc_stage; - - switch (shaderType) { - case ShaderType::VERTEX: shaderc_stage = shaderc_vertex_shader; break; - case ShaderType::TESSELLATION_CONTROL: shaderc_stage = shaderc_tess_control_shader; break; - case ShaderType::TESSELLATION_EVALUATION: shaderc_stage = shaderc_tess_evaluation_shader; break; - case ShaderType::GEOMETRY: shaderc_stage = shaderc_geometry_shader; break; - case ShaderType::FRAGMENT: shaderc_stage = shaderc_fragment_shader; break; - case ShaderType::COMPUTE: shaderc_stage = shaderc_compute_shader; break; - case ShaderType::RAY_GEN: shaderc_stage = shaderc_raygen_shader; break; - case ShaderType::CLOSEST_HIT: shaderc_stage = shaderc_closesthit_shader; break; - case ShaderType::ANY_HIT: shaderc_stage = shaderc_anyhit_shader; break; - case ShaderType::INTERSECTION: shaderc_stage = shaderc_intersection_shader; break; - case ShaderType::MISS: shaderc_stage = shaderc_miss_shader; break; - case ShaderType::CALLABLE: shaderc_stage = shaderc_callable_shader; break; - default: GAL_DEBUG_BREAK; - } - - shaderc_source_language shaderc_source_language = shaderc_source_language_glsl; - switch (shaderLanguage) { - case ShaderLanguage::GLSL: shaderc_source_language = shaderc_source_language_glsl; break; - case ShaderLanguage::HLSL: shaderc_source_language = shaderc_source_language_hlsl; break; - default: GAL_DEBUG_BREAK; - } - - shaderc_compile_options.SetSourceLanguage(shaderc_source_language); - - GTSL::String shaderNameNullTerminator(shaderName, allocator); //String guarantees null terminator, while StringView doesn't and shaderc needs it - const auto shaderc_module = shaderc_compiler.CompileGlslToSpv(reinterpret_cast(code.GetData()), code.GetBytes(), shaderc_stage, reinterpret_cast(shaderNameNullTerminator.c_str()), shaderc_compile_options); - - if (shaderc_module.GetCompilationStatus() != shaderc_compilation_status_success) { - auto errorString = shaderc_module.GetErrorMessage(); - return { false, GTSL::String(GTSL::StringView(GTSL::Byte(errorString.size()), reinterpret_cast(errorString.c_str())), allocator), GTSL::Buffer(allocator) }; - } - - GTSL::Buffer buffer((shaderc_module.end() - shaderc_module.begin()) * sizeof(GTSL::uint32), 16, allocator); - buffer.Write((shaderc_module.end() - shaderc_module.begin()) * sizeof(GTSL::uint32), reinterpret_cast(shaderc_module.begin())); - - return { true, GTSL::String(allocator), GTSL::Buffer(GTSL::MoveRef(buffer)) }; - } - - private: - shaderc::Compiler shaderc_compiler; - shaderc::CompileOptions shaderc_compile_options; - }; -} diff --git a/src/GAL/Queue.h b/src/GAL/Queue.h deleted file mode 100644 index 060f0ece..00000000 --- a/src/GAL/Queue.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "RenderCore.h" -#include "GTSL/Core.h" - -namespace GAL { - class CommandList; - class Semaphore; - - class Queue { - public: - template - struct WorkUnit final { - struct SynchronizerOperationInfo { - S* Synchronizer = nullptr; - PipelineStage stage; - }; - - GTSL::Range Signal, Wait; - GTSL::Range CommandLists; - }; - }; -} diff --git a/src/GAL/RenderContext.h b/src/GAL/RenderContext.h deleted file mode 100644 index ae1cccb8..00000000 --- a/src/GAL/RenderContext.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -namespace GAL -{ - class Window; - class RenderDevice; - class Queue; - class RenderTarget; - - class Surface - { - public: - Surface() = default; - }; - - class RenderContext - { - public: - RenderContext() = default; - - //explicit RenderContext(const CreateInfo& createInfo); - - ~RenderContext() = default; - }; -} diff --git a/src/GAL/RenderCore.h b/src/GAL/RenderCore.h deleted file mode 100644 index 092171e8..00000000 --- a/src/GAL/RenderCore.h +++ /dev/null @@ -1,517 +0,0 @@ -#pragma once - -#include - -#include - -#include - -#include "GTSL/Bitman.h" -#include "GTSL/Extent.h" -#include "GTSL/RGB.hpp" -#include "GTSL/Math/Matrix.hpp" - -#undef OPAQUE - -namespace GAL { - class Texture; - class TextureView; - -#if BE_PLATFORM_WINDOWS -#define GAL_DEBUG_BREAK __debugbreak(); -#elif BE_PLATFORM_LINUX -#define GAL_DEBUG_BREAK __builtin_trap(); -#endif - - template - constexpr void debugClear(T& handle) { if constexpr (BE_DEBUG) { handle = reinterpret_cast(0); } } - - constexpr GTSL::uint8 MAX_SHADER_STAGES = 8; - - template - void TranslateMask(const GTSL::Flags fromValue, const Y toValue, const GTSL::Flags fromVar, Z& toVar) { - GTSL::SetBitAs(GTSL::FFSB(toValue), static_cast(static_cast(fromVar) & static_cast(fromValue)), toVar); - } - - template - void TranslateMask(const Y fromValue, Z fromVar, const GTSL::Flags toValue, GTSL::Flags& toVariable) { - GTSL::SetBitAs(GTSL::FFSB(toValue), fromVar & fromValue, static_cast(toVariable)); - } - - enum class RenderAPI : GTSL::uint8 { - VULKAN, - DIRECTX12 - }; - - using MemoryType = GTSL::Flags; - - namespace MemoryTypes { - static constexpr MemoryType GPU(1), HOST_VISIBLE(2), HOST_COHERENT(4), HOST_CACHED(8), LAZY(16); - } - - struct MemoryRequirements { - GTSL::uint32 Size{ 0 }; - GTSL::uint32 Alignment{ 0 }, MemoryTypes{ 0 }; - //MemoryType MemoryTypes; - }; - - using PipelineStage = GTSL::Flags; - - inline GTSL::uint16 FloatToUNORM(const GTSL::float32 x) { - return static_cast(x * 65535); - } - - inline GTSL::int16 FloatToSNORM(const GTSL::float32 x) { - //According to D3D10 rules, the value "-1.0f" has two representations: - // 0x1000 and 0x10001 - //This allows everyone to convert by just multiplying by 32767 instead - //of multiplying the negative values by 32768 and 32767 for positive. - return static_cast(GTSL::Math::Clamp(x >= 0.0f ? (x * 32767.0f + 0.5f) : (x * 32767.0f - 0.5f), -32768.0f, 32767.0f)); - } - - namespace PipelineStages { - static constexpr PipelineStage TOP_OF_PIPE(1), - DRAW_INDIRECT(2), - VERTEX_INPUT(4), - VERTEX(8), - TESSELLATION_CONTROL(16), - TESSELLATION_EVALUATION(32), - GEOMETRY(64), - FRAGMENT(128), - EARLY_FRAGMENT_TESTS(256), - LATE_FRAGMENT_TESTS(512), - COLOR_ATTACHMENT_OUTPUT(1024), - COMPUTE(2048), - TRANSFER(4096), - BOTTOM_OF_PIPE(8192), - HOST(16384), - ALL_GRAPHICS(32768), - RAY_TRACING(0x00200000), - ACCELERATION_STRUCTURE_BUILD(0x02000000), - SHADING_RATE_IMAGE(0x00400000), - TASK(0x00080000), - MESH(0x00100000); - } - - constexpr GTSL::uint8 RAY_GEN_TABLE_INDEX = 0, HIT_TABLE_INDEX = 1, MISS_TABLE_INDEX = 2, CALLABLE_TABLE_INDEX = 3; - - enum class ComponentType : GTSL::uint8 { INT, UINT, FLOAT, NON_LINEAR }; - enum class TextureType : GTSL::uint8 { COLOR, DEPTH }; - - struct DeviceAddress { - DeviceAddress() = default; - explicit DeviceAddress(const GTSL::uint64 add) : address(add) {} - - explicit operator GTSL::uint64() const { return address; } - explicit operator bool() const { return address; } - DeviceAddress operator+(const GTSL::uint64 add) const { return DeviceAddress(address + add); } - DeviceAddress& operator+=(uint32 offset) { address += offset; return *this; } - private: - GTSL::uint64 address = 0; - }; - - struct ShaderHandle { - ShaderHandle() = default; - GTSL::byte size[32]; - }; - - inline GTSL::uint32 SizeFromExtent(const GTSL::Extent3D extent) { - return extent.Width * extent.Height * extent.Depth; - } - - constexpr GTSL::uint32 bitExtracted(GTSL::uint32 number, GTSL::uint8 k, GTSL::uint8 p) { - return (((1 << k) - 1) & (number >> (p - 1))); - } - - enum class ColorSpaces : GTSL::uint8 { - LINEAR, SRGB_NONLINEAR, DISPLAY_P3_LINEAR, DISPLAY_P3_NONLINEAR, HDR10_ST2048, DOLBY_VISION, HDR10_HLG, ADOBERGB_LINEAR, ADOBERGB_NONLINEAR - }; - - struct FormatDescriptor - { - FormatDescriptor() = default; - - constexpr FormatDescriptor(ComponentType compType, GTSL::uint8 compCount, GTSL::uint8 bitDepth, TextureType type, GTSL::uint8 a, GTSL::uint8 b, GTSL::uint8 c, GTSL::uint8 d, ColorSpaces color_space = ColorSpaces::LINEAR) : - Component(compType), ComponentCount(compCount), A(a), B(b), C(c), D(d), BitDepth(GTSL::FindFirstSetBit(bitDepth).Get()), Type(type), ColorSpace(color_space) - {} - - constexpr FormatDescriptor(const GTSL::uint32 i) : Component(static_cast(bitExtracted(i, 4, 0))), - ComponentCount(bitExtracted(i, 4, 4)), A(bitExtracted(i, 2, 8)), B(bitExtracted(i, 2, 10)), C(bitExtracted(i, 2, 12)), D(bitExtracted(i, 2, 14)), - BitDepth(bitExtracted(i, 3, 16)), Type(static_cast(bitExtracted(i, 2, 19))), ColorSpace(static_cast(bitExtracted(i, 4, 21))) {} - - ComponentType Component : 4; //0 - GTSL::uint8 ComponentCount : 4; //4 - GTSL::uint8 A : 2; //8 - GTSL::uint8 B : 2; //10 - GTSL::uint8 C : 2; //12 - GTSL::uint8 D : 2; //14 - GTSL::uint8 BitDepth : 3; //16 - TextureType Type : 2; //19 - ColorSpaces ColorSpace : 4; //21 - - [[nodiscard]] GTSL::uint8 GetBitDepth() const { return static_cast(1) << BitDepth; } - [[nodiscard]] GTSL::uint8 GetSize() const { return GetBitDepth() / 8 * ComponentCount; } - - [[nodiscard]] constexpr operator GTSL::uint32() const { - return static_cast>(Component) | ComponentCount << 4 | A << 8 | B << 10 | C << 12 | D << 14 | BitDepth << 16 | static_cast>(Type) << 19 | static_cast>(ColorSpace) << 21; - } - }; - - namespace FORMATS { - static constexpr auto R_I8 = FormatDescriptor(ComponentType::INT, 1, 8, TextureType::COLOR, 0, 0, 0, 0); - static constexpr auto R_SRGB_I8 = FormatDescriptor(ComponentType::INT, 1, 8, TextureType::COLOR, 0, 0, 0, 0, ColorSpaces::SRGB_NONLINEAR); - static constexpr auto RGB_I8 = FormatDescriptor(ComponentType::INT, 3, 8, TextureType::COLOR, 0, 1, 2, 3); - static constexpr auto BGRA_I8 = FormatDescriptor(ComponentType::INT, 4, 8, TextureType::COLOR, 2, 1, 0, 3); - static constexpr auto RG_S8 = FormatDescriptor(ComponentType::INT, 2, 8, TextureType::COLOR, 0, 1, 0, 0); - static constexpr auto RG_I32 = FormatDescriptor(ComponentType::INT, 2, 32, TextureType::COLOR, 0, 1, 0, 0); - static constexpr auto RG_F16 = FormatDescriptor(ComponentType::FLOAT, 2, 16, TextureType::COLOR, 0, 1, 0, 0); - static constexpr auto BGRA_SRGB_I8 = FormatDescriptor(ComponentType::INT, 4, 8, TextureType::COLOR, 2, 1, 0, 3, ColorSpaces::SRGB_NONLINEAR); - static constexpr auto RGBA_F16 = FormatDescriptor(ComponentType::FLOAT, 4, 16, TextureType::COLOR, 0, 1, 2, 3); - static constexpr auto RGBA_I8 = FormatDescriptor(ComponentType::INT, 4, 8, TextureType::COLOR, 0, 1, 2, 3); - static constexpr auto RGBA_SRGB_I8 = FormatDescriptor(ComponentType::INT, 4, 8, TextureType::COLOR, 0, 1, 2, 3, ColorSpaces::SRGB_NONLINEAR); - static constexpr auto DEPTH_F32 = FormatDescriptor(ComponentType::FLOAT, 1, 32, TextureType::DEPTH, 0, 0, 0, 0); - } - - enum class Format { - R_I8 = FORMATS::R_I8, - R_SRGB_I8 = FORMATS::R_SRGB_I8, - RGB_I8 = FORMATS::RGB_I8, - RGBA_I8 = FORMATS::RGBA_I8, - RGBA_SRGB_I8 = FORMATS::RGBA_SRGB_I8, - BGRA_SRGB_I8 = FORMATS::BGRA_SRGB_I8, - RGBA_F16 = FORMATS::RGBA_F16, - BGRA_I8 = FORMATS::BGRA_I8, - RG_S8 = FORMATS::RG_S8, - RG_F16 = FORMATS::RG_F16, - RG_I32 = FORMATS::RG_I32, - DEPTH32 = FORMATS::DEPTH_F32 - }; - - constexpr Format MakeFormatFromFormatDescriptor(const FormatDescriptor formatDescriptor) { - return static_cast(static_cast(formatDescriptor)); - } - - //constexpr FormatDescriptor MakeFormatDescriptorFromFormat(const Format format) { - // return FormatDescriptor(static_cast(format)); - //} - - class RenderDevice; - - using BindingFlag = GTSL::Flags; - namespace BindingFlags { - static constexpr BindingFlag PARTIALLY_BOUND(1 << 0); - } - - using ShaderStage = GTSL::Flags; - namespace ShaderStages { - static constexpr ShaderStage VERTEX(1), - TESSELLATION_CONTROL(2), - TESSELLATION_EVALUATION(4), - GEOMETRY(8), - FRAGMENT(16), - COMPUTE(32), - TASK(64), - MESH(128), - RAY_GEN(256), ANY_HIT(512), CLOSEST_HIT(1024), MISS(2048), INTERSECTION(4096), CALLABLE(8192); - }; - - using TextureUse = GTSL::Flags; - namespace TextureUses { - static constexpr TextureUse TRANSFER_SOURCE(1), TRANSFER_DESTINATION(2), SAMPLE(4), STORAGE(8), ATTACHMENT(16), TRANSIENT_ATTACHMENT(32), INPUT_ATTACHMENT(64); - } - - using QueueType = GTSL::Flags; - namespace QueueTypes { - static constexpr QueueType GRAPHICS(1 << 0), COMPUTE(1 << 1), TRANSFER(1 << 2); - } - - using BufferUse = GTSL::Flags< GTSL::uint32, struct BufferUseFlag>; - namespace BufferUses { - static constexpr BufferUse TRANSFER_SOURCE(1 << 0), TRANSFER_DESTINATION(1 << 1), STORAGE(1 << 2), ACCELERATION_STRUCTURE(1 << 3), ADDRESS(1 << 4), UNIFORM(1 << 5), VERTEX(1 << 6), INDEX(1 << 7), SHADER_BINDING_TABLE(1 << 8), BUILD_INPUT_READ(1 << 9); - }; - - using AllocationFlag = GTSL::Flags; - namespace AllocationFlags { - static constexpr AllocationFlag DEVICE_ADDRESS(1), DEVICE_ADDRESS_CAPTURE_REPLAY(2); - } - - using AccessType = GTSL::Flags; - namespace AccessTypes { - static constexpr AccessType READ(1), WRITE(4); - } - - using AccessFlag = GTSL::Flags; - namespace AccessFlags { - static constexpr AccessFlag INDIRECT_COMMAND_READ(1 << 0), - INDEX_READ(1 << 1), - VERTEX_ATTRIBUTE_READ(1 << 2), - UNIFORM_READ(1 << 3), - INPUT_ATTACHMENT_READ(1 << 4), - SHADER_READ(1 << 5), - SHADER_WRITE(1 << 6), - ATTACHMENT_READ(1 << 7), - ATTACHMENT_WRITE(1 << 8), - TRANSFER_READ(1 << 11), - TRANSFER_WRITE(1 << 12), - HOST_READ(1 << 13), - HOST_WRITE(1 << 14), - MEMORY_READ(1 << 15), - MEMORY_WRITE(1 << 16), - ACCELERATION_STRUCTURE_READ(1 << 17), - ACCELERATION_STRUCTURE_WRITE(1 << 18), - SHADING_RATE_IMAGE_READ(1 << 19); - } - - // IMAGE - - //Specifies all available image layouts. - enum class TextureLayout : GTSL::uint8 { - UNDEFINED, - GENERAL, - ATTACHMENT, - SHADER_READ, - TRANSFER_SOURCE, - TRANSFER_DESTINATION, - PREINITIALIZED, - PRESENTATION - }; - - enum class GeometryType { - TRIANGLES, AABB, INSTANCES - }; - - enum class QueryType { - COMPACT_ACCELERATION_STRUCTURE_SIZE - }; - - using GeometryFlag = GTSL::Flags; - namespace GeometryFlags { - static constexpr GeometryFlag OPAQUE(1 << 0); - } - - using AccelerationStructureFlag = GTSL::Flags; - namespace AccelerationStructureFlags { - static constexpr AccelerationStructureFlag ALLOW_UPDATE(1 << 0), ALLOW_COMPACTION(1 << 1), PREFER_FAST_TRACE(1 << 2), PREFER_FAST_BUILD(1 << 3), LOW_MEMORY(1 << 4); - } - - enum class Tiling { - OPTIMAL, LINEAR - }; - - enum class Device : GTSL::uint8 { - GPU, CPU, GPU_OR_CPU - }; - - // ATTACHMENTS - - //Describes all possible operations a GAL can perform when loading a render target onto a render pass. - enum class Operations : GTSL::uint8 { - //We don't care about the previous content of the render target. Behavior is unknown. - UNDEFINED, - //We want to load the previous content of the render target. - DO, - //We want the render target to be cleared to black for color attachments and to 0 for depth/stencil attachments. - CLEAR - }; - - enum class SampleCount : GTSL::uint8 { - SAMPLE_COUNT_1, - SAMPLE_COUNT_2, - SAMPLE_COUNT_4, - SAMPLE_COUNT_8, - SAMPLE_COUNT_16, - SAMPLE_COUNT_32, - SAMPLE_COUNT_64 - }; - - // SHADERS - - enum class ShaderLanguage : GTSL::uint8 { - GLSL, HLSL - }; - - enum class ShaderType : GTSL::uint8 { - VERTEX, - TESSELLATION_CONTROL, - TESSELLATION_EVALUATION, - GEOMETRY, - FRAGMENT, - - COMPUTE, - - TASK, MESH, - - RAY_GEN, CLOSEST_HIT, ANY_HIT, INTERSECTION, MISS, CALLABLE - }; - - enum class ShaderDataType : GTSL::uint8 { - FLOAT, - FLOAT2, - FLOAT3, - FLOAT4, - - UINT16, - UINT32, - UINT64, - - INT, - INT2, - INT3, - INT4, - - BOOL, - - MAT3, - MAT4, - - U16_SNORM, U16_SNORM2, U16_SNORM3, U16_SNORM4, - U16_UNORM, U16_UNORM2, U16_UNORM3, U16_UNORM4 - }; - - // PIPELINE - - enum class CullMode : GTSL::uint8 { - CULL_NONE, - CULL_FRONT, - CULL_BACK - }; - - enum class WindingOrder : GTSL::uint8 { - CLOCKWISE, - COUNTER_CLOCKWISE - }; - - enum class BlendOperation : GTSL::uint8 { - WRITE, - ADD, - SUBTRACT, - REVERSE_SUBTRACT, - MIN, - MAX - }; - - enum class CompareOperation : GTSL::uint8 { - NEVER, - LESS, - EQUAL, - LESS_OR_EQUAL, - GREATER, - NOT_EQUAL, - GREATER_OR_EQUAL, - ALWAYS - }; - - enum class StencilCompareOperation : GTSL::uint8 { - KEEP, - ZERO, - REPLACE, - INCREMENT_AND_CLAMP, - DECREMENT_AND_CLAMP, - INVERT, - INCREMENT_AND_WRAP, - DECREMENT_AND_WRAP - }; - - enum class BindingType : GTSL::uint8 { - SAMPLER = 0, - COMBINED_IMAGE_SAMPLER = 1, - SAMPLED_IMAGE = 2, - STORAGE_IMAGE = 3, - UNIFORM_TEXEL_BUFFER = 4, - STORAGE_TEXEL_BUFFER = 5, - UNIFORM_BUFFER = 6, - STORAGE_BUFFER = 7, - UNIFORM_BUFFER_DYNAMIC = 8, - STORAGE_BUFFER_DYNAMIC = 9, - INPUT_ATTACHMENT = 10, - ACCELERATION_STRUCTURE = 11 - }; - - enum class PresentModes : GTSL::uint8 { - /** - * \brief All rendered images are queued in FIFO fashion and presented at V-BLANK. Best for when latency is not that important and energy consumption is. - */ - FIFO = 0, - - /** - * \brief The last rendered image is the one which will be presented. Best for when latency is important and energy consumption is not. - */ - SWAP = 1 - }; - - enum class ShaderGroupType { - GENERAL, TRIANGLES, PROCEDURAL - }; - - enum class IndexType { UINT8 = 1, UINT16 = 2, UINT32 = 4 }; - - inline uint32 IndexSize(const IndexType indexType) { - return static_cast(indexType); - } - - struct RenderPassTargetDescription { - //AccessType AccessType; - Operations LoadOperation, StoreOperation; - TextureLayout Start, End; - FormatDescriptor format; - const Texture* texture = nullptr; - const TextureView* textureView = nullptr; - GTSL::RGBA ClearValue; - }; - - struct RayTracingInstance { - GTSL::Matrix3x4 Transform; - GTSL::uint32 InstanceIndex : 24; - GTSL::uint32 Mask : 8; - GTSL::uint32 InstanceShaderBindingTableRecordOffset : 24; - GeometryFlag Flags; //8 bits - DeviceAddress AccelerationStructureAddress; - }; - - inline GTSL::uint8 ShaderDataTypesSize(const ShaderDataType type) { - switch (type) { - case ShaderDataType::FLOAT: return 4; - case ShaderDataType::FLOAT2: return 8; - case ShaderDataType::FLOAT3: return 12; - case ShaderDataType::FLOAT4: return 16; - case ShaderDataType::INT: return 4; - case ShaderDataType::INT2: return 8; - case ShaderDataType::INT3: return 12; - case ShaderDataType::INT4: return 16; - case ShaderDataType::BOOL: return 1; - case ShaderDataType::MAT3: return 36; - case ShaderDataType::MAT4: return 64; - default: GAL_DEBUG_BREAK; - } - - return 0; - } - - inline IndexType SizeToIndexType(const GTSL::uint8 size) { - switch (size) { - case 1: return IndexType::UINT8; - case 2: return IndexType::UINT16; - case 4: return IndexType::UINT32; - } - } - - inline ShaderStage ShaderTypeToShaderStageFlag(ShaderType type) { - switch (type) { - case ShaderType::VERTEX: return ShaderStages::VERTEX; - case ShaderType::FRAGMENT: return ShaderStages::FRAGMENT; - case ShaderType::COMPUTE: return ShaderStages::COMPUTE; - case ShaderType::TASK: return ShaderStages::TASK; - case ShaderType::MESH: return ShaderStages::MESH; - case ShaderType::RAY_GEN: return ShaderStages::RAY_GEN; - case ShaderType::ANY_HIT: return ShaderStages::ANY_HIT; - case ShaderType::CLOSEST_HIT: return ShaderStages::CLOSEST_HIT; - case ShaderType::MISS: return ShaderStages::MISS; - case ShaderType::INTERSECTION: return ShaderStages::INTERSECTION; - case ShaderType::CALLABLE: return ShaderStages::CALLABLE; - case ShaderType::TESSELLATION_CONTROL: return ShaderStages::TESSELLATION_CONTROL; - case ShaderType::TESSELLATION_EVALUATION: return ShaderStages::TESSELLATION_EVALUATION; - } - - return ShaderStage(); - } -} \ No newline at end of file diff --git a/src/GAL/RenderDevice.h b/src/GAL/RenderDevice.h deleted file mode 100644 index af08df95..00000000 --- a/src/GAL/RenderDevice.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include - -#include "RenderCore.h" -#include "GTSL/Delegate.hpp" - -#include - -#include - -#undef ERROR - -namespace GAL -{ - struct GPUInfo - { - GTSL::StaticString<512> GPUName; - GTSL::uint32 DriverVersion; - GTSL::uint32 APIVersion; - GTSL::uint8 PipelineCacheUUID[16]; - }; - - class RenderDevice - { - public: - enum class MessageSeverity : GTSL::uint8 { MESSAGE, WARNING, ERROR }; - - enum class Extension { - RAY_TRACING, PIPELINE_CACHE_EXTERNAL_SYNC, SCALAR_LAYOUT, SWAPCHAIN_RENDERING - }; - - struct AllocationInfo - { - /** - * \brief void* UserData. uint64 Size. uint64 Alignment. - */ - GTSL::Delegate Allocate; - /** - * \brief void* UserData. void* Original Allocation. uint64 Size. uint64 Alignment. - */ - GTSL::Delegate Reallocate; - /** - * \brief void* UserData. void* Allocation. - */ - GTSL::Delegate Deallocate; - - /** - * \brief void* UserData. uint64 Size. uint64 Alignment. - */ - GTSL::Delegate InternalAllocate; - /** - * \brief void* UserData. void* Allocation. - */ - GTSL::Delegate InternalDeallocate; - - void* UserData; - }; - - struct QueueKey { - QueueType Type; - GTSL::uint32 Family, Queue; - }; - - struct CreateInfo - { - GTSL::Range ApplicationName; - GTSL::uint16 ApplicationVersion[3]; - GTSL::Range Queues; - GTSL::Range QueueKeys; - GTSL::Delegate DebugPrintFunction; - bool Debug = false; - bool PerformanceValidation = false; - bool SynchronizationValidation = false; - GTSL::Range*> Extensions; - AllocationInfo allocation; - }; - - RenderDevice(GTSL::Delegate pDelegate) : debugPrintFunction(pDelegate) - { - } - - GTSL::Delegate GetDebugPrintFunction() const { return debugPrintFunction; } - - protected: - RenderDevice() = default; - ~RenderDevice() = default; - - GTSL::Delegate debugPrintFunction; - }; -} diff --git a/src/GAL/RenderPass.h b/src/GAL/RenderPass.h deleted file mode 100644 index 40a564e8..00000000 --- a/src/GAL/RenderPass.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "RenderCore.h" - -namespace GAL -{ - constexpr GTSL::uint8 ATTACHMENT_UNUSED = 255; - - class RenderPass { - public: - RenderPass() = default; - - //Describes the reference to a render pass attachment for a sub pass. - struct AttachmentReference - { - GTSL::uint8 Index = ATTACHMENT_UNUSED; - //Layout of the attachment during the sub pass. - TextureLayout Layout = TextureLayout::ATTACHMENT; - AccessType Access; - }; - - //Describes a subpass. - struct SubPassDescriptor - { - //Array of AttachmentsReferences - GTSL::Range Attachments; - - //Array of indices identifying attachments that are not used by this subpass, but whose contents MUST be preserved throughout the subpass. - GTSL::Range PreserveAttachments; - }; - - static constexpr GTSL::uint8 EXTERNAL = 255; - - struct SubPassDependency - { - GTSL::uint8 SourceSubPass, DestinationSubPass; - PipelineStage SourcePipelineStage, DestinationPipelineStage; - AccessType SourceAccessType, DestinationAccessType; - }; - - ~RenderPass() = default; - }; - -} diff --git a/src/GAL/Serialize.hpp b/src/GAL/Serialize.hpp deleted file mode 100644 index 94997146..00000000 --- a/src/GAL/Serialize.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Pipelines.h" -#include "GTSL/Buffer.hpp" - -namespace GAL -{ - template - void Insert(const Pipeline::VertexElement& vertexElement, GTSL::Buffer& buffer) - { - Insert(vertexElement.Identifier, buffer); - Insert(vertexElement.Type, buffer); - } - - template - void Extract(Pipeline::VertexElement& vertexElement, GTSL::Buffer& buffer) - { - Extract(vertexElement.Identifier, buffer); - Extract(vertexElement.Type, buffer); - } -} diff --git a/src/GAL/Synchronization.h b/src/GAL/Synchronization.h deleted file mode 100644 index 11c84d3b..00000000 --- a/src/GAL/Synchronization.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "RenderCore.h" - -namespace GAL -{ - /** - * \brief Object to achieve host-device synchronization. - */ - class Synchronizer { - public: - enum class Type { - FENCE, SEMAPHORE, EVENT - }; - }; -} diff --git a/src/GAL/Texture.h b/src/GAL/Texture.h deleted file mode 100644 index 7757cac1..00000000 --- a/src/GAL/Texture.h +++ /dev/null @@ -1,124 +0,0 @@ -#pragma once - -#include "RenderCore.h" - -#include -#include -#include - -namespace GAL -{ - //Represents a resource utilized by the rendering API for storing and referencing textures. Which are images which hold some information loaded from memory. - class Texture { - public: - Texture() = default; - ~Texture() = default; - - static GTSL::uint32 GetImageSize(const GTSL::uint8 textureFormatSize, const GTSL::Extent2D extent) - { - return static_cast(textureFormatSize) * extent.Width * extent.Height; - } - - /** - * \brief Assumes source and target image formats are different(wont't fail if they are the same but it will perform the conversion and copying), assumes target format has a higher channel count that source. - * \param sourceImageFormat - * \param targetImageFormat - * \param imageExtent - * \param buffer - */ - static void ConvertTextureFormat(const FormatDescriptor sourceImageFormat, const FormatDescriptor targetImageFormat, const GTSL::Extent2D imageExtent, GTSL::AlignedPointer buffer, GTSL::uint8 alphaValue) - { - const GTSL::uint8 sourceFormatSize = sourceImageFormat.BitDepth * sourceImageFormat.ComponentCount, targetFormatSize = targetImageFormat.BitDepth * targetImageFormat.ComponentCount; - const GTSL::uint32 targetTextureSize = GetImageSize(targetFormatSize, imageExtent), sourceTextureSize = GetImageSize(sourceFormatSize, imageExtent); - - auto rgb_i8_to_rgba_i8 = [&]() { - using Vector = GTSL::SIMD; - - GTSL::uint32 bytesToProcessWithScalar = sourceTextureSize % Vector::Bytes; - GTSL::uint32 bytesToProcessWithVector = sourceTextureSize - bytesToProcessWithScalar; - - GTSL::uint32 pixelsToProcessWithScalar = bytesToProcessWithScalar / sourceFormatSize; - GTSL::uint32 pixelsToProcessWithVector = bytesToProcessWithVector / sourceFormatSize; - - GTSL::uint32 srcPixelsPerVector = Vector::Bytes / sourceFormatSize; - GTSL::uint32 dstPixelsPerVector = Vector::Bytes / targetFormatSize; - - GTSL::uint32 vectorsInSrc = sourceTextureSize / Vector::Bytes; //TODO pixels per vector = 10,6... ?? - - GTSL::uint32 pixels = imageExtent.Width * imageExtent.Height; - - GTSL::byte* source = buffer.Get() + sourceTextureSize - sourceFormatSize,* target = buffer.Get() + targetTextureSize - targetFormatSize; - - //for(GTSL::uint32 i = 0; i < pixelsToProcessWithScalar; ++i) //loop for each pixel - //{ - // GTSL::MemCopy(sourceFormatSize, source, target); - // *(target + 3) = alphaValue; - // - // source -= sourceFormatSize; - // target -= targetFormatSize; - //} - // - //source = buffer.Get() + sourceTextureSize - Vector::Bytes; target = buffer.Get() + targetTextureSize - Vector::Bytes; - // - //while(source != buffer.Get() - Vector::Bytes) //loop for each group of bytes that fit in a vector - //{ - // GTSL::SIMD128 data{ GTSL::AlignedPointer(source) }; - // - // //data = Vector::Shuffle<0, 1, 2, 0, 3, 4, 5, 0, 6, 7, 8, 0, 9, 10, 11, 0>(data); - // - // data.CopyTo(GTSL::AlignedPointer(target)); - // - // for (GTSL::uint32 j = 0; j < dstPixelsPerVector; ++j) - // { - // GTSL::MemCopy(sourceFormatSize, source, target); - // (*(target + ((j * 4) - 1))) = alphaValue; - // } - // - // source -= Vector::Bytes; - // target -= Vector::Bytes; - //} - - for(GTSL::uint32 i = 0; i < pixels; ++i) //loop for each pixel - { - GTSL::MemCopy(sourceFormatSize, source, target); - *(target + 3) = alphaValue; - - source -= sourceFormatSize; - target -= targetFormatSize; - } - }; - - switch (MakeFormatFromFormatDescriptor(sourceImageFormat)) { - case Format::RGB_I8: { - switch (MakeFormatFromFormatDescriptor(targetImageFormat)) - { - case Format::RGBA_I8: rgb_i8_to_rgba_i8(); return; - - default: break; - } - break; - } - case Format::RGBA_I8: { - switch (MakeFormatFromFormatDescriptor(targetImageFormat)) - { - case Format::RGBA_I8: return; - - default: break; - } - break; - } - } - } - }; - - class TextureView { - public: - TextureView() = default; - ~TextureView() = default; - }; - - class Sampler - { - public: - }; -} diff --git a/src/GAL/Vulkan/Vulkan.h b/src/GAL/Vulkan/Vulkan.h deleted file mode 100644 index af47ee97..00000000 --- a/src/GAL/Vulkan/Vulkan.h +++ /dev/null @@ -1,594 +0,0 @@ -#pragma once - -#define VK_NO_PROTOTYPES -#include - -#if BE_PLATFORM_WINDOWS -#define VK_USE_PLATFORM_WIN32_KHR -typedef unsigned long DWORD; -typedef const wchar_t* LPCWSTR; -typedef void* HANDLE; -typedef struct HINSTANCE__* HINSTANCE; -typedef struct HWND__* HWND; -typedef struct HMONITOR__* HMONITOR; -typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; -#include -#undef OPAQUE -#elif BE_PLATFORM_LINUX -#define VK_USE_PLATFORM_XCB_KHR -#define VK_USE_PLATFORM_WAYLAND_KHR -#include -//#include -#include -#include -#elif BE_PLATFORM_MACOS -#define VK_USE_PLATFORM_MACOS_MVK -#include -#endif - -#include "GAL/RenderCore.h" - -#include -#include -#include - - -namespace GAL -{ - using VulkanHandle = void*; - - inline VkAttachmentLoadOp ToVkAttachmentLoadOp(const Operations operations) { - switch (operations) { - case Operations::UNDEFINED: return VK_ATTACHMENT_LOAD_OP_DONT_CARE; - case Operations::DO: return VK_ATTACHMENT_LOAD_OP_LOAD; - case Operations::CLEAR: return VK_ATTACHMENT_LOAD_OP_CLEAR; - default: return VK_ATTACHMENT_LOAD_OP_MAX_ENUM; - } - } - - inline VkAttachmentStoreOp ToVkAttachmentStoreOp(const Operations operations) { - switch (operations) { - case Operations::UNDEFINED: return VK_ATTACHMENT_STORE_OP_DONT_CARE; - case Operations::DO: return VK_ATTACHMENT_STORE_OP_STORE; - case Operations::CLEAR: return VK_ATTACHMENT_STORE_OP_DONT_CARE; - default: return VK_ATTACHMENT_STORE_OP_MAX_ENUM; - } - } - - inline VkAccessFlags2KHR ToVulkan(const AccessType access, const PipelineStage pipelineStage) { - uint64 vkAccessFlags = 0; - if (access & AccessTypes::WRITE) { - TranslateMask(PipelineStages::TRANSFER, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::COLOR_ATTACHMENT_OUTPUT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::ACCELERATION_STRUCTURE_BUILD, VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::TOP_OF_PIPE, VK_ACCESS_2_MEMORY_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - } else { - TranslateMask(PipelineStages::TRANSFER, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::COLOR_ATTACHMENT_OUTPUT, VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::ACCELERATION_STRUCTURE_BUILD, VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::TOP_OF_PIPE, VK_ACCESS_2_MEMORY_READ_BIT_KHR, pipelineStage, vkAccessFlags); - } - return (VkAccessFlags2KHR)vkAccessFlags; - } - - inline VkAccessFlags2KHR ToVulkan(const AccessType access, const PipelineStage pipelineStage, const FormatDescriptor) { - uint64 vkAccessFlags = 0; - if (access & AccessTypes::WRITE) { - TranslateMask(PipelineStages::TRANSFER, VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::COLOR_ATTACHMENT_OUTPUT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::ACCELERATION_STRUCTURE_BUILD, VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::TOP_OF_PIPE, VK_ACCESS_2_MEMORY_WRITE_BIT_KHR, pipelineStage, vkAccessFlags); - } else { - TranslateMask(PipelineStages::TRANSFER, VK_ACCESS_2_TRANSFER_READ_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::COLOR_ATTACHMENT_OUTPUT, VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::ACCELERATION_STRUCTURE_BUILD, VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR, pipelineStage, vkAccessFlags); - TranslateMask(PipelineStages::TOP_OF_PIPE, VK_ACCESS_2_MEMORY_READ_BIT_KHR, pipelineStage, vkAccessFlags); - } - return static_cast(vkAccessFlags); - } - - inline VkAccessFlags2KHR ToVulkan(const AccessType access, const FormatDescriptor formatDescriptor) { - if (access & AccessTypes::WRITE) { - switch (formatDescriptor.Type) { - case TextureType::COLOR: return VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR; - case TextureType::DEPTH: return VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR; - } - } else { //read - switch (formatDescriptor.Type) { - case TextureType::COLOR: return VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR; - case TextureType::DEPTH: return VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR; - } - } - } - - inline VkQueueFlags ToVulkan(const QueueType queueType) { - VkQueueFlags vkQueueFlags = 0; - TranslateMask(QueueTypes::GRAPHICS, VK_QUEUE_GRAPHICS_BIT, queueType, vkQueueFlags); - TranslateMask(QueueTypes::COMPUTE, VK_QUEUE_COMPUTE_BIT, queueType, vkQueueFlags); - TranslateMask(QueueTypes::TRANSFER, VK_QUEUE_TRANSFER_BIT, queueType, vkQueueFlags); - return vkQueueFlags; - } - - inline VkImageTiling ToVulkan(const Tiling tiling) { - switch (tiling) { - case Tiling::OPTIMAL: return VK_IMAGE_TILING_OPTIMAL; - case Tiling::LINEAR: return VK_IMAGE_TILING_LINEAR; - default: return VK_IMAGE_TILING_MAX_ENUM; - } - } - - inline VkMemoryAllocateFlags ToVulkan(const AllocationFlag allocationFlag) { - VkMemoryAllocateFlags vkMemoryAllocateFlags = 0; - TranslateMask(AllocationFlags::DEVICE_ADDRESS, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, allocationFlag, vkMemoryAllocateFlags); - TranslateMask(AllocationFlags::DEVICE_ADDRESS_CAPTURE_REPLAY, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, allocationFlag, vkMemoryAllocateFlags); - return vkMemoryAllocateFlags; - } - - inline VkAccessFlags ToVulkanBufferAccessFlags(const AccessFlag accessFlag) { - VkAccessFlags vkAccessFlags = 0; - TranslateMask(AccessFlags::INDIRECT_COMMAND_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::INDEX_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::VERTEX_ATTRIBUTE_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::UNIFORM_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::INPUT_ATTACHMENT_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::SHADER_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::SHADER_WRITE, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::ATTACHMENT_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::ATTACHMENT_WRITE, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::TRANSFER_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::TRANSFER_WRITE, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::HOST_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::HOST_WRITE, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::MEMORY_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::MEMORY_WRITE, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::ACCELERATION_STRUCTURE_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::ACCELERATION_STRUCTURE_WRITE, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - TranslateMask(AccessFlags::SHADING_RATE_IMAGE_READ, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, accessFlag, vkAccessFlags); - return vkAccessFlags; - } - - inline VkImageLayout ToVulkan(const TextureLayout layout, FormatDescriptor formatDescriptor) { - switch (layout) { - case TextureLayout::UNDEFINED: return VK_IMAGE_LAYOUT_UNDEFINED; - case TextureLayout::GENERAL: return VK_IMAGE_LAYOUT_GENERAL; - case TextureLayout::ATTACHMENT: { - switch (formatDescriptor.Type) { - case TextureType::COLOR: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - case TextureType::DEPTH: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - default: return VK_IMAGE_LAYOUT_MAX_ENUM; - } - } - case TextureLayout::SHADER_READ: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - case TextureLayout::TRANSFER_SOURCE: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - case TextureLayout::TRANSFER_DESTINATION: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - case TextureLayout::PREINITIALIZED: return VK_IMAGE_LAYOUT_PREINITIALIZED; - case TextureLayout::PRESENTATION: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - default: return VK_IMAGE_LAYOUT_MAX_ENUM; - } - } - - inline VkFormat ToVulkan(const Format format) { - switch (format) { - case Format::R_I8: return VK_FORMAT_R8_UNORM; - case Format::R_SRGB_I8: return VK_FORMAT_R8_SRGB; - case Format::RGBA_I8: return VK_FORMAT_R8G8B8A8_UNORM; - case Format::RGBA_SRGB_I8: return VK_FORMAT_R8G8B8A8_SRGB; - case Format::RGBA_F16: return VK_FORMAT_R16G16B16A16_SFLOAT; - case Format::RG_S8: return VK_FORMAT_R8G8_SNORM; - case Format::RG_F16: return VK_FORMAT_R16G16_SFLOAT; - case Format::RG_I32: return VK_FORMAT_R32G32_UINT; - case Format::BGRA_I8: return VK_FORMAT_B8G8R8A8_UNORM; - case Format::DEPTH32: return VK_FORMAT_D32_SFLOAT; - case Format::RGB_I8: return VK_FORMAT_R8G8B8_UNORM; - case Format::BGRA_SRGB_I8: return VK_FORMAT_B8G8R8A8_SRGB; - default: return VK_FORMAT_MAX_ENUM; - } - } - - inline VkImageAspectFlags TextureAspectToVkImageAspectFlags(const TextureType textureType) { - switch (textureType) { - case TextureType::COLOR: return VK_IMAGE_ASPECT_COLOR_BIT; - case TextureType::DEPTH: return VK_IMAGE_ASPECT_DEPTH_BIT; - default: return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM; - } - } - - inline VkBuildAccelerationStructureFlagsKHR ToVulkan(const AccelerationStructureFlag accelerationStructureFlag) { - VkBuildAccelerationStructureFlagsKHR vk_build_acceleration_structure_flags_khr{}; - TranslateMask(AccelerationStructureFlags::ALLOW_COMPACTION, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, accelerationStructureFlag, vk_build_acceleration_structure_flags_khr); - TranslateMask(AccelerationStructureFlags::ALLOW_UPDATE, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, accelerationStructureFlag, vk_build_acceleration_structure_flags_khr); - TranslateMask(AccelerationStructureFlags::LOW_MEMORY, VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, accelerationStructureFlag, vk_build_acceleration_structure_flags_khr); - TranslateMask(AccelerationStructureFlags::PREFER_FAST_BUILD, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, accelerationStructureFlag, vk_build_acceleration_structure_flags_khr); - TranslateMask(AccelerationStructureFlags::PREFER_FAST_TRACE, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, accelerationStructureFlag, vk_build_acceleration_structure_flags_khr); - return vk_build_acceleration_structure_flags_khr; - - } - - inline VkPipelineStageFlags2KHR ToVulkan(const PipelineStage pipelineStage) { - uint64 vkPipelineStageFlags = 0; - TranslateMask(PipelineStages::TOP_OF_PIPE, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::DRAW_INDIRECT, VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::VERTEX_INPUT, VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::VERTEX, VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::TESSELLATION_CONTROL, VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::TESSELLATION_EVALUATION, VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::GEOMETRY, VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::FRAGMENT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::EARLY_FRAGMENT_TESTS, VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::LATE_FRAGMENT_TESTS, VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::COLOR_ATTACHMENT_OUTPUT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::COMPUTE, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::TRANSFER, VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::BOTTOM_OF_PIPE, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::HOST, VK_PIPELINE_STAGE_2_HOST_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::ALL_GRAPHICS, VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::RAY_TRACING, VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::ACCELERATION_STRUCTURE_BUILD, VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::TASK, VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV, pipelineStage, vkPipelineStageFlags); - TranslateMask(PipelineStages::MESH, VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV, pipelineStage, vkPipelineStageFlags); - return static_cast(vkPipelineStageFlags); - } - - inline VkDescriptorType ToVulkan(const BindingType bindingType) { - switch (bindingType) { - case BindingType::SAMPLER: return VK_DESCRIPTOR_TYPE_SAMPLER; - case BindingType::COMBINED_IMAGE_SAMPLER: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - case BindingType::SAMPLED_IMAGE: return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - case BindingType::STORAGE_IMAGE: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - case BindingType::UNIFORM_TEXEL_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - case BindingType::STORAGE_TEXEL_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - case BindingType::UNIFORM_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - case BindingType::STORAGE_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - case BindingType::UNIFORM_BUFFER_DYNAMIC: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - case BindingType::STORAGE_BUFFER_DYNAMIC: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - case BindingType::INPUT_ATTACHMENT: return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - case BindingType::ACCELERATION_STRUCTURE: return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - default: return VK_DESCRIPTOR_TYPE_MAX_ENUM; - } - } - - inline VkShaderStageFlagBits ToVulkan(const ShaderType shaderType) { - switch (shaderType) { - case ShaderType::VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; - case ShaderType::TESSELLATION_CONTROL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - case ShaderType::TESSELLATION_EVALUATION: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - case ShaderType::GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; - case ShaderType::FRAGMENT: return VK_SHADER_STAGE_FRAGMENT_BIT; - case ShaderType::COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; - case ShaderType::TASK: return VK_SHADER_STAGE_TASK_BIT_NV; - case ShaderType::MESH: return VK_SHADER_STAGE_MESH_BIT_NV; - case ShaderType::RAY_GEN: return VK_SHADER_STAGE_RAYGEN_BIT_KHR; - case ShaderType::CLOSEST_HIT: return VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; - case ShaderType::ANY_HIT: return VK_SHADER_STAGE_ANY_HIT_BIT_KHR; - case ShaderType::INTERSECTION: return VK_SHADER_STAGE_INTERSECTION_BIT_KHR; - case ShaderType::MISS: return VK_SHADER_STAGE_MISS_BIT_KHR; - case ShaderType::CALLABLE: return VK_SHADER_STAGE_CALLABLE_BIT_KHR; - default: return VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM; - } - } - - inline VkExtent2D ToVulkan(const GTSL::Extent2D extent) { - return { extent.Width, extent.Height }; - } - - inline VkExtent3D ToVulkan(const GTSL::Extent3D extent) { - return { extent.Width, extent.Height, extent.Depth }; - } - - inline VkRayTracingShaderGroupTypeKHR ToVulkan(const ShaderGroupType type) { - switch (type) { - case ShaderGroupType::GENERAL: return VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - case ShaderGroupType::TRIANGLES: return VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - case ShaderGroupType::PROCEDURAL: return VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; - default: return VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR; - } - } - - inline VkPresentModeKHR ToVulkan(const PresentModes presentModes) { - switch (presentModes) { - case PresentModes::FIFO: return VK_PRESENT_MODE_FIFO_KHR; - case PresentModes::SWAP: return VK_PRESENT_MODE_MAILBOX_KHR; - default: return VK_PRESENT_MODE_MAX_ENUM_KHR; - } - } - - inline GTSL::uint32 ImageTypeToVkImageAspectFlagBits(const TextureType imageType) { - switch (imageType) { - case TextureType::COLOR: return VK_IMAGE_ASPECT_COLOR_BIT; - case TextureType::DEPTH: return VK_IMAGE_ASPECT_DEPTH_BIT; - default: return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM; - } - } - - inline VkBufferUsageFlags ToVulkan(const BufferUse bufferUses) { - VkBufferUsageFlags vkBufferUsageFlags = 0; - TranslateMask(BufferUses::STORAGE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::TRANSFER_SOURCE, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::TRANSFER_DESTINATION, VK_BUFFER_USAGE_TRANSFER_DST_BIT, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::ADDRESS, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::ACCELERATION_STRUCTURE, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::UNIFORM, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::VERTEX, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::INDEX, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::SHADER_BINDING_TABLE, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, bufferUses, vkBufferUsageFlags); - TranslateMask(BufferUses::BUILD_INPUT_READ, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, bufferUses, vkBufferUsageFlags); - return vkBufferUsageFlags; - } - - inline VkFormat ToVulkan(const ShaderDataType shaderDataTypes) { - switch (shaderDataTypes) { - case ShaderDataType::FLOAT: return VK_FORMAT_R32_SFLOAT; - case ShaderDataType::FLOAT2: return VK_FORMAT_R32G32_SFLOAT; - case ShaderDataType::FLOAT3: return VK_FORMAT_R32G32B32_SFLOAT; - case ShaderDataType::FLOAT4: return VK_FORMAT_R32G32B32A32_SFLOAT; - case ShaderDataType::INT: return VK_FORMAT_R32_SINT; - case ShaderDataType::INT2: return VK_FORMAT_R32G32_SINT; - case ShaderDataType::INT3: return VK_FORMAT_R32G32B32_SINT; - case ShaderDataType::INT4: return VK_FORMAT_R32G32B32A32_SINT; - case ShaderDataType::BOOL: return VK_FORMAT_R32_SINT; - case ShaderDataType::U16_SNORM: return VK_FORMAT_R16_SNORM; - case ShaderDataType::U16_SNORM2: return VK_FORMAT_R16G16_SNORM; - case ShaderDataType::U16_SNORM3: return VK_FORMAT_R16G16B16_SNORM; - case ShaderDataType::U16_SNORM4: return VK_FORMAT_R16G16B16A16_SNORM; - case ShaderDataType::U16_UNORM: return VK_FORMAT_R16_UNORM; - case ShaderDataType::U16_UNORM2: return VK_FORMAT_R16G16_UNORM; - case ShaderDataType::U16_UNORM3: return VK_FORMAT_R16G16B16_UNORM; - case ShaderDataType::U16_UNORM4: return VK_FORMAT_R16G16B16A16_UNORM; - default: return VK_FORMAT_MAX_ENUM; - } - } - - inline VkQueryType ToVulkan(const QueryType queryType) { - switch (queryType) { - case QueryType::COMPACT_ACCELERATION_STRUCTURE_SIZE: return VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; - default: return VK_QUERY_TYPE_MAX_ENUM; - } - } - - inline VkDescriptorType UniformTypeToVkDescriptorType(const BindingType uniformType) { - switch (uniformType) { - case BindingType::SAMPLER: return VK_DESCRIPTOR_TYPE_SAMPLER; - case BindingType::COMBINED_IMAGE_SAMPLER: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - case BindingType::SAMPLED_IMAGE: return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - case BindingType::STORAGE_IMAGE: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - case BindingType::UNIFORM_TEXEL_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - case BindingType::STORAGE_TEXEL_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - case BindingType::UNIFORM_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - case BindingType::STORAGE_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - case BindingType::UNIFORM_BUFFER_DYNAMIC: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - case BindingType::STORAGE_BUFFER_DYNAMIC: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - case BindingType::INPUT_ATTACHMENT: return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - default: return VK_DESCRIPTOR_TYPE_MAX_ENUM; - } - }; - - inline VkAccelerationStructureBuildTypeKHR ToVulkan(const Device device) { - switch (device) { - case Device::GPU: return VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; - case Device::CPU: return VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR; - case Device::GPU_OR_CPU: return VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR; - default: return VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR; - } - } - - - inline VkCullModeFlagBits ToVulkan(const CullMode cullMode) { - switch (cullMode) { - case CullMode::CULL_BACK: return VK_CULL_MODE_BACK_BIT; - case CullMode::CULL_FRONT: return VK_CULL_MODE_FRONT_BIT; - case CullMode::CULL_NONE: return VK_CULL_MODE_NONE; - default: return VK_CULL_MODE_FLAG_BITS_MAX_ENUM; - } - } - - inline VkFrontFace ToVulkan(const WindingOrder windingOrder) { - switch (windingOrder) { - case WindingOrder::CLOCKWISE: return VK_FRONT_FACE_CLOCKWISE; - case WindingOrder::COUNTER_CLOCKWISE: return VK_FRONT_FACE_COUNTER_CLOCKWISE; - default: return VK_FRONT_FACE_MAX_ENUM; - } - } - - inline VkCompareOp ToVulkan(const CompareOperation compareOperation) { - switch (compareOperation) { - case CompareOperation::NEVER: return VK_COMPARE_OP_NEVER; - case CompareOperation::LESS: return VK_COMPARE_OP_LESS; - case CompareOperation::EQUAL: return VK_COMPARE_OP_EQUAL; - case CompareOperation::LESS_OR_EQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL; - case CompareOperation::GREATER: return VK_COMPARE_OP_GREATER; - case CompareOperation::NOT_EQUAL: return VK_COMPARE_OP_NOT_EQUAL; - case CompareOperation::GREATER_OR_EQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL; - case CompareOperation::ALWAYS: return VK_COMPARE_OP_ALWAYS; - default: return VK_COMPARE_OP_MAX_ENUM; - } - } - - inline VkImageType ToVulkanType(const GTSL::Extent3D extent) { - if (extent.Height != 1) { - if (extent.Depth != 1) { return VK_IMAGE_TYPE_3D; } - return VK_IMAGE_TYPE_2D; - } - return VK_IMAGE_TYPE_1D; - } - - inline VkImageViewType ToVkImageViewType(const GTSL::Extent3D extent) { - if (extent.Height != 1) { - if (extent.Depth != 1) { return VK_IMAGE_VIEW_TYPE_3D; } - return VK_IMAGE_VIEW_TYPE_2D; - } - return VK_IMAGE_VIEW_TYPE_1D; - } - - inline VkImageAspectFlags ToVulkan(const TextureType textureType) { - switch (textureType) { - case TextureType::COLOR: return VK_IMAGE_ASPECT_COLOR_BIT; - case TextureType::DEPTH: return VK_IMAGE_ASPECT_DEPTH_BIT; - } - return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM; - } - - inline VkIndexType ToVulkan(const IndexType indexType) { - switch (indexType) { - case IndexType::UINT8: return VK_INDEX_TYPE_UINT8_EXT; - case IndexType::UINT16: return VK_INDEX_TYPE_UINT16; - case IndexType::UINT32: return VK_INDEX_TYPE_UINT32; - } - return VK_INDEX_TYPE_MAX_ENUM; - } - - inline VkImageUsageFlags ToVulkan(const TextureUse uses, const FormatDescriptor formatDescriptor) { - VkImageUsageFlags vkUsage = 0; - if (uses & TextureUses::ATTACHMENT) { - switch (formatDescriptor.Type) { - case TextureType::COLOR: vkUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; break; - case TextureType::DEPTH: vkUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; break; - } - } - TranslateMask(TextureUses::INPUT_ATTACHMENT, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, uses, vkUsage); - TranslateMask(TextureUses::SAMPLE, VK_IMAGE_USAGE_SAMPLED_BIT, uses, vkUsage); - TranslateMask(TextureUses::STORAGE, VK_IMAGE_USAGE_STORAGE_BIT, uses, vkUsage); - TranslateMask(TextureUses::TRANSFER_DESTINATION, VK_IMAGE_USAGE_TRANSFER_DST_BIT, uses, vkUsage); - TranslateMask(TextureUses::TRANSFER_SOURCE, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, uses, vkUsage); - TranslateMask(TextureUses::TRANSIENT_ATTACHMENT, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, uses, vkUsage); - - return vkUsage; - } - - inline VkStencilOp ToVulkan(const StencilCompareOperation stencilCompareOperation) { - switch (stencilCompareOperation) { - case StencilCompareOperation::KEEP: return VK_STENCIL_OP_KEEP; - case StencilCompareOperation::ZERO: return VK_STENCIL_OP_ZERO; - case StencilCompareOperation::REPLACE: return VK_STENCIL_OP_REPLACE; - case StencilCompareOperation::INCREMENT_AND_CLAMP: return VK_STENCIL_OP_INCREMENT_AND_CLAMP; - case StencilCompareOperation::DECREMENT_AND_CLAMP: return VK_STENCIL_OP_DECREMENT_AND_CLAMP; - case StencilCompareOperation::INVERT: return VK_STENCIL_OP_INVERT; - case StencilCompareOperation::INCREMENT_AND_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP; - case StencilCompareOperation::DECREMENT_AND_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP; - } - - return VK_STENCIL_OP_MAX_ENUM; - } - - inline VkShaderStageFlags ToVulkan(const ShaderStage shaderStage) { - VkShaderStageFlags vkShaderStageFlags = 0; - TranslateMask(ShaderStages::VERTEX, VK_SHADER_STAGE_VERTEX_BIT, shaderStage, vkShaderStageFlags); - TranslateMask(ShaderStages::FRAGMENT, VK_SHADER_STAGE_FRAGMENT_BIT, shaderStage, vkShaderStageFlags); - TranslateMask(ShaderStages::COMPUTE, VK_SHADER_STAGE_COMPUTE_BIT, shaderStage, vkShaderStageFlags); - TranslateMask(ShaderStages::RAY_GEN, VK_SHADER_STAGE_RAYGEN_BIT_KHR, shaderStage, vkShaderStageFlags); - TranslateMask(ShaderStages::CLOSEST_HIT, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, shaderStage, vkShaderStageFlags); - TranslateMask(ShaderStages::ANY_HIT, VK_SHADER_STAGE_ANY_HIT_BIT_KHR, shaderStage, vkShaderStageFlags); - TranslateMask(ShaderStages::MISS, VK_SHADER_STAGE_MISS_BIT_KHR, shaderStage, vkShaderStageFlags); - TranslateMask(ShaderStages::CALLABLE, VK_SHADER_STAGE_CALLABLE_BIT_KHR, shaderStage, vkShaderStageFlags); - return vkShaderStageFlags; - } - - inline VkDescriptorBindingFlags ToVulkan(const BindingFlag bindingFlag) { - VkDescriptorBindingFlags vkDescriptorBindingFlags = 0; - TranslateMask(BindingFlags::PARTIALLY_BOUND, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, bindingFlag, vkDescriptorBindingFlags); - return vkDescriptorBindingFlags; - } - - inline VkGeometryFlagsKHR ToVkGeometryFlagsKHR(const GeometryFlag geometryFlag) { - VkGeometryFlagsKHR vkGeometryFlagsKhr = 0; - TranslateMask(GeometryFlags::OPAQUE, VK_GEOMETRY_OPAQUE_BIT_KHR, geometryFlag, vkGeometryFlagsKhr); - return vkGeometryFlagsKhr; - } - - inline VkGeometryInstanceFlagsKHR ToVkGeometryInstanceFlagsKHR(const GeometryFlag geometryFlag) { - VkGeometryInstanceFlagsKHR vkGeometryFlagsKhr = 0; - TranslateMask(GeometryFlags::OPAQUE, VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, geometryFlag, vkGeometryFlagsKhr); - return vkGeometryFlagsKhr; - } - - inline VkColorSpaceKHR ToVulkan(const ColorSpaces colorSpace) { - switch (colorSpace) { - case ColorSpaces::LINEAR: return VK_COLOR_SPACE_PASS_THROUGH_EXT; - case ColorSpaces::SRGB_NONLINEAR: return VK_COLORSPACE_SRGB_NONLINEAR_KHR; - case ColorSpaces::DISPLAY_P3_LINEAR: return VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT; - case ColorSpaces::DISPLAY_P3_NONLINEAR: return VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT; - case ColorSpaces::HDR10_ST2048: return VK_COLOR_SPACE_HDR10_ST2084_EXT; - case ColorSpaces::DOLBY_VISION: return VK_COLOR_SPACE_DOLBYVISION_EXT; - case ColorSpaces::HDR10_HLG: return VK_COLOR_SPACE_HDR10_HLG_EXT; - case ColorSpaces::ADOBERGB_LINEAR: return VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT; - case ColorSpaces::ADOBERGB_NONLINEAR: return VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT; - } - - return VK_COLOR_SPACE_MAX_ENUM_KHR; - } - - inline VkTransformMatrixKHR ToVulkan(const GTSL::Matrix3x4& matrix3X4) { - VkTransformMatrixKHR vkMatrix; - vkMatrix.matrix[0][0] = matrix3X4[0][0]; vkMatrix.matrix[0][1] = matrix3X4[0][1]; vkMatrix.matrix[0][2] = matrix3X4[0][2]; vkMatrix.matrix[0][3] = matrix3X4[0][3]; - vkMatrix.matrix[1][0] = matrix3X4[1][0]; vkMatrix.matrix[1][1] = matrix3X4[1][1]; vkMatrix.matrix[1][2] = matrix3X4[1][2]; vkMatrix.matrix[1][3] = matrix3X4[1][3]; - vkMatrix.matrix[2][0] = matrix3X4[2][0]; vkMatrix.matrix[2][1] = matrix3X4[2][1]; vkMatrix.matrix[2][2] = matrix3X4[2][2]; vkMatrix.matrix[2][3] = matrix3X4[2][3]; - return vkMatrix; - } - - //TO GAL - - inline PresentModes ToGAL(const VkPresentModeKHR presentModes) { - switch (presentModes) { - case VK_PRESENT_MODE_FIFO_KHR: return PresentModes::FIFO; - case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return PresentModes::FIFO; - case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: return PresentModes::SWAP; - case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: return PresentModes::SWAP; - case VK_PRESENT_MODE_MAX_ENUM_KHR: return PresentModes::SWAP; - case VK_PRESENT_MODE_IMMEDIATE_KHR: return PresentModes::FIFO; - case VK_PRESENT_MODE_MAILBOX_KHR: return PresentModes::SWAP; - } - return PresentModes::SWAP; - } - - inline MemoryType ToGAL(const VkMemoryPropertyFlags memoryPropertyFlags) { - MemoryType memoryType; - TranslateMask(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memoryPropertyFlags, MemoryTypes::GPU, memoryType); - TranslateMask(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, memoryPropertyFlags, MemoryTypes::HOST_VISIBLE, memoryType); - TranslateMask(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, memoryPropertyFlags, MemoryTypes::HOST_COHERENT, memoryType); - TranslateMask(VK_MEMORY_PROPERTY_HOST_CACHED_BIT, memoryPropertyFlags, MemoryTypes::HOST_CACHED, memoryType); - TranslateMask(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, memoryPropertyFlags, MemoryTypes::LAZY, memoryType); - return memoryType; - } - - inline bool IsSupported(const VkFormat format) { - return !(format == VK_FORMAT_A2B10G10R10_UNORM_PACK32); - } - - inline FormatDescriptor ToGAL(const VkFormat format) { - switch (format) { - case VK_FORMAT_R8G8B8A8_UNORM: return FORMATS::RGBA_I8; - case VK_FORMAT_B8G8R8A8_UNORM: return FORMATS::BGRA_I8; - case VK_FORMAT_B8G8R8A8_SRGB: return FORMATS::BGRA_SRGB_I8; - case VK_FORMAT_R16G16B16A16_SFLOAT: return FORMATS::RGBA_F16; - case VK_FORMAT_UNDEFINED: GAL_DEBUG_BREAK; return FORMATS::RGBA_F16; - default: GAL_DEBUG_BREAK; return FORMATS::RGBA_F16; - } - - GAL_DEBUG_BREAK; - } - - inline ColorSpaces ToGAL(const VkColorSpaceKHR colorSpace) { - switch (colorSpace) { - case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: return ColorSpaces::SRGB_NONLINEAR; - case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT: return ColorSpaces::DISPLAY_P3_NONLINEAR; - case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: break; - case VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT: return ColorSpaces::DISPLAY_P3_LINEAR; - case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT: break; - case VK_COLOR_SPACE_BT709_LINEAR_EXT: break; - case VK_COLOR_SPACE_BT709_NONLINEAR_EXT: break; - case VK_COLOR_SPACE_BT2020_LINEAR_EXT: break; - case VK_COLOR_SPACE_HDR10_ST2084_EXT: return ColorSpaces::HDR10_ST2048; - case VK_COLOR_SPACE_DOLBYVISION_EXT: return ColorSpaces::DOLBY_VISION; - case VK_COLOR_SPACE_HDR10_HLG_EXT: return ColorSpaces::HDR10_HLG; - case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT: return ColorSpaces::ADOBERGB_LINEAR; - case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT: return ColorSpaces::ADOBERGB_NONLINEAR; - case VK_COLOR_SPACE_PASS_THROUGH_EXT: return ColorSpaces::LINEAR; - case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT: break; - case VK_COLOR_SPACE_DISPLAY_NATIVE_AMD: break; - case VK_COLOR_SPACE_MAX_ENUM_KHR: break; - } - - GAL_DEBUG_BREAK; - - return ColorSpaces::SRGB_NONLINEAR; - } -} \ No newline at end of file diff --git a/src/GAL/Vulkan/VulkanAccelerationStructures.h b/src/GAL/Vulkan/VulkanAccelerationStructures.h deleted file mode 100644 index 34d06daf..00000000 --- a/src/GAL/Vulkan/VulkanAccelerationStructures.h +++ /dev/null @@ -1,228 +0,0 @@ -#pragma once - -#include "Vulkan.h" -#include "GTSL/Range.hpp" -#include - -#include "GTSL/Vector.hpp" - -namespace GAL { - struct AccelerationStructureBuildInfo; - - struct GeometryTriangles { - ShaderDataType VertexPositionFormat; IndexType indexType; GTSL::uint8 VertexStride; - DeviceAddress VertexData, IndexData; - GTSL::uint32 FirstVertex, MaxVertices; - }; - - struct GeometryAABB { - DeviceAddress Data; - GTSL::uint32 Stride; - }; - - struct GeometryInstances { - DeviceAddress Data; - }; - - struct Geometry { - GeometryType Type; - union { - GeometryTriangles Triangles; - GeometryAABB AABB; - GeometryInstances Instances; - }; - GeometryFlag Flags; - - Geometry(const GeometryTriangles triangles, const GeometryFlag flags, const GTSL::uint32 primCount, const GTSL::uint32 primOffset) : Type(GeometryType::TRIANGLES), Triangles(triangles), Flags(flags), PrimitiveCount(primCount), PrimitiveOffset(primOffset) {} - Geometry(const GeometryAABB aabb, const GeometryFlag flags, const GTSL::uint32 primCount, const GTSL::uint32 primOffset) : Type(GeometryType::AABB), AABB(aabb), Flags(flags), PrimitiveCount(primCount), PrimitiveOffset(primOffset) {} - Geometry(const GeometryInstances instances, const GeometryFlag flags, const GTSL::uint32 primCount, const GTSL::uint32 primOffset) : Type(GeometryType::INSTANCES), Instances(instances), Flags(flags), PrimitiveCount(primCount), PrimitiveOffset(primOffset) {} - - void SetGeometryTriangles(const GeometryTriangles triangles) { Type = GeometryType::TRIANGLES; Triangles = triangles; } - void SetGeometryAABB(const GeometryAABB aabb) { Type = GeometryType::AABB; AABB = aabb; } - void SetGeometryInstances(const GeometryInstances instances) { Type = GeometryType::INSTANCES; Instances = instances; } - - GTSL::uint32 PrimitiveCount, PrimitiveOffset; - }; - - inline void buildGeometryAndRange(const Geometry& descriptor, VkAccelerationStructureGeometryKHR& vkGeometry, VkAccelerationStructureBuildRangeInfoKHR& buildRange) { - auto& s = descriptor; - vkGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - vkGeometry.pNext = nullptr; - vkGeometry.flags = ToVkGeometryFlagsKHR(s.Flags); - buildRange.primitiveCount = descriptor.PrimitiveCount; - buildRange.primitiveOffset = descriptor.PrimitiveOffset; - - switch (s.Type) { - case GeometryType::TRIANGLES: { - auto& t = s.Triangles; - vkGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - vkGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - vkGeometry.geometry.triangles.pNext = nullptr; - vkGeometry.geometry.triangles.vertexData.deviceAddress = static_cast(t.VertexData); - vkGeometry.geometry.triangles.indexData.deviceAddress = static_cast(t.IndexData); - vkGeometry.geometry.triangles.transformData.deviceAddress = 0; - vkGeometry.geometry.triangles.indexType = ToVulkan(t.indexType); - vkGeometry.geometry.triangles.maxVertex = t.MaxVertices; - vkGeometry.geometry.triangles.vertexFormat = ToVulkan(t.VertexPositionFormat); - vkGeometry.geometry.triangles.vertexStride = t.VertexStride; - buildRange.firstVertex = descriptor.Triangles.FirstVertex; - buildRange.transformOffset = 0; - break; - } - case GeometryType::AABB: { - auto& a = s.AABB; - vkGeometry.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; - vkGeometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR; - vkGeometry.geometry.aabbs.pNext = nullptr; - vkGeometry.geometry.aabbs.data.deviceAddress = static_cast(a.Data); - vkGeometry.geometry.aabbs.stride = a.Stride; - buildRange.firstVertex = 0; - buildRange.transformOffset = 0; - break; - } - case GeometryType::INSTANCES: { - const auto& a = s.Instances; - vkGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - vkGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; - vkGeometry.geometry.instances.pNext = nullptr; - vkGeometry.geometry.instances.data.deviceAddress = static_cast(a.Data); - vkGeometry.geometry.instances.arrayOfPointers = false; - buildRange.firstVertex = 0; - buildRange.transformOffset = 0; - break; - } - } - } - - class VulkanAccelerationStructure { - public: - [[nodiscard]] VkAccelerationStructureKHR GetVkAccelerationStructure() const { return accelerationStructure; } - - VulkanAccelerationStructure() = default; - - void GetMemoryRequirements(const VulkanRenderDevice* renderDevice, GTSL::Range geometries, Device buildDevice, AccelerationStructureFlag flags, GTSL::uint32* accStructureSize, GTSL::uint32* scratchSize) { - GTSL::StaticVector vkGeometries; - GTSL::StaticVector primitiveCounts; - for (auto& e : geometries) { - VkAccelerationStructureGeometryKHR geometryKhr; VkAccelerationStructureBuildRangeInfoKHR buildRange; - buildGeometryAndRange(e, geometryKhr, buildRange); - vkGeometries.EmplaceBack(geometryKhr); primitiveCounts.EmplaceBack(e.PrimitiveCount); - } - - auto type = vkGeometries[0].geometryType == VK_GEOMETRY_TYPE_INSTANCES_KHR ? VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR : VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - - VkAccelerationStructureBuildGeometryInfoKHR buildInfo{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; - buildInfo.flags = ToVulkan(flags); - buildInfo.type = type; - buildInfo.geometryCount = vkGeometries.GetLength(); - buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - buildInfo.pGeometries = vkGeometries.begin(); - - VkAccelerationStructureBuildSizesInfoKHR buildSizes{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; - renderDevice->vkGetAccelerationStructureBuildSizesKHR(renderDevice->GetVkDevice(), ToVulkan(buildDevice), &buildInfo, primitiveCounts.begin(), &buildSizes); - - *accStructureSize = static_cast(buildSizes.accelerationStructureSize); *scratchSize = static_cast(buildSizes.buildScratchSize); - } - - void Initialize(const VulkanRenderDevice* renderDevice, bool topLevel, VulkanBuffer buffer, GTSL::uint32 size, GTSL::uint32 offset) { - VkAccelerationStructureCreateInfoKHR vkAccelerationStructureCreateInfoKhr{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; - vkAccelerationStructureCreateInfoKhr.createFlags = 0; - vkAccelerationStructureCreateInfoKhr.type = topLevel ? VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR : VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - vkAccelerationStructureCreateInfoKhr.offset = offset; - vkAccelerationStructureCreateInfoKhr.deviceAddress = 0; - vkAccelerationStructureCreateInfoKhr.buffer = buffer.GetVkBuffer(); - vkAccelerationStructureCreateInfoKhr.size = size; - - renderDevice->vkCreateAccelerationStructureKHR(renderDevice->GetVkDevice(), &vkAccelerationStructureCreateInfoKhr, renderDevice->GetVkAllocationCallbacks(), &accelerationStructure); - - //setName(info.RenderDevice, accelerationStructure, VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, info.Name); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->vkDestroyAccelerationStructureKHR(renderDevice->GetVkDevice(), accelerationStructure, renderDevice->GetVkAllocationCallbacks()); - debugClear(accelerationStructure); - } - - DeviceAddress GetAddress(const VulkanRenderDevice* renderDevice) const { - VkAccelerationStructureDeviceAddressInfoKHR deviceAddress{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR }; - deviceAddress.accelerationStructure = accelerationStructure; - return DeviceAddress(renderDevice->vkGetAccelerationStructureDeviceAddressKHR(renderDevice->GetVkDevice(), &deviceAddress)); - } - - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(accelerationStructure); } - - //UTILITY - static void BuildAccelerationStructure(const VulkanRenderDevice* renderDevice, GTSL::Range buildAccelerationStructureInfos); - - protected: - VkAccelerationStructureKHR accelerationStructure = nullptr; - }; - - struct AccelerationStructureBuildInfo { - VulkanAccelerationStructure SourceAccelerationStructure, DestinationAccelerationStructure; - GTSL::Range Geometries; - DeviceAddress ScratchBufferAddress; - GTSL::uint32 Flags = 0; - }; - - inline void VulkanAccelerationStructure::BuildAccelerationStructure(const VulkanRenderDevice* renderDevice, GTSL::Range buildAccelerationStructureInfos) { - GTSL::StaticVector buildGeometryInfos; - GTSL::StaticVector, 8> geometriesPerAccelerationStructure; - GTSL::StaticVector, 8> buildRangesPerAccelerationStructure; - GTSL::StaticVector buildRangesRangePerAccelerationStructure; - - for (GTSL::uint32 accStrInfoIndex = 0; accStrInfoIndex < static_cast(buildAccelerationStructureInfos.ElementCount()); ++accStrInfoIndex) { - auto& source = buildAccelerationStructureInfos[accStrInfoIndex]; - - geometriesPerAccelerationStructure.EmplaceBack(); - buildRangesPerAccelerationStructure.EmplaceBack(); - buildRangesRangePerAccelerationStructure.EmplaceBack(buildRangesPerAccelerationStructure[accStrInfoIndex].begin()); - - for (GTSL::uint32 i = 0; i < static_cast(source.Geometries.ElementCount()); ++i) { - VkAccelerationStructureGeometryKHR accelerationStructureGeometry; - VkAccelerationStructureBuildRangeInfoKHR buildRange; - buildGeometryAndRange(source.Geometries[i], accelerationStructureGeometry, buildRange); - geometriesPerAccelerationStructure[accStrInfoIndex].EmplaceBack(accelerationStructureGeometry); - buildRangesPerAccelerationStructure[accStrInfoIndex].EmplaceBack(buildRange); - } - - VkAccelerationStructureBuildGeometryInfoKHR buildGeometryInfo{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; - buildGeometryInfo.flags = source.Flags; - buildGeometryInfo.srcAccelerationStructure = source.SourceAccelerationStructure.GetVkAccelerationStructure(); - buildGeometryInfo.dstAccelerationStructure = source.DestinationAccelerationStructure.GetVkAccelerationStructure(); - buildGeometryInfo.type = source.Geometries[0].Type == GeometryType::INSTANCES ? VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR : VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - buildGeometryInfo.pGeometries = geometriesPerAccelerationStructure[accStrInfoIndex].begin(); - buildGeometryInfo.ppGeometries = nullptr; - buildGeometryInfo.geometryCount = geometriesPerAccelerationStructure[accStrInfoIndex].GetLength(); - buildGeometryInfo.scratchData.deviceAddress = static_cast(source.ScratchBufferAddress); - buildGeometryInfo.mode = source.SourceAccelerationStructure.GetVkAccelerationStructure() ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - buildGeometryInfos.EmplaceBack(buildGeometryInfo); - } - - renderDevice->vkBuildAccelerationStructuresKHR(renderDevice->GetVkDevice(), nullptr, static_cast(buildAccelerationStructureInfos.ElementCount()), buildGeometryInfos.begin(), buildRangesRangePerAccelerationStructure.begin()); - } - - inline void WriteInstance(const VulkanAccelerationStructure accelerationStructure, GTSL::uint32 instanceIndex, GeometryFlag geometryFlags, const VulkanRenderDevice* renderDevice, void* data, GTSL::uint32 instanceCustomIndex, Device device) { - auto& inst = *(static_cast(data) + instanceIndex); - inst.flags = ToVkGeometryInstanceFlagsKHR(geometryFlags); - inst.accelerationStructureReference = device == Device::CPU ? accelerationStructure.GetHandle() : static_cast(accelerationStructure.GetAddress(renderDevice)); - inst.instanceCustomIndex = instanceCustomIndex; - inst.mask = 0xFF; - inst.instanceShaderBindingTableRecordOffset = 0; - } - - inline void WriteInstanceIndex(const uint32 index, void* data, GTSL::uint32 instance_index) { - auto& inst = *(static_cast(data) + index); - inst.instanceCustomIndex = index; - } - - inline void WriteInstanceMatrix(const GTSL::Matrix3x4& matrix3X4, void* data, GTSL::uint32 index) { - auto& inst = *(static_cast(data) + index); - inst.transform = ToVulkan(matrix3X4); - } - - inline void WriteInstanceBindingTableRecordOffset(const GTSL::uint32 offset, void* data, GTSL::uint32 index) { - auto& inst = *(static_cast(data) + index); - inst.instanceShaderBindingTableRecordOffset = offset; - } -} diff --git a/src/GAL/Vulkan/VulkanAsyncHostOperation.h b/src/GAL/Vulkan/VulkanAsyncHostOperation.h deleted file mode 100644 index f7f4b929..00000000 --- a/src/GAL/Vulkan/VulkanAsyncHostOperation.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "Vulkan.h" -#include "VulkanRenderDevice.h" - -namespace GAL -{ - class VulkanRenderDevice; - - class VulkanAsyncHostOperation - { - public: - VulkanAsyncHostOperation() = default; - - void Initialize(const VulkanRenderDevice* renderDevice) { - renderDevice->vkCreateDeferredOperationKHR(renderDevice->GetVkDevice(), renderDevice->GetVkAllocationCallbacks(), &deferredOperation); - } - - GTSL::uint32 GetMaxConcurrency(const VulkanRenderDevice* renderDevice) { - return renderDevice->vkGetDeferredOperationMaxConcurrencyKHR(renderDevice->GetVkDevice(), deferredOperation); - } - - bool GetResult(const VulkanRenderDevice* renderDevice) { - return renderDevice->vkGetDeferredOperationResultKHR(renderDevice->GetVkDevice(), deferredOperation) == VK_SUCCESS; - } - - enum class JoinResult { - DONE, PENDING, WAITING - }; - JoinResult Join(const VulkanRenderDevice* renderDevice) { - switch (renderDevice->vkDeferredOperationJoinKHR(renderDevice->GetVkDevice(), deferredOperation)) - { - case VK_SUCCESS: return JoinResult::DONE; - case VK_THREAD_DONE_KHR: return JoinResult::PENDING; - case VK_THREAD_IDLE_KHR: return JoinResult::WAITING; - } - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->vkDestroyDeferredOperationKHR(renderDevice->GetVkDevice(), deferredOperation, renderDevice->GetVkAllocationCallbacks()); - } - - [[nodiscard]] VkDeferredOperationKHR GetVkDeferredHostOperationKHR() const { return deferredOperation; } - - private: - VkDeferredOperationKHR deferredOperation; - }; -} diff --git a/src/GAL/Vulkan/VulkanBindings.h b/src/GAL/Vulkan/VulkanBindings.h deleted file mode 100644 index 9c644cac..00000000 --- a/src/GAL/Vulkan/VulkanBindings.h +++ /dev/null @@ -1,279 +0,0 @@ -#pragma once - -#include "GAL/Bindings.h" - -#include "Vulkan.h" -#include "VulkanAccelerationStructures.h" -#include "VulkanBuffer.h" -#include "VulkanRenderDevice.h" -#include "VulkanTexture.h" -#include "GTSL/Vector.hpp" - -namespace GAL -{ - class VulkanBindingsSet; - - class VulkanBindingsPool final : public BindingsPool - { - public: - VulkanBindingsPool() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, GTSL::Range bindingsPoolSizes, GTSL::uint32 maxSets) { - GTSL::StaticVector vkDescriptorPoolSizes; - - for (GTSL::uint32 i = 0; i < static_cast(bindingsPoolSizes.ElementCount()); ++i) { - auto& descriptorPoolSize = vkDescriptorPoolSizes.EmplaceBack(); - descriptorPoolSize.type = ToVulkan(bindingsPoolSizes[i].Type); - //Max number of descriptors of VkDescriptorPoolSize::type we can allocate. - descriptorPoolSize.descriptorCount = bindingsPoolSizes[&descriptorPoolSize - vkDescriptorPoolSizes.begin()].Count; - } - - VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - //Is the total number of sets that can be allocated from the pool. - vkDescriptorPoolCreateInfo.maxSets = maxSets; - vkDescriptorPoolCreateInfo.poolSizeCount = vkDescriptorPoolSizes.GetLength(); - vkDescriptorPoolCreateInfo.pPoolSizes = vkDescriptorPoolSizes.begin(); - renderDevice->VkCreateDescriptorPool(renderDevice->GetVkDevice(), &vkDescriptorPoolCreateInfo, renderDevice->GetVkAllocationCallbacks(), &descriptorPool); - //setName(renderDevice, descriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL, createInfo.Name); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyDescriptorPool(renderDevice->GetVkDevice(), descriptorPool, renderDevice->GetVkAllocationCallbacks()); - debugClear(descriptorPool); - } - - //void FreeBindingsSet(const VulkanRenderDevice* renderDevice) { - // vkFreeDescriptorSets(renderDevice->GetVkDevice(), descriptorPool, - // static_cast(freeBindingsSetInfo.BindingsSet.ElementCount()), reinterpret_cast(freeBindingsSetInfo.BindingsSet.begin())); - //} - - [[nodiscard]] VkDescriptorPool GetVkDescriptorPool() const { return descriptorPool; } - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(descriptorPool); } - - struct TextureBindingUpdateInfo { - VulkanSampler Sampler; - VulkanTextureView TextureView; - TextureLayout Layout; - FormatDescriptor Format; - }; - - struct BufferBindingUpdateInfo { - VulkanBuffer Buffer; - GTSL::uint64 Offset, Range; - }; - - struct AccelerationStructureBindingUpdateInfo { - VulkanAccelerationStructure AccelerationStructure; - }; - - union BindingUpdateInfo - { - BindingUpdateInfo(TextureBindingUpdateInfo info) : TextureBinding(info) {} - BindingUpdateInfo(BufferBindingUpdateInfo info) : BufferBinding(info) {} - BindingUpdateInfo(AccelerationStructureBindingUpdateInfo info) : AccelerationStructure(info) {} - - TextureBindingUpdateInfo TextureBinding; - BufferBindingUpdateInfo BufferBinding; - AccelerationStructureBindingUpdateInfo AccelerationStructure; - }; - - struct BindingsUpdateInfo - { - VulkanBindingsSet* BindingsSet; - BindingType Type; - GTSL::uint32 SubsetIndex = 0, BindingIndex = 0; - GTSL::Range BindingUpdateInfos; - }; - - template - void Update(const VulkanRenderDevice* renderDevice, GTSL::Range bindingsUpdateInfos, const ALLOCATOR& allocator); - - private: - VkDescriptorPool descriptorPool; - }; - - class VulkanBindingsSetLayout final : public BindingSetLayout { - public: - struct ImageBindingDescriptor : BindingDescriptor { - GTSL::Range ImageViews; - GTSL::Range Layouts; - }; - - struct BufferBindingDescriptor : BindingDescriptor { - GTSL::Range Buffers; - GTSL::Range Offsets; - GTSL::Range Sizes; - }; - - struct BindingDescriptor { - BindingType Type; - ShaderStage Stage; - GTSL::uint32 BindingsCount; - BindingFlag Flags; - GTSL::Range Samplers; - }; - - VulkanBindingsSetLayout() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, GTSL::Range bindingsDescriptors) { - - VkDescriptorSetLayoutCreateInfo vkDescriptorSetLayoutCreateInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; - VkDescriptorSetLayoutBindingFlagsCreateInfo vkDescriptorSetLayoutBindingFlagsCreateInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO }; - vkDescriptorSetLayoutCreateInfo.pNext = &vkDescriptorSetLayoutBindingFlagsCreateInfo; - - GTSL::StaticVector vkDescriptorBindingFlags; - GTSL::StaticVector vkDescriptorSetLayoutBindings; - - GTSL::StaticVector staticSamplers; - - for (GTSL::uint32 i = 0; i < static_cast(bindingsDescriptors.ElementCount()); ++i) { - vkDescriptorBindingFlags.EmplaceBack(ToVulkan(bindingsDescriptors[i].Flags)); - - auto& binding = vkDescriptorSetLayoutBindings.EmplaceBack(); - binding.binding = i; - binding.descriptorCount = bindingsDescriptors[i].BindingsCount; - binding.descriptorType = ToVulkan(bindingsDescriptors[i].Type); - binding.stageFlags = ToVulkan(bindingsDescriptors[i].Stage); - - if(bindingsDescriptors[i].Samplers.ElementCount()) { - for(auto& e : bindingsDescriptors[i].Samplers) { - staticSamplers.EmplaceBack(static_cast(e).GetVkSampler()); - } - - binding.pImmutableSamplers = staticSamplers.GetData(); - } else { - binding.pImmutableSamplers = nullptr; - } - } - - vkDescriptorSetLayoutBindingFlagsCreateInfo.bindingCount = vkDescriptorSetLayoutBindings.GetLength(); - vkDescriptorSetLayoutBindingFlagsCreateInfo.pBindingFlags = vkDescriptorBindingFlags.begin(); - vkDescriptorSetLayoutCreateInfo.bindingCount = vkDescriptorSetLayoutBindings.GetLength(); - vkDescriptorSetLayoutCreateInfo.pBindings = vkDescriptorSetLayoutBindings.begin(); - - renderDevice->VkCreateDescriptorSetLayout(renderDevice->GetVkDevice(), &vkDescriptorSetLayoutCreateInfo, renderDevice->GetVkAllocationCallbacks(), &descriptorSetLayout); - //setName(createInfo.RenderDevice, &descriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, createInfo.Name); - } - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyDescriptorSetLayout(renderDevice->GetVkDevice(), descriptorSetLayout, renderDevice->GetVkAllocationCallbacks()); - debugClear(descriptorSetLayout); - } - - [[nodiscard]] VkDescriptorSetLayout GetVkDescriptorSetLayout() const { return descriptorSetLayout; } - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(descriptorSetLayout); } - - private: - VkDescriptorSetLayout descriptorSetLayout = nullptr; - }; - - class VulkanBindingsSet final : public BindingsSet - { - public: - VulkanBindingsSet() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, VulkanBindingsPool bindingsPool, const VulkanBindingsSetLayout bindingsSetLayouts) { - auto vkDescriptorSetLayout = bindingsSetLayouts.GetVkDescriptorSetLayout(); - - VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; - //vkDescriptorSetAllocateInfo.pNext = &vkDescriptorSetVariableDescriptorCountAllocateInfo; - vkDescriptorSetAllocateInfo.descriptorPool = bindingsPool.GetVkDescriptorPool(); - vkDescriptorSetAllocateInfo.descriptorSetCount = 1; - vkDescriptorSetAllocateInfo.pSetLayouts = &vkDescriptorSetLayout; - renderDevice->VkAllocateDescriptorSets(renderDevice->GetVkDevice(), &vkDescriptorSetAllocateInfo, &descriptorSet); - } - - [[nodiscard]] VkDescriptorSet GetVkDescriptorSet() const { return descriptorSet; } - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(descriptorSet); } - - private: - VkDescriptorSet descriptorSet; - }; - - //TODO: fix up potential pointer errors - - template - void VulkanBindingsPool::Update(const VulkanRenderDevice* renderDevice, GTSL::Range bindingsUpdateInfos, const ALLOCATOR& allocator) { - GTSL::Vector vkWriteDescriptorSets(static_cast(bindingsUpdateInfos.ElementCount()), allocator); - GTSL::Vector vkWriteDescriptorSetsAcc(2, allocator); - - GTSL::Vector, ALLOCATOR> accelerationStructuresPerSubSetUpdate(8, allocator); - GTSL::Vector, ALLOCATOR> buffersPerSubSetUpdate(8, allocator); - GTSL::Vector, ALLOCATOR> imagesPerSubSetUpdate(8, allocator); - GTSL::Vector, ALLOCATOR> accPerSubSetUpdate(8, allocator); - - for (GTSL::uint32 index = 0; index < static_cast(bindingsUpdateInfos.ElementCount()); ++index) { - VkWriteDescriptorSet& writeSet = vkWriteDescriptorSets.EmplaceBack(); - auto& info = bindingsUpdateInfos[index]; - - writeSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeSet.pNext = nullptr; - writeSet.dstSet = info.BindingsSet->GetVkDescriptorSet(); - writeSet.dstBinding = info.SubsetIndex; - writeSet.dstArrayElement = info.BindingIndex; - writeSet.descriptorCount = static_cast(info.BindingUpdateInfos.ElementCount()); - writeSet.descriptorType = ToVulkan(info.Type); - writeSet.pImageInfo = nullptr; - writeSet.pBufferInfo = nullptr; - writeSet.pTexelBufferView = nullptr; - - switch (info.Type) { - case BindingType::SAMPLER: - case BindingType::COMBINED_IMAGE_SAMPLER: - case BindingType::SAMPLED_IMAGE: - case BindingType::STORAGE_IMAGE: - case BindingType::INPUT_ATTACHMENT: { - imagesPerSubSetUpdate.EmplaceBack(8, allocator); - - for (auto e : info.BindingUpdateInfos) { - auto& vkDescriptorImageInfo = imagesPerSubSetUpdate.back().EmplaceBack(); - vkDescriptorImageInfo.sampler = e.TextureBinding.Sampler.GetVkSampler(); - vkDescriptorImageInfo.imageView = e.TextureBinding.TextureView.GetVkImageView(); - vkDescriptorImageInfo.imageLayout = ToVulkan(e.TextureBinding.Layout, e.TextureBinding.Format); - } - - writeSet.pImageInfo = imagesPerSubSetUpdate.back().begin(); - - break; - } - case BindingType::UNIFORM_TEXEL_BUFFER: GAL_DEBUG_BREAK; - case BindingType::STORAGE_TEXEL_BUFFER: GAL_DEBUG_BREAK; - case BindingType::UNIFORM_BUFFER: - case BindingType::STORAGE_BUFFER: - case BindingType::UNIFORM_BUFFER_DYNAMIC: - case BindingType::STORAGE_BUFFER_DYNAMIC: { - buffersPerSubSetUpdate.EmplaceBack(8, allocator); - - for (auto e : info.BindingUpdateInfos) { - auto& vkDescriptorBufferInfo = buffersPerSubSetUpdate.back().EmplaceBack(); - vkDescriptorBufferInfo.buffer = e.BufferBinding.Buffer.GetVkBuffer(); - vkDescriptorBufferInfo.offset = e.BufferBinding.Offset; - vkDescriptorBufferInfo.range = e.BufferBinding.Range; - } - - writeSet.pBufferInfo = buffersPerSubSetUpdate.back().begin(); - break; - } - case BindingType::ACCELERATION_STRUCTURE: { - auto& vkwds = vkWriteDescriptorSetsAcc.EmplaceBack(); - - vkwds.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; - vkwds.pNext = nullptr; - - writeSet.pNext = &vkwds; - - vkwds.accelerationStructureCount = static_cast(info.BindingUpdateInfos.ElementCount()); - accelerationStructuresPerSubSetUpdate.EmplaceBack(8, allocator); - - for (auto e : info.BindingUpdateInfos) { - auto& vkAcc = accPerSubSetUpdate.back().EmplaceBack(e.AccelerationStructure.AccelerationStructure); - } - - vkwds.pAccelerationStructures = accelerationStructuresPerSubSetUpdate.back().GetData(); - break; - } - } - } - - renderDevice->VkUpdateDescriptorSets(renderDevice->GetVkDevice(), vkWriteDescriptorSets.GetLength(), vkWriteDescriptorSets.begin(), 0, nullptr); - } -} diff --git a/src/GAL/Vulkan/VulkanBuffer.h b/src/GAL/Vulkan/VulkanBuffer.h deleted file mode 100644 index 2712f9ed..00000000 --- a/src/GAL/Vulkan/VulkanBuffer.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "GAL/Buffer.h" - -#include "Vulkan.h" -#include "VulkanMemory.h" -#include "VulkanRenderDevice.h" - -namespace GAL -{ - class VulkanBuffer final : public Buffer - { - public: - VulkanBuffer() = default; - ~VulkanBuffer() = default; - - void GetMemoryRequirements(const VulkanRenderDevice* renderDevice, GTSL::uint32 size, BufferUse bufferUses, MemoryRequirements* memoryRequirements) - { - VkBufferCreateInfo vkBufferCreateInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - vkBufferCreateInfo.size = size; - vkBufferCreateInfo.usage = ToVulkan(bufferUses); - vkBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - renderDevice->VkCreateBuffer(renderDevice->GetVkDevice(), &vkBufferCreateInfo, renderDevice->GetVkAllocationCallbacks(), &buffer); - - VkMemoryRequirements vkMemoryRequirements; - renderDevice->VkGetBufferMemoryRequirements(renderDevice->GetVkDevice(), buffer, &vkMemoryRequirements); - memoryRequirements->Size = static_cast(vkMemoryRequirements.size); - memoryRequirements->Alignment = static_cast(vkMemoryRequirements.alignment); - memoryRequirements->MemoryTypes = vkMemoryRequirements.memoryTypeBits; - } - - void Initialize(const VulkanRenderDevice* renderDevice, const MemoryRequirements&, VulkanDeviceMemory memory, GTSL::uint32 offset) { - //SET_NAME(buffer, VK_OBJECT_TYPE_BUFFER, info); - renderDevice->VkBindBufferMemory(renderDevice->GetVkDevice(), buffer, static_cast(memory.GetVkDeviceMemory()), offset); - } - - [[nodiscard]] DeviceAddress GetAddress(const VulkanRenderDevice* renderDevice) const { - VkBufferDeviceAddressInfo vkBufferDeviceAddressInfo{ VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO }; - vkBufferDeviceAddressInfo.buffer = buffer; - return DeviceAddress(renderDevice->VkGetBufferDeviceAddress(renderDevice->GetVkDevice(), &vkBufferDeviceAddressInfo)); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyBuffer(renderDevice->GetVkDevice(), buffer, renderDevice->GetVkAllocationCallbacks()); - debugClear(buffer); - } - - [[nodiscard]] VkBuffer GetVkBuffer() const { return buffer; } - - private: - VkBuffer buffer = nullptr; - }; -} diff --git a/src/GAL/Vulkan/VulkanCommandList.h b/src/GAL/Vulkan/VulkanCommandList.h deleted file mode 100644 index 45e9f86e..00000000 --- a/src/GAL/Vulkan/VulkanCommandList.h +++ /dev/null @@ -1,483 +0,0 @@ -#pragma once - -#include "GAL/CommandList.h" - -#include "Vulkan.h" -#include "VulkanTexture.h" -#include "VulkanRenderDevice.h" -#include "VulkanAccelerationStructures.h" -#include "VulkanPipelines.h" -#include - -#include "VulkanBindings.h" -#include "VulkanRenderPass.h" -#include "VulkanSynchronization.h" -#include "GTSL/Vector.hpp" - -#undef MemoryBarrier - -namespace GAL { - class VulkanCommandList final : public CommandList { - public: - VulkanCommandList() = default; - - explicit VulkanCommandList(const VkCommandBuffer commandBuffer) : commandBuffer(commandBuffer) {} - - void Initialize(const VulkanRenderDevice* renderDevice, const GTSL::StringView name, VulkanRenderDevice::QueueKey queueKey, const bool isOptimized = false, const bool isPrimary = true) { - VkCommandPoolCreateInfo vkCommandPoolCreateInfo{ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; - vkCommandPoolCreateInfo.queueFamilyIndex = queueKey.Family; - renderDevice->VkCreateCommandPool(renderDevice->GetVkDevice(), &vkCommandPoolCreateInfo, renderDevice->GetVkAllocationCallbacks(), &commandPool); - //setName(renderDevice, commandPool, VK_OBJECT_TYPE_COMMAND_POOL, createInfo.Name); - - VkCommandBufferAllocateInfo vkCommandBufferAllocateInfo { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO}; - vkCommandBufferAllocateInfo.commandPool = commandPool; - vkCommandBufferAllocateInfo.level = isPrimary ? VK_COMMAND_BUFFER_LEVEL_PRIMARY : VK_COMMAND_BUFFER_LEVEL_SECONDARY; - vkCommandBufferAllocateInfo.commandBufferCount = 1; - - this->isOptimized = isOptimized; - - renderDevice->VkAllocateCommandBuffers(renderDevice->GetVkDevice(), &vkCommandBufferAllocateInfo, &commandBuffer); - setName(renderDevice, commandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, name); - } - - void BeginRecording(const VulkanRenderDevice* renderDevice) const { - VkCommandBufferBeginInfo vkCommandBufferBeginInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; - vkCommandBufferBeginInfo.flags |= isOptimized ? 0 : VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - - renderDevice->VkResetCommandPool(renderDevice->GetVkDevice(), commandPool, 0); - renderDevice->VkBeginCommandBuffer(commandBuffer, &vkCommandBufferBeginInfo); - } - - void EndRecording(const VulkanRenderDevice* renderDevice) const { renderDevice->VkEndCommandBuffer(commandBuffer); } - - void ExecuteCommandLists(const VulkanRenderDevice* render_device, const GTSL::Range command_lists) const { - GTSL::StaticVector vkCommandBuffers; - for(auto& e : command_lists) { vkCommandBuffers.EmplaceBack(e.GetVkCommandBuffer()); } - render_device->VkCmdExecuteCommands(commandBuffer, vkCommandBuffers.GetLength(), vkCommandBuffers.GetData()); - } - - //void BeginRenderPass(const VulkanRenderDevice* renderDevice, VulkanRenderPass renderPass, VulkanFramebuffer framebuffer, - // GTSL::Extent2D renderArea, GTSL::Range renderPassTargetDescriptions) { - // VkRenderPassBeginInfo vkRenderPassBeginInfo{ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO }; - // vkRenderPassBeginInfo.renderPass = renderPass.GetVkRenderPass(); - // - // VkClearValue vkClearValues[32]; - // - // for (GTSL::uint8 i = 0; i < static_cast(renderPassTargetDescriptions.ElementCount()); ++i) { - // const auto& color = renderPassTargetDescriptions[i].ClearValue; - // vkClearValues[i] = VkClearValue{ color.R(), color.G(), color.B(), color.A() }; - // } - // - // vkRenderPassBeginInfo.pClearValues = vkClearValues; - // vkRenderPassBeginInfo.clearValueCount = static_cast(renderPassTargetDescriptions.ElementCount()); - // vkRenderPassBeginInfo.framebuffer = framebuffer.GetVkFramebuffer(); - // vkRenderPassBeginInfo.renderArea.extent = ToVulkan(renderArea); - // vkRenderPassBeginInfo.renderArea.offset = { 0, 0 }; - // - // renderDevice->VkCmdBeginRenderPass(commandBuffer, &vkRenderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - //} - // - //void AdvanceSubPass(const VulkanRenderDevice* renderDevice) { renderDevice->VkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); } - // - //void EndRenderPass(const VulkanRenderDevice* renderDevice) { renderDevice->VkCmdEndRenderPass(commandBuffer); } - - void BeginRenderPass(const VulkanRenderDevice* renderDevice, GTSL::Extent2D renderArea, GTSL::Range renderPassTargetDescriptions) { - GTSL::StaticVector colorAttachmentInfos; VkRenderingAttachmentInfoKHR depthAttachmentInfo; - - VkRenderingInfoKHR vk_rendering_info_khr{ VK_STRUCTURE_TYPE_RENDERING_INFO_KHR }; - vk_rendering_info_khr.flags = 0; - vk_rendering_info_khr.layerCount = 1; //TODO: if 0 device lost, validation layers? - - for(auto& e : renderPassTargetDescriptions) { - VkRenderingAttachmentInfoKHR* attachmentInfo; - - if (e.format.Type == TextureType::COLOR) { - attachmentInfo = &colorAttachmentInfos.EmplaceBack(); - } else { - attachmentInfo = &depthAttachmentInfo; - vk_rendering_info_khr.pDepthAttachment = &depthAttachmentInfo; - } - - attachmentInfo->sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; - attachmentInfo->pNext = nullptr; - attachmentInfo->clearValue = { e.ClearValue.R(), e.ClearValue.G(), e.ClearValue.B(), e.ClearValue.A() }; - attachmentInfo->imageLayout = ToVulkan(e.Start, e.format); - attachmentInfo->imageView = reinterpret_cast(e.textureView)->GetVkImageView(); - attachmentInfo->loadOp = ToVkAttachmentLoadOp(e.LoadOperation); - attachmentInfo->storeOp = ToVkAttachmentStoreOp(e.StoreOperation); - attachmentInfo->resolveMode = VK_RESOLVE_MODE_NONE; - attachmentInfo->resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachmentInfo->resolveImageView = nullptr; - } - - vk_rendering_info_khr.colorAttachmentCount = colorAttachmentInfos.GetLength(); - vk_rendering_info_khr.pColorAttachments = colorAttachmentInfos.GetData(); - vk_rendering_info_khr.pStencilAttachment = nullptr; - vk_rendering_info_khr.renderArea = { { 0, 0 }, { renderArea.Width, renderArea.Height } }; - vk_rendering_info_khr.viewMask = 0; //multiview - renderDevice->VkCmdBeginRendering(commandBuffer, &vk_rendering_info_khr); - - VkViewport viewport; - viewport.x = 0; - viewport.y = 0; - //viewport.y = renderArea.Height; - viewport.minDepth = 0; - viewport.maxDepth = 1.0f; - viewport.width = renderArea.Width; - viewport.height = renderArea.Height; - //viewport.height = -renderArea.Height; - renderDevice->VkCmdSetViewport(commandBuffer, 0, 1, &viewport); - - VkRect2D scissor; - scissor.extent.width = renderArea.Width; - scissor.extent.height = renderArea.Height; - scissor.offset = { 0, 0 }; - renderDevice->VkCmdSetScissor(commandBuffer, 0, 1, &scissor); - } - - void EndRenderPass(const VulkanRenderDevice* renderDevice) { - renderDevice->VkCmdEndRendering(commandBuffer); - } - - void BindPipeline(const VulkanRenderDevice* renderDevice, VulkanPipeline pipeline, ShaderStage shaderStage) const { - VkPipelineBindPoint pipelineBindPoint; - - if (shaderStage & (ShaderStages::VERTEX | ShaderStages::FRAGMENT)) { - pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - } else { - if(shaderStage & ShaderStages::COMPUTE) { - pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; - } else { - pipelineBindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; - } - } - - renderDevice->VkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline.GetVkPipeline()); - } - - void BindIndexBuffer(const VulkanRenderDevice* renderDevice, const VulkanBuffer buffer, GTSL::uint32 offset, [[maybe_unused]] const GTSL::uint32 indexCount, const IndexType indexType) const { - renderDevice->VkCmdBindIndexBuffer(commandBuffer, buffer.GetVkBuffer(), offset, ToVulkan(indexType)); - } - - void BindVertexBuffers(const VulkanRenderDevice* renderDevice, GTSL::Range buffers, GTSL::Range offsets, [[maybe_unused]] GTSL::uint32 size, [[maybe_unused]] GTSL::uint32 stride) const { - GTSL::StaticVector vkBuffers; - GTSL::StaticVector vkOffsets; - - for(uint32 i = 0; i < buffers.ElementCount(); ++i) { - vkBuffers.EmplaceBack(buffers[i].GetVkBuffer()); - vkOffsets.EmplaceBack(offsets[i]); - } - - renderDevice->VkCmdBindVertexBuffers(commandBuffer, 0, vkBuffers.GetLength(), vkBuffers.GetData(), vkOffsets.GetData()); - } - - void UpdatePushConstant(const VulkanRenderDevice* renderDevice, VulkanPipelineLayout pipelineLayout, GTSL::uint32 offset, GTSL::Range data, ShaderStage shaderStages) { - GTSL_ASSERT(data.ElementCount() < 128, "Data size is larger than can be pushed."); - renderDevice->VkCmdPushConstants(commandBuffer, pipelineLayout.GetVkPipelineLayout(), ToVulkan(shaderStages), offset, static_cast(data.Bytes()), data.begin()); - } - - void Draw(const VulkanRenderDevice* renderDevice, uint32_t vertex_count, uint32_t instance_count = 1, uint32_t base_instance_index = 0) const { - renderDevice->VkCmdDraw(commandBuffer, vertex_count, instance_count, 0, base_instance_index); - } - - void DrawIndexed(const VulkanRenderDevice* renderDevice, uint32_t indexCount, uint32_t instanceCount, uint32_t first_instance_index, uint32 index_offset, uint32 vertex_offset) const { - renderDevice->VkCmdDrawIndexed(commandBuffer, indexCount, instanceCount, index_offset, vertex_offset, first_instance_index); - } - - void DrawMesh(const VulkanRenderDevice* renderDevice, GTSL::uint32 taskCount) const { - renderDevice->VkCmdDrawMeshTasks(commandBuffer, taskCount, 0); - } - - void TraceRays(const VulkanRenderDevice* renderDevice, GTSL::StaticVector shaderTableDescriptors, GTSL::Extent3D dispatchSize) { - VkStridedDeviceAddressRegionKHR raygenSBT, hitSBT, missSBT, callableSBT; - raygenSBT.deviceAddress = static_cast(shaderTableDescriptors[RAY_GEN_TABLE_INDEX].Address); - raygenSBT.size = shaderTableDescriptors[RAY_GEN_TABLE_INDEX].Entries * shaderTableDescriptors[RAY_GEN_TABLE_INDEX].EntrySize; - raygenSBT.stride = shaderTableDescriptors[RAY_GEN_TABLE_INDEX].EntrySize; - - hitSBT.deviceAddress = static_cast(shaderTableDescriptors[HIT_TABLE_INDEX].Address); - hitSBT.size = shaderTableDescriptors[HIT_TABLE_INDEX].Entries * shaderTableDescriptors[HIT_TABLE_INDEX].EntrySize; - hitSBT.stride = shaderTableDescriptors[HIT_TABLE_INDEX].EntrySize; - - missSBT.deviceAddress = static_cast(shaderTableDescriptors[MISS_TABLE_INDEX].Address); - missSBT.size = shaderTableDescriptors[MISS_TABLE_INDEX].Entries * shaderTableDescriptors[MISS_TABLE_INDEX].EntrySize; - missSBT.stride = shaderTableDescriptors[MISS_TABLE_INDEX].EntrySize; - - callableSBT.deviceAddress = static_cast(shaderTableDescriptors[CALLABLE_TABLE_INDEX].Address); - callableSBT.size = shaderTableDescriptors[CALLABLE_TABLE_INDEX].Entries * shaderTableDescriptors[CALLABLE_TABLE_INDEX].EntrySize; - callableSBT.stride = shaderTableDescriptors[CALLABLE_TABLE_INDEX].EntrySize; - - renderDevice->vkCmdTraceRaysKHR(commandBuffer, &raygenSBT, &missSBT, &hitSBT, &callableSBT, dispatchSize.Width, dispatchSize.Height, dispatchSize.Depth); - } - - void AddLabel(const VulkanRenderDevice* renderDevice, GTSL::Range name) const { -#if BE_DEBUG - VkDebugUtilsLabelEXT vkLabelInfo{ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; - vkLabelInfo.pLabelName = reinterpret_cast(name.GetData()); - renderDevice->vkCmdInsertDebugUtilsLabelEXT(commandBuffer, &vkLabelInfo); -#endif - } - - void BeginRegion(const VulkanRenderDevice* renderDevice, GTSL::Range name) const { -#if BE_DEBUG - VkDebugUtilsLabelEXT vkLabelInfo{ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; - vkLabelInfo.pLabelName = reinterpret_cast(name.GetData()); - renderDevice->vkCmdBeginDebugUtilsLabelEXT(commandBuffer, &vkLabelInfo); -#endif - } - - void EndRegion(const VulkanRenderDevice* renderDevice) const { -#if BE_DEBUG - renderDevice->vkCmdEndDebugUtilsLabelEXT(commandBuffer); -#endif - } - - void Dispatch(const VulkanRenderDevice* renderDevice, GTSL::Extent3D workGroups) { - renderDevice->VkCmdDispatch(commandBuffer, workGroups.Width, workGroups.Height, workGroups.Depth); - } - - void DispatchIndirect(const VulkanRenderDevice* render_device, const VulkanBuffer buffer, const uint64 offset) { - render_device->VkCmdDispatchIndirect(commandBuffer, buffer.GetVkBuffer(), offset); - } - - void BindBindingsSets(const VulkanRenderDevice* renderDevice, ShaderStage shaderStage, GTSL::Range bindingsSets, VulkanPipelineLayout pipelineLayout, GTSL::uint32 firstSet) { - GTSL::StaticVector vkDescriptorSets; - for (auto e : bindingsSets) { vkDescriptorSets.EmplaceBack(e.GetVkDescriptorSet()); } - - const GTSL::uint32 bindingSetCount = static_cast(bindingsSets.ElementCount()); - - if (shaderStage & (ShaderStages::VERTEX | ShaderStages::FRAGMENT | ShaderStages::MESH)) { - renderDevice->VkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.GetVkPipelineLayout(), firstSet, bindingSetCount, vkDescriptorSets.begin(), 0, nullptr); - } - if (shaderStage & ShaderStages::COMPUTE) { - renderDevice->VkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.GetVkPipelineLayout(), firstSet, bindingSetCount, vkDescriptorSets.begin(), 0, nullptr); - } - if (shaderStage & ShaderStages::RAY_GEN) { - renderDevice->VkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.GetVkPipelineLayout(), firstSet, bindingSetCount, vkDescriptorSets.begin(), 0, nullptr); - } - } - - void BindBindingsSets(const VulkanRenderDevice* renderDevice, ShaderStage shaderStage, GTSL::Range bindingsSets, GTSL::Range offsets, VulkanPipelineLayout pipelineLayout, GTSL::uint32 firstSet) { - - GTSL::StaticVector vkDescriptorSets; - for (auto e : bindingsSets) { vkDescriptorSets.EmplaceBack(e.GetVkDescriptorSet()); } - - const GTSL::uint32 bindingSetCount = static_cast(bindingsSets.ElementCount()), offsetCount = static_cast(offsets.ElementCount()); - - if (shaderStage & (ShaderStages::VERTEX | ShaderStages::FRAGMENT | ShaderStages::MESH)) { - renderDevice->VkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.GetVkPipelineLayout(), firstSet, bindingSetCount, - reinterpret_cast(bindingsSets.begin()), offsetCount, offsets.begin()); - } - - if (shaderStage & ShaderStages::COMPUTE) { - renderDevice->VkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.GetVkPipelineLayout(), firstSet, bindingSetCount, - reinterpret_cast(bindingsSets.begin()), offsetCount, offsets.begin()); - } - - if(shaderStage & ShaderStages::RAY_GEN) { - renderDevice->VkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.GetVkPipelineLayout(), firstSet, bindingSetCount, - reinterpret_cast(bindingsSets.begin()), offsetCount, offsets.begin()); - } - } - - void CopyTextureToTexture(const VulkanRenderDevice* renderDevice, VulkanTexture sourceTexture, VulkanTexture destinationTexture, TextureLayout sourceLayout, TextureLayout destinationLayout, FormatDescriptor sourceFormat, FormatDescriptor destinationFormat, GTSL::Extent3D extent) { - VkImageCopy vkImageCopy; - vkImageCopy.extent = ToVulkan(extent); - vkImageCopy.srcOffset = {}; - vkImageCopy.dstOffset = {}; - vkImageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkImageCopy.srcSubresource.baseArrayLayer = 0; - vkImageCopy.srcSubresource.layerCount = 1; - vkImageCopy.srcSubresource.mipLevel = 0; - - vkImageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkImageCopy.dstSubresource.baseArrayLayer = 0; - vkImageCopy.dstSubresource.layerCount = 1; - vkImageCopy.dstSubresource.mipLevel = 0; - - renderDevice->VkCmdCopyImage(commandBuffer, sourceTexture.GetVkImage(), ToVulkan(sourceLayout, sourceFormat), destinationTexture.GetVkImage(), ToVulkan(destinationLayout, destinationFormat), 1, &vkImageCopy); - } - - void BlitTexture(const VulkanRenderDevice* render_device, const VulkanTexture source_texture, const TextureLayout source_layout, const FormatDescriptor source_format_descriptor, const GTSL::Extent3D source_extent, const VulkanTexture destination_texture, const TextureLayout destination_layout, const FormatDescriptor destination_format_descriptor, const GTSL::Extent3D destination_extent) { - VkImageBlit2KHR vkImageBlit2Khr{ VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR }; - vkImageBlit2Khr.srcOffsets[0] = { 0, 0, 0 }; - vkImageBlit2Khr.srcOffsets[1] = { source_extent.Width, source_extent.Height, source_extent.Depth }; - vkImageBlit2Khr.srcSubresource.mipLevel = 0; - vkImageBlit2Khr.srcSubresource.baseArrayLayer = 0; - vkImageBlit2Khr.srcSubresource.layerCount = 1; - vkImageBlit2Khr.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - vkImageBlit2Khr.dstOffsets[0] = { 0, 0, 0 }; - vkImageBlit2Khr.dstOffsets[1] = { destination_extent.Width, destination_extent.Height, destination_extent.Depth }; - vkImageBlit2Khr.dstSubresource.mipLevel = 0; - vkImageBlit2Khr.dstSubresource.baseArrayLayer = 0; - vkImageBlit2Khr.dstSubresource.layerCount = 1; - vkImageBlit2Khr.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - VkBlitImageInfo2KHR vkBlitImageInfo2Khr{ VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR }; - vkBlitImageInfo2Khr.srcImage = source_texture.GetVkImage(); - vkBlitImageInfo2Khr.srcImageLayout = ToVulkan(source_layout, source_format_descriptor); - vkBlitImageInfo2Khr.dstImage = destination_texture.GetVkImage(); - vkBlitImageInfo2Khr.dstImageLayout = ToVulkan(destination_layout, destination_format_descriptor); - vkBlitImageInfo2Khr.filter = VK_FILTER_LINEAR; - vkBlitImageInfo2Khr.regionCount = 1; - vkBlitImageInfo2Khr.pRegions = &vkImageBlit2Khr; - render_device->VkCmdBlitImage2KHR(commandBuffer, &vkBlitImageInfo2Khr); - } - - void CopyBufferToTexture(const VulkanRenderDevice* renderDevice, VulkanBuffer source, VulkanTexture destination, const TextureLayout layout, const FormatDescriptor format, GTSL::Extent3D extent) { - VkBufferImageCopy region; - region.bufferOffset = 0; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; - region.imageOffset = VkOffset3D{ 0, 0, 0 }; - region.imageExtent = ToVulkan(extent); - renderDevice->VkCmdCopyBufferToImage(commandBuffer, source.GetVkBuffer(), destination.GetVkImage(),ToVulkan(layout, format), 1, ®ion); - } - - template - void AddPipelineBarrier(const VulkanRenderDevice* renderDevice, GTSL::Range barriers, const ALLOCATOR& allocator) const { - GTSL::Vector imageMemoryBarriers(4, allocator); GTSL::Vector memoryBarriers(4, allocator); GTSL::Vector bufferBarriers(4, allocator); - - for(auto& b : barriers) { - switch (b.Type) { - case BarrierType::MEMORY: { - auto& barrier = b.Memory; - VkMemoryBarrier2KHR& memoryBarrier = memoryBarriers.EmplaceBack(); - - memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR; memoryBarrier.pNext = nullptr; - memoryBarrier.srcAccessMask = ToVulkan(b.SourceAccess, b.SourceStage); - memoryBarrier.dstAccessMask = ToVulkan(b.DestinationAccess, b.DestinationStage); - memoryBarrier.srcStageMask = ToVulkan(b.SourceStage); - memoryBarrier.dstStageMask = ToVulkan(b.DestinationStage); - - break; - } - case BarrierType::BUFFER: { - auto& barrier = b.Buffer; - VkBufferMemoryBarrier2KHR& bufferBarrier = bufferBarriers.EmplaceBack(); - - bufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR; bufferBarrier.pNext = nullptr; - bufferBarrier.size = barrier.size; - bufferBarrier.buffer = static_cast(barrier.buffer)->GetVkBuffer(); - bufferBarrier.srcAccessMask = ToVulkan(b.SourceAccess, b.SourceStage); - bufferBarrier.dstAccessMask = ToVulkan(b.DestinationAccess, b.DestinationStage); - bufferBarrier.srcQueueFamilyIndex = b.From; - bufferBarrier.dstQueueFamilyIndex = b.To; - bufferBarrier.srcStageMask = ToVulkan(b.SourceStage); - bufferBarrier.dstStageMask = ToVulkan(b.DestinationStage); - break; - } - case BarrierType::TEXTURE: { - auto& barrier = b.Texture; - VkImageMemoryBarrier2KHR& textureBarrier = imageMemoryBarriers.EmplaceBack(); - - textureBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR; textureBarrier.pNext = nullptr; - textureBarrier.oldLayout = ToVulkan(barrier.CurrentLayout, barrier.Format); - textureBarrier.newLayout = ToVulkan(barrier.TargetLayout, barrier.Format); - textureBarrier.srcQueueFamilyIndex = b.From; - textureBarrier.dstQueueFamilyIndex = b.To; - textureBarrier.image = static_cast(barrier.texture)->GetVkImage(); - textureBarrier.subresourceRange.aspectMask = ToVulkan(barrier.Format.Type); - textureBarrier.subresourceRange.baseMipLevel = 0; - textureBarrier.subresourceRange.levelCount = 1; - textureBarrier.subresourceRange.baseArrayLayer = 0; - textureBarrier.subresourceRange.layerCount = 1; - textureBarrier.srcStageMask = ToVulkan(b.SourceStage); - textureBarrier.dstStageMask = ToVulkan(b.DestinationStage); - textureBarrier.srcAccessMask = ToVulkan(b.SourceAccess, b.SourceStage, barrier.Format); - textureBarrier.dstAccessMask = ToVulkan(b.DestinationAccess, b.DestinationStage, barrier.Format); - break; - } - } - } - - VkDependencyInfoKHR vk_dependency_info_khr{ VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR }; - vk_dependency_info_khr.bufferMemoryBarrierCount = bufferBarriers.GetLength(); - vk_dependency_info_khr.pBufferMemoryBarriers = bufferBarriers.GetData(); - vk_dependency_info_khr.imageMemoryBarrierCount = imageMemoryBarriers.GetLength(); - vk_dependency_info_khr.pImageMemoryBarriers = imageMemoryBarriers.GetData(); - vk_dependency_info_khr.memoryBarrierCount = memoryBarriers.GetLength(); - vk_dependency_info_khr.pMemoryBarriers = memoryBarriers.GetData(); - vk_dependency_info_khr.dependencyFlags = 0; - - renderDevice->VkCmdPipelineBarrier2(commandBuffer, &vk_dependency_info_khr); - } - - void CopyBuffer(const VulkanRenderDevice* renderDevice, VulkanBuffer source, VulkanBuffer destination, const GTSL::uint32 size) const { - VkBufferCopy vkBufferCopy; - vkBufferCopy.size = size; vkBufferCopy.srcOffset = 0; vkBufferCopy.dstOffset = 0; - renderDevice->VkCmdCopyBuffer(commandBuffer, source.GetVkBuffer(), destination.GetVkBuffer(), 1, &vkBufferCopy); - } - - void CopyBuffer(const VulkanRenderDevice* renderDevice, VulkanBuffer source, const GTSL::uint32 sOffset, VulkanBuffer destination, const GTSL::uint32 dOffset, const GTSL::uint32 size) const { - VkBufferCopy vkBufferCopy; - vkBufferCopy.size = size; vkBufferCopy.srcOffset = sOffset; vkBufferCopy.dstOffset = dOffset; - renderDevice->VkCmdCopyBuffer(commandBuffer, source.GetVkBuffer(), destination.GetVkBuffer(), 1, &vkBufferCopy); - } - - template - void BuildAccelerationStructure(const VulkanRenderDevice* renderDevice, GTSL::Range infos, const ALLOCATOR& allocator) const { - GTSL::Vector buildGeometryInfos(infos.ElementCount(), allocator); - GTSL::Vector, ALLOCATOR> geoPerAccStructure(infos.ElementCount(), allocator); - GTSL::Vector, ALLOCATOR> buildRangesPerAccelerationStructure(infos.ElementCount(), allocator); - GTSL::Vector buildRangesRangePerAccelerationStructure(infos.ElementCount(), allocator); - - for (GTSL::uint32 accStrInfoIndex = 0; accStrInfoIndex < infos.ElementCount(); ++accStrInfoIndex) { - auto& source = infos[accStrInfoIndex]; - - geoPerAccStructure.EmplaceBack(source.Geometries.ElementCount(), allocator); - buildRangesPerAccelerationStructure.EmplaceBack(source.Geometries.ElementCount(), allocator); - buildRangesRangePerAccelerationStructure.EmplaceBack(buildRangesPerAccelerationStructure[accStrInfoIndex].begin()); - - for (GTSL::uint32 i = 0; i < source.Geometries.ElementCount(); ++i) { - VkAccelerationStructureGeometryKHR accelerationStructureGeometry; VkAccelerationStructureBuildRangeInfoKHR buildRange; - buildGeometryAndRange(source.Geometries[i], accelerationStructureGeometry, buildRange); - geoPerAccStructure[accStrInfoIndex].EmplaceBack(accelerationStructureGeometry); - buildRangesPerAccelerationStructure[accStrInfoIndex].EmplaceBack(buildRange); - } - - VkAccelerationStructureBuildGeometryInfoKHR buildGeometryInfo{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; - buildGeometryInfo.flags = source.Flags; - buildGeometryInfo.srcAccelerationStructure = source.SourceAccelerationStructure.GetVkAccelerationStructure(); - buildGeometryInfo.dstAccelerationStructure = source.DestinationAccelerationStructure.GetVkAccelerationStructure(); - buildGeometryInfo.type = source.Geometries[0].Type == GeometryType::INSTANCES ? VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR : VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - buildGeometryInfo.pGeometries = geoPerAccStructure[accStrInfoIndex].begin(); - buildGeometryInfo.ppGeometries = nullptr; - buildGeometryInfo.geometryCount = geoPerAccStructure[accStrInfoIndex].GetLength(); - buildGeometryInfo.scratchData.deviceAddress = static_cast(source.ScratchBufferAddress); - buildGeometryInfo.mode = source.SourceAccelerationStructure.GetVkAccelerationStructure() ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - buildGeometryInfos.EmplaceBack(buildGeometryInfo); - } - - renderDevice->vkCmdBuildAccelerationStructuresKHR(commandBuffer, buildGeometryInfos.GetLength(), - buildGeometryInfos.begin(), buildRangesRangePerAccelerationStructure.begin()); - } - - void SetEvent(const VulkanRenderDevice* renderDevice, VulkanSynchronizer event, PipelineStage pipelineStage) { - renderDevice->VkCmdSetEvent(commandBuffer, event.GetVkEvent(), ToVulkan(pipelineStage)); - } - - void ResetEvent(const VulkanRenderDevice* renderDevice, VulkanSynchronizer event, PipelineStage pipelineStage) { - renderDevice->VkCmdResetEvent(commandBuffer, event.GetVkEvent(), ToVulkan(pipelineStage)); - } - - [[nodiscard]] VkCommandBuffer GetVkCommandBuffer() const { return commandBuffer; } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyCommandPool(renderDevice->GetVkDevice(), commandPool, renderDevice->GetVkAllocationCallbacks()); - debugClear(commandPool); - } - - [[nodiscard]] VkCommandPool GetVkCommandPool() const { return commandPool; } - - private: - VkCommandPool commandPool = nullptr; - VkCommandBuffer commandBuffer = nullptr; - bool isOptimized = false; - }; -} diff --git a/src/GAL/Vulkan/VulkanMemory.h b/src/GAL/Vulkan/VulkanMemory.h deleted file mode 100644 index fa738b13..00000000 --- a/src/GAL/Vulkan/VulkanMemory.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "GAL/Memory.h" - -#include "Vulkan.h" -#include "VulkanRenderDevice.h" - -namespace GAL -{ - class VulkanDeviceMemory final : public DeviceMemory - { - public: - VulkanDeviceMemory() = default; - - bool Initialize(const VulkanRenderDevice* renderDevice, AllocationFlag flags, GTSL::uint32 size, MemoryType memoryType) { - VkMemoryAllocateInfo vkMemoryAllocateInfo{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - - VkMemoryAllocateFlagsInfo vkMemoryAllocateFlagsInfo{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO }; - vkMemoryAllocateFlagsInfo.flags = ToVulkan(flags); - - vkMemoryAllocateInfo.pNext = &vkMemoryAllocateFlagsInfo; - vkMemoryAllocateInfo.allocationSize = size; - vkMemoryAllocateInfo.memoryTypeIndex = renderDevice->GetMemoryTypeIndex(memoryType); - - return renderDevice->VkAllocateMemory(renderDevice->GetVkDevice(), &vkMemoryAllocateInfo, renderDevice->GetVkAllocationCallbacks(), &deviceMemory) == VK_SUCCESS; - //setName(info.RenderDevice, deviceMemory, VK_OBJECT_TYPE_DEVICE_MEMORY, info.Name); - } - - ~VulkanDeviceMemory() = default; - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkFreeMemory(renderDevice->GetVkDevice(), deviceMemory, renderDevice->GetVkAllocationCallbacks()); - debugClear(deviceMemory); - } - - [[nodiscard]] VkDeviceMemory GetVkDeviceMemory() const { return deviceMemory; } - - [[nodiscard]] void* Map(const VulkanRenderDevice* renderDevice, const GTSL::uint32 size, const GTSL::uint32 offset) const { - void* data = nullptr; - renderDevice->VkMapMemory(renderDevice->GetVkDevice(), deviceMemory, offset, size, 0, &data); - return data; - } - - void Unmap(const VulkanRenderDevice* renderDevice) const { - renderDevice->VkUnmapMemory(renderDevice->GetVkDevice(), deviceMemory); - } - - private: - VkDeviceMemory deviceMemory = nullptr; - }; -} diff --git a/src/GAL/Vulkan/VulkanPipelines.h b/src/GAL/Vulkan/VulkanPipelines.h deleted file mode 100644 index 8a648756..00000000 --- a/src/GAL/Vulkan/VulkanPipelines.h +++ /dev/null @@ -1,578 +0,0 @@ -#pragma once - -#include "GAL/Pipelines.h" - -#define VK_ENABLE_BETA_EXTENSIONS -#include -#include - -#include "Vulkan.h" -#include "VulkanBindings.h" -#include "VulkanRenderPass.h" - -namespace GTSL { - class BufferInterface; -} - -namespace GAL -{ - //static bool glslLangInitialized = false; - - //bool GAL::VulkanShader::CompileShader(GTSL::Range code, GTSL::Range shaderName, ShaderType shaderType, ShaderLanguage shaderLanguage, GTSL::Buffer& result, GTSL::Buffer& stringError) - //{ - // EShLanguage shaderc_stage; - // - // switch (ShaderTypeToVkShaderStageFlagBits(shaderType)) - // { - // case VK_SHADER_STAGE_VERTEX_BIT: shaderc_stage = EShLangVertex; break; - // case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: shaderc_stage = EShLangTessControl; break; - // case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: shaderc_stage = EShLangTessEvaluation; break; - // case VK_SHADER_STAGE_GEOMETRY_BIT: shaderc_stage = EShLangGeometry; break; - // case VK_SHADER_STAGE_FRAGMENT_BIT: shaderc_stage = EShLangFragment; break; - // case VK_SHADER_STAGE_COMPUTE_BIT: shaderc_stage = EShLangCompute; break; - // case VK_SHADER_STAGE_RAYGEN_BIT_KHR: shaderc_stage = EShLangRayGen; break; - // case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: shaderc_stage = EShLangClosestHit; break; - // case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: shaderc_stage = EShLangAnyHit; break; - // case VK_SHADER_STAGE_MISS_BIT_KHR: shaderc_stage = EShLangMiss; break; - // case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: shaderc_stage = EShLangIntersect; break; - // case VK_SHADER_STAGE_CALLABLE_BIT_KHR: shaderc_stage = EShLangCallable; break; - // default: GAL_DEBUG_BREAK; - // } - // - // const TBuiltInResource DefaultTBuiltInResource{}; - // - // if(glslLangInitialized) - // { - // glslang::InitializeProcess(); - // glslLangInitialized = true; - // } - // - // glslang::TShader shader(shaderc_stage); - // GTSL::int32 length = code.ElementCount(); - // auto* string = code.begin(); - // shader.setStringsWithLengths(&string, &length, 1); - // - // int ClientInputSemanticsVersion = 460; // maps to, say, #define VULKAN 100 - // glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_2; - // glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5; - // - // shader.setEnvInput(glslang::EShSourceGlsl, shaderc_stage, glslang::EShClientVulkan, ClientInputSemanticsVersion); - // shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion); - // shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion); - // - // TBuiltInResource resources; - // resources = DefaultTBuiltInResource; - // EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); - // - // const GTSL::uint32 defaultVersion = 460; - // - // if (!shader.parse(&resources, defaultVersion, false, messages)) - // { - // const char* textBegin = "GLSL Parsing Failed for: "; - // stringError.WriteBytes(26, reinterpret_cast(textBegin)); - // stringError.WriteBytes(shaderName.ElementCount(), reinterpret_cast(shaderName.begin())); - // stringError.WriteBytes(GTSL::StringLength(shader.getInfoLog()), reinterpret_cast(shader.getInfoLog())); - // stringError.WriteBytes(GTSL::StringLength(shader.getInfoDebugLog()), reinterpret_cast(shader.getInfoDebugLog())); - // - // return false; - // } - // - // glslang::TProgram Program; - // Program.addShader(&shader); - // - // if (!Program.link(messages)) - // { - // const char* textBegin = "GLSL Linking Failed for: "; - // stringError.WriteBytes(26, reinterpret_cast(textBegin)); - // stringError.WriteBytes(shaderName.ElementCount(), reinterpret_cast(shaderName.begin())); - // stringError.WriteBytes(GTSL::StringLength(shader.getInfoLog()), reinterpret_cast(shader.getInfoLog())); - // stringError.WriteBytes(GTSL::StringLength(shader.getInfoDebugLog()), reinterpret_cast(shader.getInfoDebugLog())); - // - // return false; - // } - // - // std::vector spirv; - // spv::SpvBuildLogger logger; - // glslang::SpvOptions spvOptions; - // glslang::GlslangToSpv(*Program.getIntermediate(shaderc_stage), spirv, &logger, &spvOptions); - // - // result.WriteBytes(spirv.size() * sizeof(GTSL::uint32), reinterpret_cast(spirv.data())); - // - // return true; - //} - - class VulkanPipelineCache : public PipelineCache { - public: - VulkanPipelineCache() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, bool externallySync, GTSL::Range data) { - - VkPipelineCacheCreateInfo vkPipelineCacheCreateInfo{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; - GTSL::SetBitAs(0, externallySync, vkPipelineCacheCreateInfo.flags); - vkPipelineCacheCreateInfo.initialDataSize = data.Bytes(); - vkPipelineCacheCreateInfo.pInitialData = data.begin(); - - renderDevice->VkCreatePipelineCache(renderDevice->GetVkDevice(), &vkPipelineCacheCreateInfo, renderDevice->GetVkAllocationCallbacks(), &pipelineCache); - } - - void Initialize(const VulkanRenderDevice* renderDevice, GTSL::Range caches) { - - VkPipelineCacheCreateInfo vkPipelineCacheCreateInfo{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; - - renderDevice->VkCreatePipelineCache(renderDevice->GetVkDevice(), &vkPipelineCacheCreateInfo, renderDevice->GetVkAllocationCallbacks(), &pipelineCache); - - renderDevice->VkMergePipelineCaches(renderDevice->GetVkDevice(), pipelineCache, static_cast(caches.ElementCount()), reinterpret_cast(caches.begin())); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyPipelineCache(renderDevice->GetVkDevice(), pipelineCache, renderDevice->GetVkAllocationCallbacks()); - debugClear(pipelineCache); - } - - [[nodiscard]] VkPipelineCache GetVkPipelineCache() const { return pipelineCache; } - - void GetCacheSize(const VulkanRenderDevice* renderDevice, GTSL::uint32& size) const { - size_t data_size = 0; - renderDevice->VkGetPipelineCacheData(renderDevice->GetVkDevice(), pipelineCache, &data_size, nullptr); - size = static_cast(data_size); - } - - template - void GetCache(const VulkanRenderDevice* renderDevice, B& buffer) const { - GTSL::uint64 data_size; - renderDevice->VkGetPipelineCacheData(renderDevice->GetVkDevice(), pipelineCache, &data_size, buffer.begin()); - buffer.Resize(data_size); - } - - private: - VkPipelineCache pipelineCache = nullptr; - }; - - class VulkanShader final : public Shader { - public: - VulkanShader() = default; - void Initialize(const VulkanRenderDevice* renderDevice, GTSL::Range blob) { - VkShaderModuleCreateInfo shaderModuleCreateInfo{ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; - shaderModuleCreateInfo.codeSize = blob.Bytes(); - shaderModuleCreateInfo.pCode = reinterpret_cast(blob.begin()); - renderDevice->VkCreateShaderModule(renderDevice->GetVkDevice(), &shaderModuleCreateInfo, renderDevice->GetVkAllocationCallbacks(), &vkShaderModule); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyShaderModule(renderDevice->GetVkDevice(), vkShaderModule, renderDevice->GetVkAllocationCallbacks()); - debugClear(vkShaderModule); - } - - VkShaderModule GetVkShaderModule() const { return vkShaderModule; } - - private: - VkShaderModule vkShaderModule; - }; - - class VulkanPipelineLayout final { - public: - VulkanPipelineLayout() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, const PushConstant* pushConstant, const GTSL::Range bindingsSetLayouts) { - VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; - - GTSL::StaticVector vkDescriptorSetLayouts; - for (auto& e : bindingsSetLayouts) { vkDescriptorSetLayouts.EmplaceBack(e.GetVkDescriptorSetLayout()); } - - VkPushConstantRange vkPushConstantRange; - if (pushConstant) { - vkPushConstantRange.size = pushConstant->NumberOf4ByteSlots * 4; - vkPushConstantRange.offset = 0; - vkPushConstantRange.stageFlags = ToVulkan(pushConstant->Stage); - - vkPipelineLayoutCreateInfo.pushConstantRangeCount = 1; - vkPipelineLayoutCreateInfo.pPushConstantRanges = &vkPushConstantRange; - } else { - vkPipelineLayoutCreateInfo.pushConstantRangeCount = 0; - vkPipelineLayoutCreateInfo.pPushConstantRanges = nullptr; - } - - vkPipelineLayoutCreateInfo.setLayoutCount = vkDescriptorSetLayouts.GetLength(); - vkPipelineLayoutCreateInfo.pSetLayouts = vkDescriptorSetLayouts.begin(); - - renderDevice->VkCreatePipelineLayout(renderDevice->GetVkDevice(), &vkPipelineLayoutCreateInfo, renderDevice->GetVkAllocationCallbacks(), &pipelineLayout); - //setName(createInfo.RenderDevice, pipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, createInfo.Name); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyPipelineLayout(renderDevice->GetVkDevice(), pipelineLayout, renderDevice->GetVkAllocationCallbacks()); - debugClear(pipelineLayout); - } - - [[nodiscard]] VkPipelineLayout GetVkPipelineLayout() const { return pipelineLayout; } - private: - VkPipelineLayout pipelineLayout = nullptr; - }; - - class VulkanPipeline : public Pipeline { - public: - struct ShaderInfo - { - VulkanShader Shader; ShaderType Type; - GTSL::Range Blob; - }; - - void InitializeRasterPipeline(const VulkanRenderDevice* renderDevice, const GTSL::Range pipelineStates, GTSL::Range stages, const VulkanPipelineLayout pipelineLayout, const VulkanPipelineCache pipelineCache) { - VkPipelineMultisampleStateCreateInfo vkPipelineMultisampleStateCreateInfo; - vkPipelineMultisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - vkPipelineMultisampleStateCreateInfo.pNext = 0; - vkPipelineMultisampleStateCreateInfo.alphaToCoverageEnable = false; - vkPipelineMultisampleStateCreateInfo.alphaToOneEnable = false; - vkPipelineMultisampleStateCreateInfo.flags = 0; - vkPipelineMultisampleStateCreateInfo.minSampleShading = 0; - vkPipelineMultisampleStateCreateInfo.pSampleMask = nullptr; - vkPipelineMultisampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - vkPipelineMultisampleStateCreateInfo.sampleShadingEnable = false; - - VkGraphicsPipelineCreateInfo vkGraphicsPipelineCreateInfo{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; - vkGraphicsPipelineCreateInfo.pTessellationState = nullptr; vkGraphicsPipelineCreateInfo.pColorBlendState = nullptr; - vkGraphicsPipelineCreateInfo.pVertexInputState = nullptr; vkGraphicsPipelineCreateInfo.pInputAssemblyState = nullptr; - vkGraphicsPipelineCreateInfo.pViewportState = nullptr; vkGraphicsPipelineCreateInfo.pRasterizationState = nullptr; - vkGraphicsPipelineCreateInfo.pDepthStencilState = nullptr; vkGraphicsPipelineCreateInfo.pMultisampleState = &vkPipelineMultisampleStateCreateInfo; - vkGraphicsPipelineCreateInfo.layout = pipelineLayout.GetVkPipelineLayout(); - - GTSL::StaticVector specializationMapEntries; const byte* specializationData = nullptr; uint64 specializationDataSize = 0; - - GTSL::Buffer> buffer(8192, 8); - - for (GTSL::uint8 ps = 0; ps < static_cast(pipelineStates.ElementCount()); ++ps) { - switch (const auto& pipelineState = pipelineStates[ps]; pipelineState.Type) { - case PipelineStateBlock::StateType::VIEWPORT_STATE: { - auto* vkViewport = buffer.AllocateStructure(); - vkViewport->x = 0; - vkViewport->y = 0; - vkViewport->width = 1.0f; - vkViewport->height = 1.0f; - vkViewport->minDepth = 0.0f; - vkViewport->maxDepth = 1.0f; - - auto* vkScissor = buffer.AllocateStructure(); - *vkScissor = { { 0, 0 }, { 1, 1 } }; - - auto* pointer = buffer.AllocateStructure(); - - VkPipelineViewportStateCreateInfo& vkPipelineViewportStateCreateInfo = *pointer; - vkPipelineViewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vkPipelineViewportStateCreateInfo.pNext = nullptr; - vkPipelineViewportStateCreateInfo.viewportCount = pipelineState.Viewport.ViewportCount; - vkPipelineViewportStateCreateInfo.pViewports = vkViewport; - vkPipelineViewportStateCreateInfo.scissorCount = 1; - vkPipelineViewportStateCreateInfo.pScissors = vkScissor; - - vkGraphicsPipelineCreateInfo.pViewportState = pointer; - - break; - } - case PipelineStateBlock::StateType::RASTER_STATE: { - auto* pointer = buffer.AllocateStructure(); - - VkPipelineRasterizationStateCreateInfo& vkPipelineRasterizationStateCreateInfo = *pointer; - vkPipelineRasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - vkPipelineRasterizationStateCreateInfo.pNext = nullptr; - vkPipelineRasterizationStateCreateInfo.depthClampEnable = VK_FALSE; - vkPipelineRasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE; - vkPipelineRasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL; - vkPipelineRasterizationStateCreateInfo.lineWidth = 1.0f; - vkPipelineRasterizationStateCreateInfo.frontFace = ToVulkan(pipelineState.Raster.windingOrder); - vkPipelineRasterizationStateCreateInfo.cullMode = ToVulkan(pipelineState.Raster.cullMode); - vkPipelineRasterizationStateCreateInfo.depthBiasEnable = VK_FALSE; - vkPipelineRasterizationStateCreateInfo.depthBiasConstantFactor = 0.0f; // Optional - vkPipelineRasterizationStateCreateInfo.depthBiasClamp = 0.0f; // Optional - vkPipelineRasterizationStateCreateInfo.depthBiasSlopeFactor = 0.0f; // Optional - - vkGraphicsPipelineCreateInfo.pRasterizationState = pointer; - - break; - } - case PipelineStateBlock::StateType::DEPTH_STATE: - { - auto* pointer = buffer.AllocateStructure(); - - auto& vkPipelineDepthStencilStateCreateInfo = *pointer; - vkPipelineDepthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - vkPipelineDepthStencilStateCreateInfo.pNext = nullptr; - vkPipelineDepthStencilStateCreateInfo.depthTestEnable = true; - vkPipelineDepthStencilStateCreateInfo.depthWriteEnable = true; - vkPipelineDepthStencilStateCreateInfo.depthCompareOp = ToVulkan(pipelineState.Depth.compareOperation); - vkPipelineDepthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE; - vkPipelineDepthStencilStateCreateInfo.minDepthBounds = 0.0f; // Optional - vkPipelineDepthStencilStateCreateInfo.maxDepthBounds = 1.0f; // Optional - vkPipelineDepthStencilStateCreateInfo.stencilTestEnable = false; - - vkGraphicsPipelineCreateInfo.pDepthStencilState = pointer; - - break; - } - case PipelineStateBlock::StateType::COLOR_BLEND_STATE: { - auto* pointer = buffer.AllocateStructure(); - - auto& vkPipelineColorblendStateCreateInfo = *pointer; - vkPipelineColorblendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - vkPipelineColorblendStateCreateInfo.pNext = nullptr; - vkPipelineColorblendStateCreateInfo.logicOpEnable = VK_FALSE; - vkPipelineColorblendStateCreateInfo.logicOp = VK_LOGIC_OP_COPY; // Optional - vkPipelineColorblendStateCreateInfo.pAttachments = reinterpret_cast(buffer.GetData() + buffer.GetLength()); - - VkFormat depthFormat = VK_FORMAT_UNDEFINED; - - GTSL::uint8 colorAttachmentCount = 0, depthAttachmentIndex = 0xFF; - for (GTSL::uint8 i = 0; i < static_cast(pipelineState.Context.Attachments.ElementCount()); ++i) { - if (pipelineState.Context.Attachments[i].Format.Type == TextureType::COLOR) { - auto* state = buffer.AllocateStructure(); - state->blendEnable = pipelineState.Context.Attachments[i].BlendEnable; - state->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - state->srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; state->dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - state->colorBlendOp = VK_BLEND_OP_ADD; state->alphaBlendOp = VK_BLEND_OP_SUBTRACT; - state->srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; state->dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - ++colorAttachmentCount; - } else { - depthAttachmentIndex = i; - depthFormat = ToVulkan(MakeFormatFromFormatDescriptor(pipelineState.Context.Attachments[depthAttachmentIndex].Format)); - } - } - - vkPipelineColorblendStateCreateInfo.attachmentCount = colorAttachmentCount; - vkPipelineColorblendStateCreateInfo.blendConstants[0] = 0.0f; // Optional - vkPipelineColorblendStateCreateInfo.blendConstants[1] = 0.0f; // Optional - vkPipelineColorblendStateCreateInfo.blendConstants[2] = 0.0f; // Optional - vkPipelineColorblendStateCreateInfo.blendConstants[3] = 0.0f; // Optional - - vkGraphicsPipelineCreateInfo.pColorBlendState = pointer; - - auto* pipeline_rendering_create_info = buffer.AllocateStructure(VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); - pipeline_rendering_create_info->pColorAttachmentFormats = reinterpret_cast(buffer.GetData() + buffer.GetLength()); - for(auto i = 0; i < colorAttachmentCount; ++i) { buffer.AllocateStructure(ToVulkan(MakeFormatFromFormatDescriptor(pipelineState.Context.Attachments[i].Format))); } - pipeline_rendering_create_info->colorAttachmentCount = colorAttachmentCount; - pipeline_rendering_create_info->depthAttachmentFormat = depthFormat; - pipeline_rendering_create_info->stencilAttachmentFormat = VK_FORMAT_UNDEFINED; - pipeline_rendering_create_info->viewMask = 0; - - vkGraphicsPipelineCreateInfo.pNext = pipeline_rendering_create_info; - - vkGraphicsPipelineCreateInfo.renderPass = nullptr; - vkGraphicsPipelineCreateInfo.subpass = 0; - - break; - } - case PipelineStateBlock::StateType::VERTEX_STATE: { - auto* vk_pipeline_vertex_input_state_create_info = buffer.AllocateStructure(); - - vk_pipeline_vertex_input_state_create_info->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vk_pipeline_vertex_input_state_create_info->pNext = nullptr; - vk_pipeline_vertex_input_state_create_info->vertexBindingDescriptionCount = 0; - vk_pipeline_vertex_input_state_create_info->pVertexBindingDescriptions = reinterpret_cast(buffer.GetData() + buffer.GetLength()); - - auto* bindings = reinterpret_cast(buffer.GetData() + buffer.GetLength()); - - for (uint32_t i = 0; i < pipelineState.Vertex.VertexStreams.ElementCount(); ++i) { - auto* binding = buffer.AllocateStructure(); - binding->binding = i; binding->inputRate = VK_VERTEX_INPUT_RATE_VERTEX; binding->stride = 0; - ++vk_pipeline_vertex_input_state_create_info->vertexBindingDescriptionCount; - } - - vk_pipeline_vertex_input_state_create_info->vertexAttributeDescriptionCount = 0; - vk_pipeline_vertex_input_state_create_info->pVertexAttributeDescriptions = reinterpret_cast(buffer.GetData() + buffer.GetLength()); - - for (uint32_t i = 0; i < pipelineState.Vertex.VertexStreams.ElementCount(); ++i) { - for (GTSL::uint32 j = 0; j < static_cast(pipelineState.Vertex.VertexStreams[i].ElementCount()); ++j) { - auto size = ShaderDataTypesSize(pipelineState.Vertex.VertexStreams[i][j].Type); - - auto& vertex = *buffer.AllocateStructure(); - vertex.location = pipelineState.Vertex.VertexStreams[i][j].Location; - vertex.binding = i; - vertex.format = ToVulkan(pipelineState.Vertex.VertexStreams[i][j].Type); - vertex.offset = bindings[i].stride; - bindings[i].stride += size; - ++vk_pipeline_vertex_input_state_create_info->vertexAttributeDescriptionCount; - } - } - - vkGraphicsPipelineCreateInfo.pVertexInputState = vk_pipeline_vertex_input_state_create_info; - - auto* inputAssemblyState = buffer.AllocateStructure(); - inputAssemblyState->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssemblyState->pNext = nullptr; - inputAssemblyState->flags = 0; inputAssemblyState->primitiveRestartEnable = false; inputAssemblyState->topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - vkGraphicsPipelineCreateInfo.pInputAssemblyState = inputAssemblyState; - - break; - } - case PipelineStateBlock::StateType::SPECIALIZATION: { - specializationData = pipelineState.Specialization.Data.begin(); - specializationDataSize = pipelineState.Specialization.Data.Bytes(); - - for(auto& e : pipelineState.Specialization.Entries) { - auto& s = specializationMapEntries.EmplaceBack(); - s.size = e.Size; s.offset = e.Offset; - s.constantID = e.ID; - } - - break; - } - default:; - } - } - - VkPipelineDynamicStateCreateInfo vkPipelineDynamicStateCreateInfo{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; - GTSL::StaticVector vkDynamicStates = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - vkPipelineDynamicStateCreateInfo.dynamicStateCount = vkDynamicStates.GetLength(); - vkPipelineDynamicStateCreateInfo.pDynamicStates = vkDynamicStates.begin(); - - GTSL::StaticVector vkPipelineShaderStageCreateInfos; - - for (GTSL::uint8 i = 0; i < static_cast(stages.ElementCount()); ++i) { - auto& stage = vkPipelineShaderStageCreateInfos.EmplaceBack(); - - stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stage.pNext = nullptr; - stage.flags = 0; - stage.stage = ToVulkan(stages[i].Type); - stage.pName = "main"; - stage.module = stages[i].Shader.GetVkShaderModule(); - auto* specializationInfo = buffer.AllocateStructure(); - stage.pSpecializationInfo = specializationInfo; - - specializationInfo->dataSize = specializationDataSize; - specializationInfo->mapEntryCount = specializationMapEntries.GetLength(); - specializationInfo->pData = specializationData; - specializationInfo->pMapEntries = specializationMapEntries.GetData(); - } - - vkGraphicsPipelineCreateInfo.stageCount = vkPipelineShaderStageCreateInfos.GetLength(); - vkGraphicsPipelineCreateInfo.pStages = vkPipelineShaderStageCreateInfos.begin(); - vkGraphicsPipelineCreateInfo.pDynamicState = &vkPipelineDynamicStateCreateInfo; - vkGraphicsPipelineCreateInfo.basePipelineIndex = -1; - vkGraphicsPipelineCreateInfo.basePipelineHandle = nullptr; - - renderDevice->VkCreateGraphicsPipelines(renderDevice->GetVkDevice(), pipelineCache.GetVkPipelineCache(), 1, &vkGraphicsPipelineCreateInfo, renderDevice->GetVkAllocationCallbacks(), &pipeline); - //SET_NAME(pipeline, VK_OBJECT_TYPE_PIPELINE, createInfo); - } - - void InitializeComputePipeline(const VulkanRenderDevice* renderDevice, const GTSL::Range pipeline_states, GTSL::Range stages, const VulkanPipelineLayout pipelineLayout, const VulkanPipelineCache pipelineCache) { - GTSL::StaticVector specializationMapEntries; const byte* specializationData = nullptr; uint64 specializationDataSize = 0; - - GTSL::StaticBuffer<8192> buffer; - - VkComputePipelineCreateInfo computePipelineCreateInfo{ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; - computePipelineCreateInfo.basePipelineIndex = -1; - computePipelineCreateInfo.layout = pipelineLayout.GetVkPipelineLayout(); - computePipelineCreateInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - computePipelineCreateInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; - computePipelineCreateInfo.stage.pName = "main"; - computePipelineCreateInfo.stage.module = stages[0].Shader.GetVkShaderModule(); - - auto* specializationInfo = buffer.AllocateStructure(); - - computePipelineCreateInfo.stage.pSpecializationInfo = specializationInfo; - - for (GTSL::uint8 ps = 0; ps < static_cast(pipeline_states.ElementCount()); ++ps) { - switch (const auto& pipelineState = pipeline_states[ps]; pipelineState.Type) { - case PipelineStateBlock::StateType::SPECIALIZATION: { - specializationData = pipelineState.Specialization.Data.begin(); - specializationDataSize = pipelineState.Specialization.Data.Bytes(); - - for(auto& e : pipelineState.Specialization.Entries) { - auto& s = specializationMapEntries.EmplaceBack(); - s.size = e.Size; s.offset = e.Offset; - s.constantID = e.ID; - } - - break; - } - } - } - - specializationInfo->dataSize = specializationDataSize; - specializationInfo->mapEntryCount = specializationMapEntries.GetLength(); - specializationInfo->pData = specializationData; - specializationInfo->pMapEntries = specializationMapEntries.GetData(); - - renderDevice->VkCreateComputePipelines(renderDevice->GetVkDevice(), pipelineCache.GetVkPipelineCache(), 1, &computePipelineCreateInfo, renderDevice->GetVkAllocationCallbacks(), &pipeline); - } - - void InitializeRayTracePipeline(const VulkanRenderDevice* renderDevice, const VulkanPipeline parentPipeline, const GTSL::Range pipelineStates, GTSL::Range stages, const VulkanPipelineLayout pipelineLayout, const VulkanPipelineCache pipelineCache) { - GTSL::StaticVector vkRayTracingShaderGroupCreateInfoKhrs; - - VkRayTracingPipelineCreateInfoKHR vkRayTracingPipelineCreateInfo{ VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR }; - vkRayTracingPipelineCreateInfo.basePipelineIndex = -1; - vkRayTracingPipelineCreateInfo.maxPipelineRayRecursionDepth = 0; - - for (GTSL::uint32 i = 0; i < static_cast(pipelineStates.ElementCount()); ++i) - { - auto& pipelineState = pipelineStates[i]; - - switch (pipelineState.Type) { - case PipelineStateBlock::StateType::RAY_TRACE_GROUPS: { - for (const auto& e : pipelineState.RayTracing.Groups) { - auto& p = vkRayTracingShaderGroupCreateInfoKhrs.EmplaceBack(); - p.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - p.pNext = nullptr; - - p.anyHitShader = e.AnyHitShader == RayTraceGroup::SHADER_UNUSED ? VK_SHADER_UNUSED_KHR : e.AnyHitShader; - p.closestHitShader = e.ClosestHitShader == RayTraceGroup::SHADER_UNUSED ? VK_SHADER_UNUSED_KHR : e.ClosestHitShader; - p.generalShader = e.GeneralShader == RayTraceGroup::SHADER_UNUSED ? VK_SHADER_UNUSED_KHR : e.GeneralShader; - p.intersectionShader = e.IntersectionShader == RayTraceGroup::SHADER_UNUSED ? VK_SHADER_UNUSED_KHR : e.IntersectionShader; - - p.type = ToVulkan(e.ShaderGroup); - - p.pShaderGroupCaptureReplayHandle = nullptr; - } - - vkRayTracingPipelineCreateInfo.maxPipelineRayRecursionDepth = pipelineState.RayTracing.MaxRecursionDepth; - - break; - } - default: break; - } - } - - GTSL::StaticVector vkPipelineShaderStageCreateInfos; - - for (GTSL::uint32 i = 0; i < static_cast(stages.ElementCount()); ++i) { - auto& stageCreateInfo = vkPipelineShaderStageCreateInfos.EmplaceBack(); - stageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stageCreateInfo.pNext = nullptr; - stageCreateInfo.flags = 0; - stageCreateInfo.stage = ToVulkan(stages[i].Type); - stageCreateInfo.pName = "main"; - stageCreateInfo.pSpecializationInfo = nullptr; - stageCreateInfo.module = stages[i].Shader.GetVkShaderModule(); - } - - vkRayTracingPipelineCreateInfo.stageCount = vkPipelineShaderStageCreateInfos.GetLength(); - vkRayTracingPipelineCreateInfo.pStages = vkPipelineShaderStageCreateInfos.begin(); - - vkRayTracingPipelineCreateInfo.layout = pipelineLayout.GetVkPipelineLayout(); - - vkRayTracingPipelineCreateInfo.groupCount = vkRayTracingShaderGroupCreateInfoKhrs.GetLength(); - vkRayTracingPipelineCreateInfo.pGroups = vkRayTracingShaderGroupCreateInfoKhrs.begin(); - - if (const auto h = parentPipeline.GetVkPipeline()) { - vkRayTracingPipelineCreateInfo.basePipelineIndex = 0; - vkRayTracingPipelineCreateInfo.basePipelineHandle = h; - } - - renderDevice->vkCreateRayTracingPipelinesKHR(renderDevice->GetVkDevice(), nullptr, pipelineCache.GetVkPipelineCache(), 1, &vkRayTracingPipelineCreateInfo, renderDevice->GetVkAllocationCallbacks(), &pipeline); - //SET_NAME(pipeline, VK_OBJECT_TYPE_PIPELINE, createInfo) - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyPipeline(renderDevice->GetVkDevice(), pipeline, renderDevice->GetVkAllocationCallbacks()); - debugClear(pipeline); - } - - [[nodiscard]] VkPipeline GetVkPipeline() const { return pipeline; } - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(pipeline); } - - template - void GetShaderGroupHandles(VulkanRenderDevice* renderDevice, GTSL::uint32 firstGroup, GTSL::uint32 groupCount, GTSL::Vector& vector) { - vector.SetLength(groupCount); - renderDevice->vkGetRayTracingShaderGroupHandlesKHR(renderDevice->GetVkDevice(), pipeline, firstGroup, groupCount, groupCount * 32u, vector.begin()); - } - protected: - VkPipeline pipeline = nullptr; - }; -} diff --git a/src/GAL/Vulkan/VulkanQueryPool.h b/src/GAL/Vulkan/VulkanQueryPool.h deleted file mode 100644 index 892ed2f0..00000000 --- a/src/GAL/Vulkan/VulkanQueryPool.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "Vulkan.h" -#include "VulkanRenderDevice.h" - -namespace GAL -{ - class VulkanQueryPool - { - public: - VulkanQueryPool() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, QueryType queryType, GTSL::uint32 queryCount) { - VkQueryPoolCreateInfo vk_query_pool_create_info{ VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO }; - vk_query_pool_create_info.queryCount = queryCount; - vk_query_pool_create_info.queryType = ToVulkan(queryType); - - renderDevice->VkCreateQueryPool(renderDevice->GetVkDevice(), &vk_query_pool_create_info, renderDevice->GetVkAllocationCallbacks(), &queryPool); - //setName(createInfo.RenderDevice, queryPool, VK_OBJECT_TYPE_QUERY_POOL, createInfo.Name); - } - - void GetQueryResults(const VulkanRenderDevice* renderDevice, void* data, GTSL::uint32 size, GTSL::uint32 queryCount, GTSL::uint32 stride, bool wait) const { - VkQueryResultFlags flags = 0; - GTSL::SetBitAs(1, wait, flags); - - renderDevice->VkGetQueryPoolResults(renderDevice->GetVkDevice(), queryPool, 0, queryCount, size, data, stride, flags); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyQueryPool(renderDevice->GetVkDevice(), queryPool, renderDevice->GetVkAllocationCallbacks()); - debugClear(queryPool); - } - - [[nodiscard]] VkQueryPool GetVkQueryPool() const { return queryPool; } - private: - VkQueryPool queryPool; - }; -} diff --git a/src/GAL/Vulkan/VulkanQueue.h b/src/GAL/Vulkan/VulkanQueue.h deleted file mode 100644 index c0307569..00000000 --- a/src/GAL/Vulkan/VulkanQueue.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include "VulkanCommandList.h" -#include "GTSL/Core.h" - -#include "VulkanRenderDevice.h" -#include "VulkanSynchronization.h" -#include "GAL/Queue.h" - -namespace GAL { - class VulkanQueue final : public Queue - { - public: - VulkanQueue() = default; - ~VulkanQueue() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, const VulkanRenderDevice::QueueKey queue_key) { - queueKey = queue_key; - renderDevice->getDeviceProcAddr(u8"vkGetDeviceQueue")(renderDevice->GetVkDevice(), queueKey.Family, queueKey.Queue, &queue); - } - - void Wait(const VulkanRenderDevice* renderDevice) const { - renderDevice->VkQueueWaitIdle(queue); - } - - bool Submit(const VulkanRenderDevice* renderDevice, const GTSL::Range*> submitInfos, VulkanSynchronizer& fence) { - VkResult submitResult; - - { - GTSL::StaticVector vkSubmitInfos; - - GTSL::StaticVector, 4> vkCommandBuffers; - GTSL::StaticVector, 4> signalSemaphores, waitSemaphores; - GTSL::StaticVector, 4> vkPipelineStageFlags; - - for (auto& si : submitInfos) { - auto& a = vkSubmitInfos.EmplaceBack(VK_STRUCTURE_TYPE_SUBMIT_INFO); - auto& wucb = vkCommandBuffers.EmplaceBack(); - auto& wuss = signalSemaphores.EmplaceBack(); auto& wuws = waitSemaphores.EmplaceBack(); - auto& psfs = vkPipelineStageFlags.EmplaceBack(); - - for (auto cbi : si.CommandLists) { - wucb.EmplaceBack(static_cast(cbi)->GetVkCommandBuffer()); - } - - for (auto& cbi : si.Signal) { - wuss.EmplaceBack(cbi.Synchronizer->GetVkSemaphore()); - cbi.Synchronizer->Signal(); - } - - for (auto& cbi : si.Wait) { - wuws.EmplaceBack(cbi.Synchronizer->GetVkSemaphore()); - psfs.EmplaceBack(ToVulkan(cbi.stage)); - cbi.Synchronizer->Release(); - } - - a.commandBufferCount = wucb.GetLength(); - a.pCommandBuffers = wucb.begin(); - a.waitSemaphoreCount = wuws.GetLength(); - a.pWaitSemaphores = wuws.begin(); - a.signalSemaphoreCount = wuss.GetLength(); - a.pSignalSemaphores = wuss.begin(); - a.pWaitDstStageMask = psfs.GetData(); - } - - submitResult = renderDevice->VkQueueSubmit(queue, vkSubmitInfos.GetLength(), vkSubmitInfos.GetData(), fence.GetVkFence()); - } - - fence.Signal(); - - if(submitResult == VK_ERROR_DEVICE_LOST) { - renderDevice->Log(u8"Error: Device lost", RenderDevice::MessageSeverity::ERROR); - } - - return submitResult == VK_SUCCESS; - } - - [[nodiscard]] VkQueue GetVkQueue() const { return queue; } - [[nodiscard]] VulkanRenderDevice::QueueKey GetQueueKey() const { return queueKey; } - - private: - VkQueue queue = nullptr; - VulkanRenderDevice::QueueKey queueKey; - }; -} diff --git a/src/GAL/Vulkan/VulkanRenderContext.h b/src/GAL/Vulkan/VulkanRenderContext.h deleted file mode 100644 index ce832c70..00000000 --- a/src/GAL/Vulkan/VulkanRenderContext.h +++ /dev/null @@ -1,234 +0,0 @@ -#pragma once - -#include "GAL/RenderContext.h" - -#include "VulkanTexture.h" -#include "VulkanQueue.h" -#include "VulkanSynchronization.h" - -#include -#include -#include - -namespace GAL -{ - class VulkanQueue; - - class VulkanSurface final : public Surface { - public: - VulkanSurface() = default; - - bool Initialize(const VulkanRenderDevice* renderDevice, const GTSL::Application& application, const GTSL::Window& window) { -#if BE_PLATFORM_WINDOWS - VkWin32SurfaceCreateInfoKHR vkWin32SurfaceCreateInfoKhr{ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR }; - vkWin32SurfaceCreateInfoKhr.hwnd = window.GetHWND(); - vkWin32SurfaceCreateInfoKhr.hinstance = application.GetHINSTANCE(); - return renderDevice->VkCreateWin32Surface(renderDevice->GetVkInstance(), &vkWin32SurfaceCreateInfoKhr, renderDevice->GetVkAllocationCallbacks(), &surface) == VK_SUCCESS; - //setName(renderDevice, surface, VK_OBJECT_TYPE_SURFACE_KHR, createInfo.Name); -#elif BE_PLATFORM_LINUX - if(true) { // Use X11 { - // Create Vulkan xcb surface - VkXcbSurfaceCreateInfoKHR vkXcbSurfaceCreateInfoKhr{ VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR }; - vkXcbSurfaceCreateInfoKhr.connection = window.GetXCBConnection(); - vkXcbSurfaceCreateInfoKhr.window = window.GetXCBWindow(); - return renderDevice->VkCreateXcbSurface(renderDevice->GetVkInstance(), &vkXcbSurfaceCreateInfoKhr, renderDevice->GetVkAllocationCallbacks(), &surface) == VK_SUCCESS; - } else { - // Create Vulkan Wayland surface - VkWaylandSurfaceCreateInfoKHR vkWaylandSurfaceCreateInfoKhr{ VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR }; - //vkWaylandSurfaceCreateInfoKhr.display = window.GetDisplay(); - //vkWaylandSurfaceCreateInfoKhr.surface = window.GetWindow(); - return renderDevice->VkCreateWaylandSurface(renderDevice->GetVkInstance(), &vkWaylandSurfaceCreateInfoKhr, renderDevice->GetVkAllocationCallbacks(), &surface) == VK_SUCCESS; - } -#endif - } - - void Destroy(class VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroySurface(renderDevice->GetVkInstance(), surface, renderDevice->GetVkAllocationCallbacks()); - debugClear(surface); - } - - GTSL::StaticVector, 16> GetSupportedFormatsAndColorSpaces(const VulkanRenderDevice* renderDevice) const { - GTSL::uint32 surfaceFormatsCount = 16; - VkSurfaceFormatKHR vkSurfaceFormatKhrs[16]; - renderDevice->VkGetPhysicalDeviceSurfaceFormats(renderDevice->GetVkPhysicalDevice(), surface, &surfaceFormatsCount, vkSurfaceFormatKhrs); - - GTSL::StaticVector, 16> result; - - for (GTSL::uint8 i = 0; i < static_cast(surfaceFormatsCount); ++i) { - if(GAL::IsSupported(vkSurfaceFormatKhrs[i].format)) - result.EmplaceBack(GTSL::Pair(ToGAL(vkSurfaceFormatKhrs[i].colorSpace), ToGAL(vkSurfaceFormatKhrs[i].format))); - } - - return result; - } - - GTSL::StaticVector GetSupportedPresentModes(const VulkanRenderDevice* renderDevice) const { - GTSL::uint32 presentModesCount = 8; - VkPresentModeKHR vkPresentModes[8]; - renderDevice->VkGetPhysicalDeviceSurfacePresentModes(renderDevice->GetVkPhysicalDevice(), surface, &presentModesCount, vkPresentModes); - - GTSL::StaticVector result; - - for (GTSL::uint8 i = 0; i < static_cast(presentModesCount); ++i) { - result.EmplaceBack(ToGAL(vkPresentModes[i])); - } - - return result; - } - - struct SurfaceCapabilities - { - uint32_t MinImageCount, MaxImageCount; - GTSL::Extent2D CurrentExtent, MinImageExtent, MaxImageExtent; - VkImageUsageFlags SupportedUsageFlags; - }; - bool IsSupported(class VulkanRenderDevice* renderDevice, SurfaceCapabilities* surfaceCapabilities) { - VkBool32 supported = 0; - renderDevice->VkGetPhysicalDeviceSurfaceSupport(renderDevice->GetVkPhysicalDevice(), 0, surface, &supported); - - VkSurfaceCapabilitiesKHR vkSurfaceCapabilitiesKhr; - renderDevice->VkGetPhysicalDeviceSurfaceCapabilities(renderDevice->GetVkPhysicalDevice(), surface, &vkSurfaceCapabilitiesKhr); - - auto vkExtentToExtent = [](const VkExtent2D vkExtent) { return GTSL::Extent2D(vkExtent.width, vkExtent.height); }; - - surfaceCapabilities->CurrentExtent = vkExtentToExtent(vkSurfaceCapabilitiesKhr.currentExtent); - surfaceCapabilities->MinImageExtent = vkExtentToExtent(vkSurfaceCapabilitiesKhr.minImageExtent); - surfaceCapabilities->MaxImageExtent = vkExtentToExtent(vkSurfaceCapabilitiesKhr.maxImageExtent); - surfaceCapabilities->MinImageCount = vkSurfaceCapabilitiesKhr.minImageCount; - surfaceCapabilities->MaxImageCount = vkSurfaceCapabilitiesKhr.maxImageCount; - surfaceCapabilities->SupportedUsageFlags = vkSurfaceCapabilitiesKhr.supportedUsageFlags; - - return supported; - } - - [[nodiscard]] VkSurfaceKHR GetVkSurface() const { return surface; } - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(surface); } - - private: - VkSurfaceKHR surface = nullptr; - }; - - class VulkanRenderContext final : public RenderContext { - public: - VulkanRenderContext() = default; - - ~VulkanRenderContext() = default; - - bool InitializeOrRecreate(const VulkanRenderDevice* renderDevice, [[maybe_unused]] const VulkanQueue queue, const VulkanSurface* surface, GTSL::Extent2D extent, FormatDescriptor format, ColorSpaces colorSpace, TextureUse textureUse, PresentModes presentMode, GTSL::uint8 desiredFramesInFlight) { - VkSwapchainCreateInfoKHR vkSwapchainCreateInfoKhr{ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; - vkSwapchainCreateInfoKhr.surface = static_cast(surface->GetVkSurface()); - vkSwapchainCreateInfoKhr.minImageCount = desiredFramesInFlight; - vkSwapchainCreateInfoKhr.imageFormat = ToVulkan(MakeFormatFromFormatDescriptor(format)); - vkSwapchainCreateInfoKhr.imageColorSpace = ToVulkan(colorSpace); - vkSwapchainCreateInfoKhr.imageExtent = ToVulkan(extent); - //The imageArrayLayers specifies the amount of layers each image consists of. This is always 1 unless you are developing a stereoscopic 3D application. - vkSwapchainCreateInfoKhr.imageArrayLayers = 1; - vkSwapchainCreateInfoKhr.imageUsage = ToVulkan(textureUse, format); - vkSwapchainCreateInfoKhr.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - vkSwapchainCreateInfoKhr.queueFamilyIndexCount = 0; - vkSwapchainCreateInfoKhr.pQueueFamilyIndices = nullptr; - vkSwapchainCreateInfoKhr.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - vkSwapchainCreateInfoKhr.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - vkSwapchainCreateInfoKhr.presentMode = ToVulkan(presentMode); - vkSwapchainCreateInfoKhr.clipped = VK_TRUE; - vkSwapchainCreateInfoKhr.oldSwapchain = swapchain; - - auto res = renderDevice->VkCreateSwapchain(renderDevice->GetVkDevice(), &vkSwapchainCreateInfoKhr, renderDevice->GetVkAllocationCallbacks(), &swapchain); - //setName(createInfo.RenderDevice, swapchain, VK_OBJECT_TYPE_SWAPCHAIN_KHR, createInfo.Name); - - renderDevice->VkDestroySwapchain(renderDevice->GetVkDevice(), vkSwapchainCreateInfoKhr.oldSwapchain, renderDevice->GetVkAllocationCallbacks()); - - return res == VK_SUCCESS; - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroySwapchain(renderDevice->GetVkDevice(), swapchain, renderDevice->GetVkAllocationCallbacks()); - debugClear(swapchain); - } - - enum class AcquireState { OK, SUBOPTIMAL, BAD }; - - /** - * \brief Acquires the next image in the swapchain queue to present to. - * \param acquireNextImageInfo Information to perform image acquisition. - * \return Returns true if the contexts needs to be recreated. - */ - [[nodiscard]] GTSL::Result AcquireNextImage(const VulkanRenderDevice* renderDevice, VulkanSynchronizer& semaphore, VulkanSynchronizer& fence) const { - GTSL::uint32 image_index = 0; - - auto result = renderDevice->VkAcquireNextImage(renderDevice->GetVkDevice(), swapchain, ~0ULL, semaphore.GetVkSemaphore(), fence.GetVkFence(), &image_index); - - auto state = result == VK_SUCCESS ? AcquireState::OK : result == VK_SUBOPTIMAL_KHR ? AcquireState::SUBOPTIMAL : AcquireState::BAD; - - fence.Signal(); - semaphore.Signal(); - - return GTSL::Result(static_cast(image_index), state); - } - - [[nodiscard]] GTSL::Result AcquireNextImage(const VulkanRenderDevice* renderDevice, VulkanSynchronizer* semaphore) const { - GTSL::uint32 image_index = 0; - - auto result = renderDevice->VkAcquireNextImage(renderDevice->GetVkDevice(), swapchain, ~0ULL, semaphore->GetVkSemaphore(), nullptr, &image_index); - - AcquireState acquire_state; - - switch (result) { - case VK_SUCCESS: acquire_state = AcquireState::OK; break; - case VK_SUBOPTIMAL_KHR: acquire_state = AcquireState::SUBOPTIMAL; break; - case VK_ERROR_OUT_OF_DATE_KHR: acquire_state = AcquireState::BAD; break; - default: acquire_state = AcquireState::BAD; break; - } - - //if (!semaphore.IsSignaled()) { - semaphore->Signal(); - //} - - return GTSL::Result(static_cast(image_index), acquire_state); - } - - static bool Present(const VulkanRenderDevice* renderDevice, GTSL::Range waitSemaphores, GTSL::Range render_contexts, GTSL::Range indices, VulkanQueue queue) { - VkPresentInfoKHR vkPresentInfoKhr{ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; - - GTSL::StaticVector semaphores; - GTSL::StaticVector swapchains; - - for (auto& s : waitSemaphores) { - s->Release(); - semaphores.EmplaceBack(s->GetVkSemaphore()); - } - - for(const auto& e : render_contexts) { - swapchains.EmplaceBack(e->swapchain); - } - - vkPresentInfoKhr.waitSemaphoreCount = semaphores.GetLength(); - vkPresentInfoKhr.pWaitSemaphores = semaphores.begin(); - vkPresentInfoKhr.swapchainCount = swapchains.GetLength(); - vkPresentInfoKhr.pSwapchains = swapchains.GetData(); - vkPresentInfoKhr.pImageIndices = indices.begin(); - vkPresentInfoKhr.pResults = nullptr; - - return renderDevice->VkQueuePresent(queue.GetVkQueue(), &vkPresentInfoKhr) == VK_SUCCESS; - } - - [[nodiscard]] GTSL::StaticVector GetTextures(const VulkanRenderDevice* renderDevice) const { - GTSL::uint32 swapchainImageCount = 8; - VkImage vkImages[8]; - renderDevice->VkGetSwapchainImages(renderDevice->GetVkDevice(), swapchain, &swapchainImageCount, vkImages); - - GTSL::StaticVector vulkanTextures; - - for(GTSL::uint32 i = 0; i < swapchainImageCount; ++i) { - vulkanTextures.EmplaceBack(vkImages[i]); - } - - return vulkanTextures; - } - - [[nodiscard]] GTSL::uint64 GetHandle() const { return reinterpret_cast(swapchain); } - - private: - VkSwapchainKHR swapchain = nullptr; - }; -} \ No newline at end of file diff --git a/src/GAL/Vulkan/VulkanRenderDevice.h b/src/GAL/Vulkan/VulkanRenderDevice.h deleted file mode 100644 index d8367a5b..00000000 --- a/src/GAL/Vulkan/VulkanRenderDevice.h +++ /dev/null @@ -1,1005 +0,0 @@ -#pragma once - -#include "GAL/RenderDevice.h" - -#include "Vulkan.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#undef ERROR - -namespace GAL -{ - class VulkanRenderDevice; - - template - void setName(const VulkanRenderDevice* renderDevice, T handle, const VkObjectType objectType, const GTSL::Range text); - - class VulkanRenderDevice final : public RenderDevice { - public: - struct RayTracingCapabilities { - GTSL::uint32 RecursionDepth = 0, ShaderGroupHandleAlignment = 0, ShaderGroupBaseAlignment = 0, ShaderGroupHandleSize = 0, ScratchBuildOffsetAlignment = 0; - Device BuildDevice; - }; - - VulkanRenderDevice() = default; - - using InitRes = GTSL::Result>; - - template - [[nodiscard]] InitRes Initialize(const CreateInfo& createInfo, const ALLOC& alloc) { - debugPrintFunction = createInfo.DebugPrintFunction; - -#if BE_PLATFORM_WINDOWS - if (!vulkanDLL.LoadLibrary(u8"vulkan-1")) { return InitRes(GTSL::Range(u8"Vulkan dynamic library could not be loaded."), false); } -#elif BE_PLATFORM_LINUX - if (!vulkanDLL.LoadLibrary(u8"libvulkan.so.1")) { return InitRes(GTSL::Range(u8"Vulkan dynamic library could not be loaded."), false); } -#endif - - vulkanDLL.LoadDynamicFunction(u8"vkGetInstanceProcAddr", &VkGetInstanceProcAddr); - if (!VkGetInstanceProcAddr) { return InitRes(GTSL::Range(u8"vkGetInstanceProcAddr function could not be loaded."), false); } - - auto vkAllocate = [](void* data, size_t size, size_t alignment, VkSystemAllocationScope) -> void* { - auto* allocation_info = static_cast(data); - return allocation_info->Allocate(allocation_info->UserData, size, alignment); - }; - - auto vkReallocate = [](void* data, void* originalAlloc, size_t size, size_t alignment, VkSystemAllocationScope) -> void* { - auto* allocation_info = static_cast(data); - - if (originalAlloc && size) { - return allocation_info->Reallocate(allocation_info->UserData, originalAlloc, size, alignment); - } - - if (!originalAlloc && size) { - return allocation_info->Allocate(allocation_info->UserData, size, alignment); - } - - allocation_info->Deallocate(allocation_info->UserData, originalAlloc); - return nullptr; - }; - - auto vkFree = [](void* data, void* alloc) -> void { - if (alloc) { - auto* allocation_info = static_cast(data); - allocation_info->Deallocate(allocation_info->UserData, alloc); - } - }; - - allocationCallbacks.pUserData = &allocationInfo; - allocationCallbacks.pfnAllocation = vkAllocate; - allocationCallbacks.pfnReallocation = vkReallocate; - allocationCallbacks.pfnFree = vkFree; - allocationCallbacks.pfnInternalAllocation = nullptr; allocationCallbacks.pfnInternalFree = nullptr; - - allocationInfo = createInfo.allocation; debug = createInfo.Debug; - - { - GTSL::HashMap availableInstanceExtensions(32, alloc); - VkExtensionProperties extension_properties[64]; - - uint32 extensionCount = 64; - getInstanceProcAddr(u8"vkEnumerateInstanceExtensionProperties")(nullptr, &extensionCount, extension_properties); - - for (uint32 i = 0; i < extensionCount; ++i) { - availableInstanceExtensions.Emplace(GTSL::StringView(reinterpret_cast(extension_properties[i].extensionName)), i); - } - - VkApplicationInfo vkApplicationInfo{ VK_STRUCTURE_TYPE_APPLICATION_INFO }; - //vkEnumerateInstanceVersion(&vkApplicationInfo.apiVersion); - vkApplicationInfo.apiVersion = VK_MAKE_VERSION(1, 3, 0); - vkApplicationInfo.applicationVersion = VK_MAKE_VERSION(createInfo.ApplicationVersion[0], createInfo.ApplicationVersion[1], createInfo.ApplicationVersion[2]); - vkApplicationInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1); - //vkApplicationInfo.pApplicationName = createInfo.ApplicationName.begin(); //todo: translate - vkApplicationInfo.pEngineName = "Game-Tek | ByteEngine"; - - VkInstanceCreateInfo vkInstanceCreateInfo{ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; - - auto setInstancepNext = [&](void* newPointer) { - if (vkInstanceCreateInfo.pNext) { - //pointer to last structure now extending vkInstanceCreateInfo - auto* str = static_cast(const_cast(vkInstanceCreateInfo.pNext)); //constness is only there to guarantee VK will not touch it, WE can do it with no problem - void** strpNext = reinterpret_cast(str + sizeof(VkStructureType)); - *strpNext = newPointer; - return; - } - - vkInstanceCreateInfo.pNext = newPointer; - }; - - GTSL::StaticVector instanceLayers; - GTSL::StaticVector instanceExtensions; - - if (debug) { - instanceLayers.EmplaceBack("VK_LAYER_KHRONOS_validation"); - instanceExtensions.EmplaceBack(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - } - - auto tryAddExtension = [&](const GTSL::StringView extensionName) { - if (auto searchResult = availableInstanceExtensions.TryGet(extensionName)) { - instanceExtensions.EmplaceBack(extension_properties[searchResult.Get()].extensionName); - return true; - } - - return false; - }; - - for (auto e : createInfo.Extensions) { - switch (e.First) { - case Extension::RAY_TRACING: break; - case Extension::PIPELINE_CACHE_EXTERNAL_SYNC: break; - case Extension::SCALAR_LAYOUT: break; - case Extension::SWAPCHAIN_RENDERING: { - if(!tryAddExtension(u8"VK_KHR_surface")) { - return InitRes(GTSL::Range(u8"Required instance extension: \nVK_KHR_surface\" is not available."), false); - } -#if BE_PLATFORM_WINDOWS - if(!tryAddExtension(u8"VK_KHR_win32_surface")) { - return InitRes(GTSL::Range(u8"Required instance extension: \nVK_KHR_win32_surface\" is not available."), false); - } -#elif BE_PLATFORM_LINUX - if(!tryAddExtension(u8"VK_KHR_xcb_surface")) { - return InitRes(GTSL::Range(u8"Required instance extension: \nVK_KHR_xcb_surface\" is not available."), false); - } - - if(!tryAddExtension(u8"VK_KHR_xlib_surface")) { - return InitRes(GTSL::Range(u8"Required instance extension: \nVK_KHR_xlib_surface\" is not available."), false); - } - - if(!tryAddExtension(u8"VK_KHR_wayland_surface")) { - return InitRes(GTSL::Range(u8"Required instance extension: \nVK_KHR_wayland_surface\" is not available."), false); - } -#endif - break; - } - default:; - } - } - -#if BE_DEBUG - GTSL::StaticVector enables; - if (createInfo.SynchronizationValidation) { enables.EmplaceBack(VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT); } - if (createInfo.PerformanceValidation) { enables.EmplaceBack(VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT); } - VkValidationFeaturesEXT features = {}; - features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; - features.enabledValidationFeatureCount = enables.GetLength(); - features.pEnabledValidationFeatures = enables.begin(); - - setInstancepNext(&features); - - VkDebugUtilsMessengerCreateInfoEXT vkDebugUtilsMessengerCreateInfoExt{ VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT }; - vkDebugUtilsMessengerCreateInfoExt.pNext = nullptr; - vkDebugUtilsMessengerCreateInfoExt.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - vkDebugUtilsMessengerCreateInfoExt.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - vkDebugUtilsMessengerCreateInfoExt.pfnUserCallback = debugCallback; - vkDebugUtilsMessengerCreateInfoExt.pUserData = this; - vkInstanceCreateInfo.pNext = debug ? &vkDebugUtilsMessengerCreateInfoExt : nullptr; -#endif - - vkInstanceCreateInfo.pApplicationInfo = &vkApplicationInfo; - vkInstanceCreateInfo.enabledLayerCount = instanceLayers.GetLength(); - vkInstanceCreateInfo.ppEnabledLayerNames = instanceLayers.begin(); - vkInstanceCreateInfo.enabledExtensionCount = instanceExtensions.GetLength(); - vkInstanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.begin(); - - if (getInstanceProcAddr(u8"vkCreateInstance")(&vkInstanceCreateInfo, GetVkAllocationCallbacks(), &instance) != VK_SUCCESS) { - return InitRes(GTSL::Range(u8"Failed to create instance."), false); - } - -#if BE_DEBUG - if (debug) { - getInstanceProcAddr(u8"vkCreateDebugUtilsMessengerEXT")(instance, &vkDebugUtilsMessengerCreateInfoExt, GetVkAllocationCallbacks(), &debugMessenger); - } -#endif - } - - { - uint32_t physicalDeviceCount{ 16 }; VkPhysicalDevice vkPhysicalDevices[16]; - getInstanceProcAddr(u8"vkEnumeratePhysicalDevices")(instance, &physicalDeviceCount, vkPhysicalDevices); - - if (!physicalDeviceCount) { return InitRes(GTSL::Range(u8"Physical device count returned was 0."), false); } - - uint32 bestScore = 0, bestPhysicalDevice = ~0U; - - for(uint32 i = 0; i < physicalDeviceCount; ++i) { - VkPhysicalDeviceProperties physical_device_properties; - getInstanceProcAddr(u8"vkGetPhysicalDeviceProperties")(vkPhysicalDevices[i], &physical_device_properties); - VkPhysicalDeviceFeatures physical_device_features; - getInstanceProcAddr(u8"vkGetPhysicalDeviceFeatures")(vkPhysicalDevices[i], &physical_device_features); - - uint64 currentScore = 0; - - switch (physical_device_properties.deviceType) { - case VK_PHYSICAL_DEVICE_TYPE_OTHER: currentScore += 1000; break; - case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: currentScore += 4000; break; - case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: currentScore += 5000; break; - case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: currentScore += 3000; break; - case VK_PHYSICAL_DEVICE_TYPE_CPU: currentScore += 2000; break; - default: return InitRes(GTSL::Range(u8"Driver returned unhandled value."), false); - } - - currentScore += physical_device_properties.limits.maxImageDimension2D / 1024; - currentScore += physical_device_features.textureCompressionBC; - - if(currentScore > bestScore) { - bestPhysicalDevice = i; - bestScore = currentScore; - } - } - - if (bestPhysicalDevice == ~0U) { return InitRes(GTSL::Range(u8"No suitable physical device could be chosen."), false); } - - physicalDevice = vkPhysicalDevices[bestPhysicalDevice]; - } - - GTSL::HashMap availableDeviceExtensions(256, 0.25f, alloc); - VkExtensionProperties extension_properties[256]; - GTSL::StaticVector deviceExtensions; - - { - uint32 extensionCount = 256; - getInstanceProcAddr(u8"vkEnumerateDeviceExtensionProperties")(physicalDevice, nullptr, &extensionCount, extension_properties); - - for (uint32 i = 0; i < extensionCount; ++i) { - availableDeviceExtensions.Emplace(GTSL::StringView(reinterpret_cast(extension_properties[i].extensionName)), i); - } - } - - { - GTSL::StaticVector vkDeviceQueueCreateInfos; GTSL::uint32 queueFamiliesCount = 32; - - GTSL::float32 familiesPriorities[8][8]{ 0.5f }; // THIS ARRAY MUST BE KEPT ALIVE UNTIL vkCreateDevice IS CALLED, IT MUST NOT GO OUT OF SCOPE - - { - VkQueueFamilyProperties vkQueueFamiliesProperties[32]; - //Get the amount of queue families there are in the physical device. - getInstanceProcAddr(u8"vkGetPhysicalDeviceQueueFamilyProperties")(physicalDevice, &queueFamiliesCount, vkQueueFamiliesProperties); - - - GTSL::StaticMap familyMap; - - for (GTSL::uint8 queueIndex = 0; auto & queue : createInfo.Queues) { - uint32 bestFamilyIndex = 0xFFFFFFFF, lessSetBits = 0xFFFFFFFF; - - for (uint32 i = 0; i < queueFamiliesCount; ++i) { - auto setBits = GTSL::NumberOfSetBits(vkQueueFamiliesProperties[i].queueFlags); - if (setBits < lessSetBits && vkQueueFamiliesProperties[i].queueFlags & ToVulkan(queue) && vkQueueFamiliesProperties[i].queueCount) { - bestFamilyIndex = i; - lessSetBits = setBits; - } - } - - auto res = familyMap.TryEmplace(bestFamilyIndex, vkDeviceQueueCreateInfos.GetLength()); - - if (res) { - auto& queueCreateInfo = vkDeviceQueueCreateInfos.EmplaceBack(); - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.pNext = nullptr; - queueCreateInfo.flags = 0; - queueCreateInfo.queueFamilyIndex = bestFamilyIndex; - queueCreateInfo.queueCount = 0; - queueCreateInfo.pQueuePriorities = familiesPriorities[res.Get()]; - } - - createInfo.QueueKeys[queueIndex].Queue = vkDeviceQueueCreateInfos[res.Get()].queueCount; - createInfo.QueueKeys[queueIndex].Family = bestFamilyIndex; - familiesPriorities[bestFamilyIndex][vkDeviceQueueCreateInfos[res.Get()].queueCount] = 1.0f; - ++vkDeviceQueueCreateInfos[res.Get()].queueCount; - - ++queueIndex; - } - } - - VkPhysicalDeviceProperties2 properties2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 }; VkPhysicalDeviceFeatures2 features2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; - - features2.features.samplerAnisotropy = true; - features2.features.shaderSampledImageArrayDynamicIndexing = true; - features2.features.shaderStorageImageArrayDynamicIndexing = true; - features2.features.shaderUniformBufferArrayDynamicIndexing = true; - features2.features.shaderStorageBufferArrayDynamicIndexing = true; - features2.features.shaderInt16 = true; features2.features.shaderInt64 = true; - features2.features.robustBufferAccess = false; - features2.features.shaderStorageImageReadWithoutFormat = true; features2.features.shaderStorageImageWriteWithoutFormat = true; - - void** lastProperty = &properties2.pNext; void** lastFeature = &features2.pNext; - - { - GTSL::Buffer buffer(8192, 8, alloc); - - auto placePropertiesStructure = [&](T** structure, VkStructureType structureType) { - auto* newStructure = buffer.template AllocateStructure(); - *lastProperty = static_cast(newStructure); - *structure = newStructure; newStructure->sType = structureType; - lastProperty = &newStructure->pNext; - }; - - auto placeFeaturesStructure = [&](T** structure, VkStructureType structureType) { - auto* newStructure = buffer.template AllocateStructure(); - *lastFeature = static_cast(newStructure); - *structure = newStructure; newStructure->sType = structureType; - lastFeature = &newStructure->pNext; - }; - - auto getProperties = [&](void* prop) { - VkPhysicalDeviceProperties2 props{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 }; - props.pNext = prop; - getInstanceProcAddr(u8"vkGetPhysicalDeviceProperties2")(physicalDevice, &props); - }; - - auto getFeatures = [&](void* feature) { - VkPhysicalDeviceFeatures2 feats{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; - feats.pNext = feature; - getInstanceProcAddr(u8"vkGetPhysicalDeviceFeatures2")(physicalDevice, &feats); - }; - - auto tryAddExtension = [&](const GTSL::StringView extensionName) { - if(auto searchResult = availableDeviceExtensions.TryGet(extensionName)) { - deviceExtensions.EmplaceBack(extension_properties[searchResult.Get()].extensionName); - return true; - } - return false; - }; - - { - VkPhysicalDeviceVulkan11Features* structure; - placeFeaturesStructure(&structure, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES); - structure->storageBuffer16BitAccess = true; structure->storagePushConstant16 = true; - } - - { - VkPhysicalDeviceVulkan12Features* structure; - placeFeaturesStructure(&structure, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES); - structure->separateDepthStencilLayouts = true; structure->timelineSemaphore = true; - structure->bufferDeviceAddress = true; structure->descriptorIndexing = true; - structure->scalarBlockLayout = true; structure->shaderInt8 = true; - structure->storageBuffer8BitAccess = true; structure->runtimeDescriptorArray = true; - structure->descriptorBindingPartiallyBound = true; structure->shaderSampledImageArrayNonUniformIndexing = true; - structure->shaderStorageBufferArrayNonUniformIndexing = true; structure->shaderStorageImageArrayNonUniformIndexing = true; - structure->shaderUniformBufferArrayNonUniformIndexing = true; - } - - if (tryAddExtension(u8"VK_KHR_synchronization2")) { - VkPhysicalDeviceSynchronization2FeaturesKHR* structure; - placeFeaturesStructure(&structure, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR); - structure->synchronization2 = true; - } else { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_synchronization2\" is not available."), false); - } - - if(!tryAddExtension(u8"VK_KHR_copy_commands2")) { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_copy_commands2\" is not available."), false); - } - - if(!tryAddExtension(u8"VK_KHR_swapchain")) { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_swapchain\" is not available."), false); - } - - //if (tryAddExtension(u8"VK_NV_mesh_shader")) { - // VkPhysicalDeviceMeshShaderFeaturesNV* features; - // placeFeaturesStructure(&features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV); - // features->taskShader = true; features->meshShader = true; - //} else { - // return InitRes(GTSL::Range(u8"Required extension: \nVK_NV_mesh_shader\" is not available."), false); - //} - - if(!tryAddExtension(u8"VK_KHR_maintenance4")) { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_maintenance4\" is not available."), false); - } - - if (tryAddExtension(u8"VK_KHR_dynamic_rendering")) { - VkPhysicalDeviceDynamicRenderingFeaturesKHR* features; - placeFeaturesStructure(&features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR); - features->dynamicRendering = true; - } else { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_dynamic_rendering\" is not available."), false); - } - - for (GTSL::uint32 extension = 0; extension < static_cast(createInfo.Extensions.ElementCount()); ++extension) { - switch (createInfo.Extensions[extension].First) { - case Extension::RAY_TRACING: { - if (tryAddExtension(u8"VK_KHR_acceleration_structure")) { - VkPhysicalDeviceAccelerationStructureFeaturesKHR* acceleration_structure_features; - VkPhysicalDeviceAccelerationStructurePropertiesKHR* acceleration_structure_properties; - - placeFeaturesStructure(&acceleration_structure_features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR); - placePropertiesStructure(&acceleration_structure_properties, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR); - - acceleration_structure_features->accelerationStructure = true; - - VkPhysicalDeviceAccelerationStructureFeaturesKHR features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR }; - VkPhysicalDeviceAccelerationStructurePropertiesKHR properties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR }; - - getFeatures(&features); - getProperties(&properties); - - auto* capabilities = static_cast(createInfo.Extensions[extension].Second); - capabilities->BuildDevice = features.accelerationStructureHostCommands ? Device::CPU : Device::GPU; - capabilities->ScratchBuildOffsetAlignment = properties.minAccelerationStructureScratchOffsetAlignment; - } else{ - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_acceleration_structure\" is not available."), false); - } - - if(tryAddExtension(u8"VK_KHR_ray_query")) { - } else { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_ray_query\" is not available."), false); - } - - if (tryAddExtension(u8"VK_KHR_ray_tracing_pipeline")) { - VkPhysicalDeviceRayTracingPipelineFeaturesKHR* ray_tracing_pipeline_features; - VkPhysicalDeviceRayTracingPipelinePropertiesKHR* ray_tracing_pipeline_properties; - - placeFeaturesStructure(&ray_tracing_pipeline_features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR); - placePropertiesStructure(&ray_tracing_pipeline_properties, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR); - - ray_tracing_pipeline_features->rayTracingPipeline = true; - - VkPhysicalDeviceRayTracingPipelineFeaturesKHR features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR }; - VkPhysicalDeviceRayTracingPipelinePropertiesKHR properties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR }; - - getProperties(&properties); getFeatures(&features); - - auto* capabilities = static_cast(createInfo.Extensions[extension].Second); - capabilities->RecursionDepth = properties.maxRayRecursionDepth; - capabilities->ShaderGroupHandleAlignment = properties.shaderGroupHandleAlignment; - capabilities->ShaderGroupBaseAlignment = properties.shaderGroupBaseAlignment; - capabilities->ShaderGroupHandleSize = properties.shaderGroupHandleSize; - } else { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_ray_tracing_pipeline\" is not available."), false); - } - - if (tryAddExtension(u8"VK_KHR_pipeline_library")) { - } else { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_pipeline_library\" is not available."), false); - } - - if (tryAddExtension(u8"VK_KHR_deferred_host_operations")) { - } else { - return InitRes(GTSL::Range(u8"Required extension: \nVK_KHR_deferred_host_operations\" is not available."), false); - } - - break; - } - case Extension::PIPELINE_CACHE_EXTERNAL_SYNC: { - VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT* pipelineCacheSyncControl; - placeFeaturesStructure(&pipelineCacheSyncControl, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT); - pipelineCacheSyncControl->pipelineCreationCacheControl = true; - break; - } - case Extension::SWAPCHAIN_RENDERING: break; - } - } - - VkDeviceCreateInfo vkDeviceCreateInfo{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; - vkDeviceCreateInfo.pNext = &features2; //extended features - vkDeviceCreateInfo.queueCreateInfoCount = vkDeviceQueueCreateInfos.GetLength(); - vkDeviceCreateInfo.pQueueCreateInfos = vkDeviceQueueCreateInfos.begin(); - vkDeviceCreateInfo.pEnabledFeatures = nullptr; - vkDeviceCreateInfo.enabledExtensionCount = deviceExtensions.GetLength(); - vkDeviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.begin(); - - if (getInstanceProcAddr(u8"vkCreateDevice")(physicalDevice, &vkDeviceCreateInfo, GetVkAllocationCallbacks(), &device) != VK_SUCCESS) { - return InitRes(GTSL::Range(u8"Failed to create device."), false); - } - - getInstanceProcAddr(u8"vkGetDeviceProcAddr", &VkGetDeviceProcAddr); - - getInstanceProcAddr(u8"vkGetPhysicalDeviceProperties2")(physicalDevice, &properties2); - getInstanceProcAddr(u8"vkGetPhysicalDeviceFeatures2")(physicalDevice, &features2); - - uniformBufferMinOffset = static_cast(properties2.properties.limits.minUniformBufferOffsetAlignment); - storageBufferMinOffset = static_cast(properties2.properties.limits.minStorageBufferOffsetAlignment); - linearNonLinearAlignment = static_cast(properties2.properties.limits.bufferImageGranularity); - } - } - - getInstanceProcAddr(u8"vkGetPhysicalDeviceMemoryProperties")(physicalDevice, &memoryProperties); - - getDeviceProcAddr(u8"vkQueueSubmit", &VkQueueSubmit); - getDeviceProcAddr(u8"vkQueueSubmit2KHR", &VkQueueSubmit2); - getDeviceProcAddr(u8"vkQueuePresentKHR", &VkQueuePresent); - getDeviceProcAddr(u8"vkQueueWaitIdle", &VkQueueWaitIdle); - getInstanceProcAddr(u8"vkCreateSwapchainKHR", &VkCreateSwapchain); - getInstanceProcAddr(u8"vkGetSwapchainImagesKHR", &VkGetSwapchainImages); - getInstanceProcAddr(u8"vkAcquireNextImageKHR", &VkAcquireNextImage); - getInstanceProcAddr(u8"vkDestroySwapchainKHR", &VkDestroySwapchain); -#if BE_PLATFORM_WINDOWS - getInstanceProcAddr(u8"vkCreateWin32SurfaceKHR", &VkCreateWin32Surface); -#elif BE_PLATFORM_LINUX - getInstanceProcAddr(u8"vkCreateXcbSurfaceKHR", &VkCreateXcbSurface); - getInstanceProcAddr(u8"vkCreateWaylandSurfaceKHR", &VkCreateWaylandSurface); -#endif - getInstanceProcAddr(u8"vkDestroySurfaceKHR", &VkDestroySurface); - getInstanceProcAddr(u8"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", &VkGetPhysicalDeviceSurfaceCapabilities); - getInstanceProcAddr(u8"vkGetPhysicalDeviceSurfaceFormatsKHR", &VkGetPhysicalDeviceSurfaceFormats); - getInstanceProcAddr(u8"vkGetPhysicalDeviceSurfacePresentModesKHR", &VkGetPhysicalDeviceSurfacePresentModes); - getInstanceProcAddr(u8"vkGetPhysicalDeviceSurfaceSupportKHR", &VkGetPhysicalDeviceSurfaceSupport); - getDeviceProcAddr(u8"vkCreateBuffer", &VkCreateBuffer); - getDeviceProcAddr(u8"vkGetBufferDeviceAddress", &VkGetBufferDeviceAddress); - getDeviceProcAddr(u8"vkDestroyBuffer", &VkDestroyBuffer); - getDeviceProcAddr(u8"vkGetBufferMemoryRequirements", &VkGetBufferMemoryRequirements); - getDeviceProcAddr(u8"vkBindBufferMemory", &VkBindBufferMemory); - getDeviceProcAddr(u8"vkCreateImage", &VkCreateImage); - getDeviceProcAddr(u8"vkDestroyImage", &VkDestroyImage); - getDeviceProcAddr(u8"vkGetImageMemoryRequirements", &VkGetImageMemoryRequirements); - getDeviceProcAddr(u8"vkBindImageMemory", &VkBindImageMemory); - getDeviceProcAddr(u8"vkCreateCommandPool", &VkCreateCommandPool); - getDeviceProcAddr(u8"vkDestroyCommandPool", &VkDestroyCommandPool); - getDeviceProcAddr(u8"vkResetCommandPool", &VkResetCommandPool); - getDeviceProcAddr(u8"vkAllocateCommandBuffers", &VkAllocateCommandBuffers); - getDeviceProcAddr(u8"vkBeginCommandBuffer", &VkBeginCommandBuffer); - getDeviceProcAddr(u8"vkEndCommandBuffer", &VkEndCommandBuffer); - getDeviceProcAddr(u8"vkCreateRenderPass", &VkCreateRenderPass); - getDeviceProcAddr(u8"vkDestroyRenderPass", &VkDestroyRenderPass); - getDeviceProcAddr(u8"vkCreateFramebuffer", &VkCreateFramebuffer); - getDeviceProcAddr(u8"vkDestroyFramebuffer", &VkDestroyFramebuffer); - getDeviceProcAddr(u8"vkCreateShaderModule", &VkCreateShaderModule); - getDeviceProcAddr(u8"vkDestroyShaderModule", &VkDestroyShaderModule); - getDeviceProcAddr(u8"vkCreatePipelineLayout", &VkCreatePipelineLayout); - getDeviceProcAddr(u8"vkDestroyPipelineLayout", &VkDestroyPipelineLayout); - getDeviceProcAddr(u8"vkCreatePipelineCache", &VkCreatePipelineCache); - getDeviceProcAddr(u8"vkMergePipelineCaches", &VkMergePipelineCaches); - getDeviceProcAddr(u8"vkGetPipelineCacheData", &VkGetPipelineCacheData); - getDeviceProcAddr(u8"vkDestroyPipelineCache", &VkDestroyPipelineCache); - getDeviceProcAddr(u8"vkCreateDescriptorSetLayout", &VkCreateDescriptorSetLayout); - getDeviceProcAddr(u8"vkDestroyDescriptorSetLayout", &VkDestroyDescriptorSetLayout); - getDeviceProcAddr(u8"vkCreateDescriptorPool", &VkCreateDescriptorPool); - getDeviceProcAddr(u8"vkAllocateDescriptorSets", &VkAllocateDescriptorSets); - getDeviceProcAddr(u8"vkUpdateDescriptorSets", &VkUpdateDescriptorSets); - getDeviceProcAddr(u8"vkDestroyDescriptorPool", &VkDestroyDescriptorPool); - getDeviceProcAddr(u8"vkCreateFence", &VkCreateFence); - getDeviceProcAddr(u8"vkWaitForFences", &VkWaitForFences); - getDeviceProcAddr(u8"vkGetFenceStatus", &VkGetFenceStatus); - getDeviceProcAddr(u8"vkResetFences", &VkResetFences); - getDeviceProcAddr(u8"vkDestroyFence", &VkDestroyFence); - getDeviceProcAddr(u8"vkCreateSemaphore", &VkCreateSemaphore); - getDeviceProcAddr(u8"vkDestroySemaphore", &VkDestroySemaphore); - getDeviceProcAddr(u8"vkCreateEvent", &VkCreateEvent); - getDeviceProcAddr(u8"vkSetEvent", &VkSetEvent); - getDeviceProcAddr(u8"vkResetEvent", &VkResetEvent); - getDeviceProcAddr(u8"vkDestroyEvent", &VkDestroyEvent); - getDeviceProcAddr(u8"vkCreateGraphicsPipelines", &VkCreateGraphicsPipelines); - getDeviceProcAddr(u8"vkCreateComputePipelines", &VkCreateComputePipelines); - getDeviceProcAddr(u8"vkDestroyPipeline", &VkDestroyPipeline); - getDeviceProcAddr(u8"vkAllocateMemory", &VkAllocateMemory); - getDeviceProcAddr(u8"vkFreeMemory", &VkFreeMemory); - getDeviceProcAddr(u8"vkMapMemory", &VkMapMemory); - getDeviceProcAddr(u8"vkUnmapMemory", &VkUnmapMemory); - getDeviceProcAddr(u8"vkCreateImageView", &VkCreateImageView); - getDeviceProcAddr(u8"vkDestroyImageView", &VkDestroyImageView); - getDeviceProcAddr(u8"vkCreateSampler", &VkCreateSampler); - getDeviceProcAddr(u8"vkDestroySampler", &VkDestroySampler); - getDeviceProcAddr(u8"vkCreateQueryPool", &VkCreateQueryPool); - getDeviceProcAddr(u8"vkGetQueryPoolResults", &VkGetQueryPoolResults); - getDeviceProcAddr(u8"vkDestroyQueryPool", &VkDestroyQueryPool); - getDeviceProcAddr(u8"vkBeginCommandBuffer", &VkBeginCommandBuffer); - getDeviceProcAddr(u8"vkEndCommandBuffer", &VkEndCommandBuffer); - getDeviceProcAddr(u8"vkCmdExecuteCommands", &VkCmdExecuteCommands); - getDeviceProcAddr(u8"vkCmdBeginRenderPass", &VkCmdBeginRenderPass); - getDeviceProcAddr(u8"vkCmdNextSubpass", &VkCmdNextSubpass); - getDeviceProcAddr(u8"vkCmdEndRenderPass", &VkCmdEndRenderPass); - getDeviceProcAddr(u8"vkCmdSetScissor", &VkCmdSetScissor); - getDeviceProcAddr(u8"vkCmdSetViewport", &VkCmdSetViewport); - getDeviceProcAddr(u8"vkCmdBindPipeline", &VkCmdBindPipeline); - getDeviceProcAddr(u8"vkCmdBindDescriptorSets", &VkCmdBindDescriptorSets); - getDeviceProcAddr(u8"vkCmdPushConstants", &VkCmdPushConstants); - getDeviceProcAddr(u8"vkCmdBindVertexBuffers", &VkCmdBindVertexBuffers); - getDeviceProcAddr(u8"vkCmdBindIndexBuffer", &VkCmdBindIndexBuffer); - getDeviceProcAddr(u8"vkCmdDraw", &VkCmdDraw); - getDeviceProcAddr(u8"vkCmdDrawIndexed", &VkCmdDrawIndexed); - getDeviceProcAddr(u8"vkCmdDispatch", &VkCmdDispatch); - getDeviceProcAddr(u8"vkCmdDispatchIndirect", &VkCmdDispatchIndirect); - getDeviceProcAddr(u8"vkCmdCopyBuffer", &VkCmdCopyBuffer); - getDeviceProcAddr(u8"vkCmdCopyBufferToImage", &VkCmdCopyBufferToImage); - getDeviceProcAddr(u8"vkCmdBlitImage2KHR", &VkCmdBlitImage2KHR); - getDeviceProcAddr(u8"vkCmdCopyImage", &VkCmdCopyImage); - getDeviceProcAddr(u8"vkCmdPipelineBarrier", &VkCmdPipelineBarrier); - getDeviceProcAddr(u8"vkCmdPipelineBarrier2KHR", &VkCmdPipelineBarrier2); - getDeviceProcAddr(u8"vkCmdSetEvent", &VkCmdSetEvent); - getDeviceProcAddr(u8"vkCmdResetEvent", &VkCmdResetEvent); - - //getDeviceProcAddr(u8"vkGetDeviceBufferMemoryRequirementsKHR", &VkGetDeviceBufferMemoryRequirements); - //getDeviceProcAddr(u8"vkGetDeviceImageMemoryRequirementsKHR", &VkGetDeviceImageMemoryRequirements); - - if (availableDeviceExtensions.Find(u8"VK_NV_mesh_shader")) { - getDeviceProcAddr(u8"vkCmdDrawMeshTasksNV", &VkCmdDrawMeshTasks); - } else { - return InitRes(GTSL::Range(u8"Required extension: \nVK_NV_mesh_shader\" is not available."), false); - } - - getDeviceProcAddr(u8"vkCmdBeginRenderingKHR", &VkCmdBeginRendering); - getDeviceProcAddr(u8"vkCmdEndRenderingKHR", &VkCmdEndRendering); - - for (auto e : createInfo.Extensions) { - switch (e.First) { - case Extension::RAY_TRACING: { - getDeviceProcAddr(u8"vkCreateAccelerationStructureKHR", &vkCreateAccelerationStructureKHR); - getDeviceProcAddr(u8"vkDestroyAccelerationStructureKHR", &vkDestroyAccelerationStructureKHR); - getDeviceProcAddr(u8"vkCreateRayTracingPipelinesKHR", &vkCreateRayTracingPipelinesKHR); - getDeviceProcAddr(u8"vkGetAccelerationStructureBuildSizesKHR", &vkGetAccelerationStructureBuildSizesKHR); - getDeviceProcAddr(u8"vkGetRayTracingShaderGroupHandlesKHR", &vkGetRayTracingShaderGroupHandlesKHR); - getDeviceProcAddr(u8"vkBuildAccelerationStructuresKHR", &vkBuildAccelerationStructuresKHR); - getDeviceProcAddr(u8"vkCmdBuildAccelerationStructuresKHR", &vkCmdBuildAccelerationStructuresKHR); - getDeviceProcAddr(u8"vkGetAccelerationStructureDeviceAddressKHR", &vkGetAccelerationStructureDeviceAddressKHR); - getDeviceProcAddr(u8"vkCreateDeferredOperationKHR", &vkCreateDeferredOperationKHR); - getDeviceProcAddr(u8"vkDeferredOperationJoinKHR", &vkDeferredOperationJoinKHR); - getDeviceProcAddr(u8"vkGetDeferredOperationResultKHR", &vkGetDeferredOperationResultKHR); - getDeviceProcAddr(u8"vkGetDeferredOperationMaxConcurrencyKHR", &vkGetDeferredOperationMaxConcurrencyKHR); - getDeviceProcAddr(u8"vkDestroyDeferredOperationKHR", &vkDestroyDeferredOperationKHR); - getDeviceProcAddr(u8"vkCmdCopyAccelerationStructureKHR", &vkCmdCopyAccelerationStructureKHR); - getDeviceProcAddr(u8"vkCmdCopyAccelerationStructureToMemoryKHR", &vkCmdCopyAccelerationStructureToMemoryKHR); - getDeviceProcAddr(u8"vkCmdCopyMemoryToAccelerationStructureKHR", &vkCmdCopyMemoryToAccelerationStructureKHR); - getDeviceProcAddr(u8"vkCmdWriteAccelerationStructuresPropertiesKHR", &vkCmdWriteAccelerationStructuresPropertiesKHR); - getDeviceProcAddr(u8"vkCmdTraceRaysKHR", &vkCmdTraceRaysKHR); - getDeviceProcAddr(u8"vkCmdSetRayTracingPipelineStackSizeKHR", &vkCmdSetRayTracingPipelineStackSizeKHR); - getDeviceProcAddr(u8"vkGetRayTracingShaderGroupStackSizeKHR", &vkGetRayTracingShaderGroupStackSizeKHR); - break; - } - } - } - - for (GTSL::uint32 i = 0; i < memoryProperties.memoryTypeCount; ++i) { - memoryTypes[i] = ToGAL(memoryProperties.memoryTypes[i].propertyFlags); - } - -#if BE_DEBUG - getInstanceProcAddr(u8"vkSetDebugUtilsObjectNameEXT", &vkSetDebugUtilsObjectNameEXT); - getInstanceProcAddr(u8"vkCmdInsertDebugUtilsLabelEXT", &vkCmdInsertDebugUtilsLabelEXT); - getInstanceProcAddr(u8"vkCmdBeginDebugUtilsLabelEXT", &vkCmdBeginDebugUtilsLabelEXT); - getInstanceProcAddr(u8"vkCmdEndDebugUtilsLabelEXT", &vkCmdEndDebugUtilsLabelEXT); - - VkPhysicalDeviceProperties physicalDeviceProperties; - getInstanceProcAddr(u8"vkGetPhysicalDeviceProperties")(physicalDevice, &physicalDeviceProperties); - - //NVIDIA's driver have a bug when setting the name for this 3 object types, TODO. fix in the future - if (physicalDeviceProperties.vendorID != NVIDIA_VENDOR_ID) { - GTSL::StaticString<128> instanceName(createInfo.ApplicationName); instanceName += u8" instance"; - setName(this, instance, VK_OBJECT_TYPE_INSTANCE, instanceName); - - GTSL::StaticString<128> physicalDeviceName(createInfo.ApplicationName); physicalDeviceName += u8" physical device"; - setName(this, physicalDevice, VK_OBJECT_TYPE_PHYSICAL_DEVICE, physicalDeviceName); - - GTSL::StaticString<128> deviceName(createInfo.ApplicationName); deviceName += u8" device"; - setName(this, device, VK_OBJECT_TYPE_DEVICE, deviceName); - } -#endif - - return InitRes(true); - } - - static constexpr uint32 NVIDIA_VENDOR_ID = 0x10DE; - - void Wait() const { getDeviceProcAddr(u8"vkDeviceWaitIdle")(device); } - - void Destroy() { - Wait(); - getDeviceProcAddr(u8"vkDestroyDevice")(device, GetVkAllocationCallbacks()); - -#if BE_DEBUG - if (debug) { - getInstanceProcAddr(u8"vkDestroyDebugUtilsMessengerEXT")(instance, debugMessenger, GetVkAllocationCallbacks()); - } - debugClear(debugMessenger); -#endif - - getInstanceProcAddr(u8"vkDestroyInstance")(instance, GetVkAllocationCallbacks()); - - debugClear(device); debugClear(instance); - } - - ~VulkanRenderDevice() = default; - - GPUInfo GetGPUInfo() const { - GPUInfo result; VkPhysicalDeviceProperties physicalDeviceProperties; - - getInstanceProcAddr(u8"vkGetPhysicalDeviceProperties")(physicalDevice, &physicalDeviceProperties); - - result.GPUName = GTSL::Range(reinterpret_cast(physicalDeviceProperties.deviceName)); - result.DriverVersion = physicalDeviceProperties.driverVersion; - result.APIVersion = physicalDeviceProperties.apiVersion; - for (auto e : physicalDeviceProperties.pipelineCacheUUID) { - result.PipelineCacheUUID[&e - physicalDeviceProperties.pipelineCacheUUID] = e; - } - - return result; - } - - [[nodiscard]] uint32_t GetMemoryTypeIndex(MemoryType memoryType) const { - for (GTSL::uint32 i = 0; i < memoryProperties.memoryTypeCount; ++i) { - if (memoryType == memoryTypes[i]) { - return i; - } - } - - return 0xFFFFFFFF; - } - - struct FindSupportedImageFormat { - GTSL::Range Candidates; - TextureUse TextureUses; - FormatDescriptor Format; - Tiling TextureTiling; - }; - [[nodiscard]] FormatDescriptor FindNearestSupportedImageFormat(const FindSupportedImageFormat& findSupportedImageFormat) const { - VkFormatProperties format_properties; - - VkFormatFeatureFlags features{}; - - TranslateMask(TextureUses::TRANSFER_SOURCE, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, findSupportedImageFormat.TextureUses, features); - TranslateMask(TextureUses::TRANSFER_DESTINATION, VK_FORMAT_FEATURE_TRANSFER_DST_BIT, findSupportedImageFormat.TextureUses, features); - TranslateMask(TextureUses::SAMPLE, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, findSupportedImageFormat.TextureUses, features); - TranslateMask(TextureUses::STORAGE, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT, findSupportedImageFormat.TextureUses, features); - if(findSupportedImageFormat.TextureUses & TextureUses::ATTACHMENT) { - switch (findSupportedImageFormat.Format.Type) { - case TextureType::COLOR: features |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; break; - case TextureType::DEPTH: features |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; break; - } - } - - for (auto e : findSupportedImageFormat.Candidates) { - getInstanceProcAddr(u8"vkGetPhysicalDeviceFormatProperties")(physicalDevice, ToVulkan(MakeFormatFromFormatDescriptor(e)), &format_properties); - - switch (static_cast(findSupportedImageFormat.TextureTiling)) { - case VK_IMAGE_TILING_LINEAR: { - if (format_properties.linearTilingFeatures & features) { return e; } - break; - } - case VK_IMAGE_TILING_OPTIMAL: { - if (format_properties.optimalTilingFeatures & features) { return e; } - break; - } - default: GAL_DEBUG_BREAK; - } - } - - return {}; - } - - [[nodiscard]] VkInstance GetVkInstance() const { return instance; } - [[nodiscard]] VkPhysicalDevice GetVkPhysicalDevice() const { return physicalDevice; } - [[nodiscard]] VkDevice GetVkDevice() const { return device; } - - [[nodiscard]] MemoryType FindNearestMemoryType(MemoryType memoryType) const { - for (GTSL::uint32 i = 0; i < memoryProperties.memoryTypeCount; ++i) { - if ((ToGAL(memoryProperties.memoryTypes[i].propertyFlags) & memoryType) == memoryType) { - return ToGAL(memoryProperties.memoryTypes[i].propertyFlags); - } - } - - return MemoryType(); - } - - [[nodiscard]] GTSL::uint32 GetUniformBufferBindingOffsetAlignment() const { return static_cast(uniformBufferMinOffset); } - [[nodiscard]] GTSL::uint32 GetStorageBufferBindingOffsetAlignment() const { return static_cast(storageBufferMinOffset); } - - struct MemoryHeap { - GTSL::Byte Size; - MemoryType HeapType; - - GTSL::StaticVector MemoryTypes; - }; - - GTSL::StaticVector GetMemoryHeaps() const { - GTSL::StaticVector memoryHeaps; - - for (GTSL::uint8 heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex) { - MemoryHeap memoryHeap; - memoryHeap.Size = GTSL::Byte(memoryProperties.memoryHeaps[heapIndex].size); - - TranslateMask(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, memoryProperties.memoryHeaps[heapIndex].flags, MemoryTypes::GPU, memoryHeap.HeapType); - - for (GTSL::uint8 memType = 0; memType < memoryProperties.memoryTypeCount; ++memType) { - if (memoryProperties.memoryTypes[memType].heapIndex == heapIndex) { - memoryHeap.MemoryTypes.EmplaceBack(ToGAL(memoryProperties.memoryTypes[memType].propertyFlags)); - } - } - - memoryHeaps.EmplaceBack(memoryHeap); - } - - return memoryHeaps; - } - - void Log(const GTSL::StringView message, MessageSeverity severity) const { - GetDebugPrintFunction()(message, severity); - } - - static auto debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) -> VkBool32 { - auto* deviceCallback = static_cast(pUserData); - - switch (messageSeverity) { - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: { - deviceCallback->GetDebugPrintFunction()(GTSL::StringView(reinterpret_cast(pCallbackData->pMessage)), MessageSeverity::MESSAGE); - break; - } - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: { - deviceCallback->GetDebugPrintFunction()(GTSL::StringView(reinterpret_cast(pCallbackData->pMessage)), MessageSeverity::MESSAGE); - break; - } - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: { - deviceCallback->GetDebugPrintFunction()(GTSL::StringView(reinterpret_cast(pCallbackData->pMessage)), MessageSeverity::WARNING); - break; - } - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: { - deviceCallback->GetDebugPrintFunction()(GTSL::StringView(reinterpret_cast(pCallbackData->pMessage)), MessageSeverity::ERROR); - break; - } - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT: break; - default: GAL_DEBUG_BREAK; break; - } - - return VK_FALSE; - }; - - - [[nodiscard]] const VkAllocationCallbacks* GetVkAllocationCallbacks() const { return nullptr; } - - GTSL::uint32 GetLinearNonLinearGranularity() const { return linearNonLinearAlignment; } - - [[nodiscard]] GTSL::Byte GetAccelerationStructureInstanceSize() const { return GTSL::Byte(64); } - - GTSL::DLL vulkanDLL; - - PFN_vkGetInstanceProcAddr VkGetInstanceProcAddr; PFN_vkGetDeviceProcAddr VkGetDeviceProcAddr; - - template - FT getInstanceProcAddr(const char8_t* name) const { return reinterpret_cast(VkGetInstanceProcAddr(instance, reinterpret_cast(name))); } - template - void getInstanceProcAddr(const char8_t* name, FT* function) const { *function = *reinterpret_cast(VkGetInstanceProcAddr(instance, reinterpret_cast(name))); } - - template - void getDeviceProcAddr(const char8_t* name, FT* function) const { *function = *reinterpret_cast(VkGetDeviceProcAddr(device, reinterpret_cast(name))); } - - template - FT getDeviceProcAddr(const char8_t* name) const { return reinterpret_cast(VkGetDeviceProcAddr(device, reinterpret_cast(name))); } - - PFN_vkCmdBeginRenderPass VkCmdBeginRenderPass; PFN_vkCmdNextSubpass VkCmdNextSubpass; PFN_vkCmdEndRenderPass VkCmdEndRenderPass; - PFN_vkCmdDrawIndexed VkCmdDrawIndexed; PFN_vkCmdDraw VkCmdDraw; - PFN_vkAcquireNextImageKHR VkAcquireNextImage; - PFN_vkResetCommandPool VkResetCommandPool; - PFN_vkCreateBuffer VkCreateBuffer; PFN_vkDestroyBuffer VkDestroyBuffer; - PFN_vkGetBufferMemoryRequirements VkGetBufferMemoryRequirements; - PFN_vkGetImageMemoryRequirements VkGetImageMemoryRequirements; - PFN_vkGetBufferDeviceAddress VkGetBufferDeviceAddress; - PFN_vkCreateImage VkCreateImage; PFN_vkDestroyImage VkDestroyImage; - PFN_vkCreateImageView VkCreateImageView; PFN_vkDestroyImageView VkDestroyImageView; - PFN_vkCreateFramebuffer VkCreateFramebuffer; PFN_vkDestroyFramebuffer VkDestroyFramebuffer; - PFN_vkAllocateMemory VkAllocateMemory; PFN_vkFreeMemory VkFreeMemory; - PFN_vkMapMemory VkMapMemory; PFN_vkUnmapMemory VkUnmapMemory; - PFN_vkCreatePipelineCache VkCreatePipelineCache; PFN_vkDestroyPipelineCache VkDestroyPipelineCache; - PFN_vkMergePipelineCaches VkMergePipelineCaches; - PFN_vkGetPipelineCacheData VkGetPipelineCacheData; - PFN_vkCreateShaderModule VkCreateShaderModule; PFN_vkDestroyShaderModule VkDestroyShaderModule; - PFN_vkCreatePipelineLayout VkCreatePipelineLayout; PFN_vkDestroyPipelineLayout VkDestroyPipelineLayout; - PFN_vkCreateGraphicsPipelines VkCreateGraphicsPipelines; PFN_vkCreateComputePipelines VkCreateComputePipelines; - PFN_vkDestroyPipeline VkDestroyPipeline; - PFN_vkCreateDescriptorPool VkCreateDescriptorPool; PFN_vkDestroyDescriptorPool VkDestroyDescriptorPool; - PFN_vkCreateDescriptorSetLayout VkCreateDescriptorSetLayout; PFN_vkDestroyDescriptorSetLayout VkDestroyDescriptorSetLayout; - PFN_vkAllocateDescriptorSets VkAllocateDescriptorSets; - PFN_vkUpdateDescriptorSets VkUpdateDescriptorSets; - PFN_vkAllocateCommandBuffers VkAllocateCommandBuffers; - PFN_vkCreateCommandPool VkCreateCommandPool; PFN_vkDestroyCommandPool VkDestroyCommandPool; - PFN_vkBeginCommandBuffer VkBeginCommandBuffer; PFN_vkEndCommandBuffer VkEndCommandBuffer; - PFN_vkCreateSampler VkCreateSampler; PFN_vkDestroySampler VkDestroySampler; - PFN_vkCreateSwapchainKHR VkCreateSwapchain; PFN_vkDestroySwapchainKHR VkDestroySwapchain; - PFN_vkGetSwapchainImagesKHR VkGetSwapchainImages; - PFN_vkCreateRenderPass VkCreateRenderPass; PFN_vkDestroyRenderPass VkDestroyRenderPass; - PFN_vkBindBufferMemory VkBindBufferMemory; - PFN_vkBindImageMemory VkBindImageMemory; - PFN_vkCmdBindPipeline VkCmdBindPipeline; - PFN_vkCmdDispatch VkCmdDispatch; - PFN_vkCmdDispatchIndirect VkCmdDispatchIndirect; - PFN_vkCmdCopyBuffer VkCmdCopyBuffer; - PFN_vkCmdCopyBufferToImage VkCmdCopyBufferToImage; - PFN_vkCmdBlitImage2KHR VkCmdBlitImage2KHR; - PFN_vkCmdCopyImage VkCmdCopyImage; - PFN_vkCmdPipelineBarrier VkCmdPipelineBarrier; - PFN_vkCmdPipelineBarrier2KHR VkCmdPipelineBarrier2; - PFN_vkCmdBindDescriptorSets VkCmdBindDescriptorSets; - PFN_vkCmdPushConstants VkCmdPushConstants; - PFN_vkCmdBindVertexBuffers VkCmdBindVertexBuffers; - PFN_vkCmdBindIndexBuffer VkCmdBindIndexBuffer; - PFN_vkCmdSetScissor VkCmdSetScissor; - PFN_vkCmdSetViewport VkCmdSetViewport; - PFN_vkCmdSetEvent VkCmdSetEvent; - PFN_vkCmdResetEvent VkCmdResetEvent; - PFN_vkCreateQueryPool VkCreateQueryPool; PFN_vkDestroyQueryPool VkDestroyQueryPool; - PFN_vkGetQueryPoolResults VkGetQueryPoolResults; - PFN_vkQueueSubmit VkQueueSubmit; - PFN_vkQueueSubmit2KHR VkQueueSubmit2; - PFN_vkQueuePresentKHR VkQueuePresent; - PFN_vkQueueWaitIdle VkQueueWaitIdle; - PFN_vkWaitSemaphores vkWaitSemaphores; - - PFN_vkCmdBeginRenderingKHR VkCmdBeginRendering; - PFN_vkCmdEndRenderingKHR VkCmdEndRendering; - - PFN_vkCmdExecuteCommands VkCmdExecuteCommands; - - //PFN_vkGetDeviceBufferMemoryRequirementsKHR VkGetDeviceBufferMemoryRequirements; - //PFN_vkGetDeviceBufferMemoryRequirementsKHR VkGetDeviceImageMemoryRequirements; - -#if BE_PLATFORM_WINDOWS - PFN_vkCreateWin32SurfaceKHR VkCreateWin32Surface; -#elif BE_PLATFORM_LINUX - PFN_vkCreateXcbSurfaceKHR VkCreateXcbSurface; - PFN_vkCreateWaylandSurfaceKHR VkCreateWaylandSurface; -#endif - - PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR VkGetPhysicalDeviceSurfaceCapabilities; - PFN_vkGetPhysicalDeviceSurfaceFormatsKHR VkGetPhysicalDeviceSurfaceFormats; - PFN_vkGetPhysicalDeviceSurfacePresentModesKHR VkGetPhysicalDeviceSurfacePresentModes; - PFN_vkGetPhysicalDeviceSurfaceSupportKHR VkGetPhysicalDeviceSurfaceSupport; - PFN_vkDestroySurfaceKHR VkDestroySurface; - PFN_vkCreateFence VkCreateFence; PFN_vkDestroyFence VkDestroyFence; - PFN_vkWaitForFences VkWaitForFences; PFN_vkResetFences VkResetFences; - PFN_vkGetFenceStatus VkGetFenceStatus; - PFN_vkCreateSemaphore VkCreateSemaphore; PFN_vkDestroySemaphore VkDestroySemaphore; - PFN_vkCreateEvent VkCreateEvent; PFN_vkDestroyEvent VkDestroyEvent; - PFN_vkSetEvent VkSetEvent; PFN_vkResetEvent VkResetEvent; - - PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR = nullptr; - PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR = nullptr; - PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR = nullptr; - PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR = nullptr; - PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR = nullptr; - PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR = nullptr; - PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR = nullptr; - PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR = nullptr; - PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR = nullptr; - PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR = nullptr; - PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR = nullptr; - PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR = nullptr; - PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR = nullptr; - PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR = nullptr; - PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR = nullptr; - PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR = nullptr; - PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR = nullptr; - PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR = nullptr; - PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR = nullptr; - PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR = nullptr; - - PFN_vkCmdDrawMeshTasksNV VkCmdDrawMeshTasks; - -#if BE_DEBUG - PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; - PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT = nullptr; - PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr; - PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = nullptr; -#endif - - private: -#if BE_DEBUG - VkDebugUtilsMessengerEXT debugMessenger = nullptr; -#endif - bool debug = false; - - GTSL::uint16 uniformBufferMinOffset, storageBufferMinOffset, linearNonLinearAlignment; - - VkInstance instance = nullptr; - VkPhysicalDevice physicalDevice = nullptr; - VkDevice device = nullptr; - AllocationInfo allocationInfo; - VkAllocationCallbacks allocationCallbacks; - VkPhysicalDeviceMemoryProperties memoryProperties; - - MemoryType memoryTypes[16]; - }; - - template - void setName(const VulkanRenderDevice* renderDevice, T handle, const VkObjectType objectType, const GTSL::Range text) { -#if BE_DEBUG - VkDebugUtilsObjectNameInfoEXT vkDebugUtilsObjectNameInfo{ VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT }; - vkDebugUtilsObjectNameInfo.objectHandle = reinterpret_cast(handle); - vkDebugUtilsObjectNameInfo.objectType = objectType; - vkDebugUtilsObjectNameInfo.pObjectName = reinterpret_cast(text.GetData()); - renderDevice->vkSetDebugUtilsObjectNameEXT(renderDevice->GetVkDevice(), &vkDebugUtilsObjectNameInfo); -#endif - } -} diff --git a/src/GAL/Vulkan/VulkanRenderPass.h b/src/GAL/Vulkan/VulkanRenderPass.h deleted file mode 100644 index c746f378..00000000 --- a/src/GAL/Vulkan/VulkanRenderPass.h +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include "GAL/RenderPass.h" - -#include "GAL/Vulkan/Vulkan.h" -#include "GAL/Vulkan/VulkanRenderDevice.h" -#include - -namespace GAL -{ - class VulkanRenderPass final : public RenderPass - { - public: - VulkanRenderPass() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, GTSL::Range attachments, - GTSL::Range subPasses, const GTSL::Range subPassDependencies) { - GTSL::StaticVector vkAttachmentDescriptions; - - for (GTSL::uint32 i = 0; i < static_cast(attachments.ElementCount()); ++i) { - auto& attachmentDescription = vkAttachmentDescriptions.EmplaceBack(); - - attachmentDescription.flags = 0; - attachmentDescription.format = ToVulkan(MakeFormatFromFormatDescriptor(attachments[i].format)); - attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; //TODO: Should match that of the SwapChain images. - attachmentDescription.loadOp = ToVkAttachmentLoadOp(attachments[i].LoadOperation); - attachmentDescription.storeOp = ToVkAttachmentStoreOp(attachments[i].StoreOperation); - attachmentDescription.stencilLoadOp = vkAttachmentDescriptions[i].loadOp; - attachmentDescription.stencilStoreOp = vkAttachmentDescriptions[i].storeOp; - attachmentDescription.initialLayout = ToVulkan(attachments[i].Start, attachments[i].format); - attachmentDescription.finalLayout = ToVulkan(attachments[i].End, attachments[i].format); - } - - GTSL::StaticVector, 16> writeAttachmentsReferences; - GTSL::StaticVector, 16> readAttachmentsReferences; - GTSL::StaticVector, 16> preserveAttachmentsIndices; - GTSL::StaticVector vkDepthAttachmentReferences; - - for (GTSL::uint32 s = 0; s < static_cast(subPasses.ElementCount()); ++s) { - writeAttachmentsReferences.EmplaceBack(); readAttachmentsReferences.EmplaceBack(); preserveAttachmentsIndices.EmplaceBack(); - - auto& depthAttachment = vkDepthAttachmentReferences.EmplaceBack(); - depthAttachment.attachment = VK_ATTACHMENT_UNUSED; depthAttachment.layout = VK_IMAGE_LAYOUT_UNDEFINED; - - for (GTSL::uint32 a = 0; a < static_cast(subPasses[s].Attachments.ElementCount()); ++a) { - VkAttachmentReference attachmentReference; - attachmentReference.attachment = subPasses[s].Attachments[a].Index; - attachmentReference.layout = ToVulkan(subPasses[s].Attachments[a].Layout, attachments[subPasses[s].Attachments[a].Index].format); - - if (subPasses[s].Attachments[a].Access & AccessTypes::WRITE) { - if (attachments[subPasses[s].Attachments[a].Index].format.Type == TextureType::COLOR) { - writeAttachmentsReferences[s].EmplaceBack(attachmentReference); - } else { - depthAttachment.attachment = attachmentReference.attachment; - depthAttachment.layout = attachmentReference.layout; - } - } else { - if (attachments[subPasses[s].Attachments[a].Index].format.Type == TextureType::COLOR) { - readAttachmentsReferences[s].EmplaceBack(attachmentReference); - } else { - depthAttachment.attachment = attachmentReference.attachment; - depthAttachment.layout = attachmentReference.layout; - } - } - } - - for (GTSL::uint32 a = 0; a < static_cast(subPasses[s].PreserveAttachments.ElementCount()); ++a) { - preserveAttachmentsIndices[s].EmplaceBack(subPasses[s].PreserveAttachments[a]); - } - } - - GTSL::StaticVector vkSubpassDescriptions; - - for (GTSL::uint32 s = 0; s < static_cast(subPasses.ElementCount()); ++s) { - auto& description = vkSubpassDescriptions.EmplaceBack(); - description.flags = 0; - description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - description.colorAttachmentCount = writeAttachmentsReferences[s].GetLength(); - description.pColorAttachments = writeAttachmentsReferences[s].begin(); - description.inputAttachmentCount = readAttachmentsReferences[s].GetLength(); - description.pInputAttachments = readAttachmentsReferences[s].begin(); - description.pResolveAttachments = nullptr; - description.preserveAttachmentCount = preserveAttachmentsIndices[s].GetLength(); - description.pPreserveAttachments = preserveAttachmentsIndices[s].begin(); - description.pDepthStencilAttachment = &vkDepthAttachmentReferences[s]; - - //if(vkDepthAttachmentReferences[s].attachment != 0U) { - // - //} - } - - GTSL::StaticVector vkSubpassDependencies; - for (GTSL::uint32 s = 0; s < static_cast(subPassDependencies.ElementCount()); ++s) { - auto& dependency = vkSubpassDependencies.EmplaceBack(); - dependency.srcSubpass = subPassDependencies[s].SourceSubPass == EXTERNAL ? VK_SUBPASS_EXTERNAL : subPassDependencies[s].SourceSubPass; - dependency.dstSubpass = subPassDependencies[s].DestinationSubPass == EXTERNAL ? VK_SUBPASS_EXTERNAL : subPassDependencies[s].DestinationSubPass; - dependency.srcStageMask = ToVulkan(subPassDependencies[s].SourcePipelineStage); - dependency.dstStageMask = ToVulkan(subPassDependencies[s].DestinationPipelineStage); - dependency.dependencyFlags = 0; - } - - VkRenderPassCreateInfo vkRenderpassCreateInfo{ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; - vkRenderpassCreateInfo.attachmentCount = static_cast(attachments.ElementCount()); - vkRenderpassCreateInfo.pAttachments = vkAttachmentDescriptions.begin(); - vkRenderpassCreateInfo.subpassCount = static_cast(subPasses.ElementCount()); - vkRenderpassCreateInfo.pSubpasses = vkSubpassDescriptions.begin(); - vkRenderpassCreateInfo.dependencyCount = vkSubpassDependencies.GetLength(); - vkRenderpassCreateInfo.pDependencies = vkSubpassDependencies.begin(); - - renderDevice->VkCreateRenderPass(renderDevice->GetVkDevice(), &vkRenderpassCreateInfo, renderDevice->GetVkAllocationCallbacks(), &renderPass); - //setName(createInfo.RenderDevice, renderPass, VK_OBJECT_TYPE_RENDER_PASS, createInfo.Name); - } - - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyRenderPass(renderDevice->GetVkDevice(), renderPass, renderDevice->GetVkAllocationCallbacks()); - debugClear(renderPass); - } - - ~VulkanRenderPass() = default; - - [[nodiscard]] VkRenderPass GetVkRenderPass() const { return renderPass; } - [[nodiscard]] uint64_t GetHandle() const { return reinterpret_cast(renderPass); } - private: - VkRenderPass renderPass = nullptr; - }; -} diff --git a/src/GAL/Vulkan/VulkanSynchronization.h b/src/GAL/Vulkan/VulkanSynchronization.h deleted file mode 100644 index d09aa105..00000000 --- a/src/GAL/Vulkan/VulkanSynchronization.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include "GAL/Synchronization.h" -#include "Vulkan.h" -#include "GTSL/Range.hpp" -#include "VulkanRenderDevice.h" - -namespace GAL -{ - class VulkanSynchronizer final : public Synchronizer { - public: - VulkanSynchronizer() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, const GTSL::StringView name, Type syncType, bool isSignaled = false, uint64 initialValue = ~0ULL) { - SyncType = syncType; - - switch (SyncType) { - case Type::FENCE: { - VkFenceCreateInfo vk_fence_create_info{ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; - vk_fence_create_info.flags = isSignaled; - - renderDevice->VkCreateFence(renderDevice->GetVkDevice(), &vk_fence_create_info, renderDevice->GetVkAllocationCallbacks(), &fence); - counter = isSignaled ? 1 : 0; - break; - } - case Type::SEMAPHORE: { - VkSemaphoreCreateInfo vkSemaphoreCreateInfo{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - VkSemaphoreTypeCreateInfo vkSemaphoreTypeCreateInfo{ VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO }; - vkSemaphoreTypeCreateInfo.semaphoreType = initialValue == 0xFFFFFFFFFFFFFFFF ? VK_SEMAPHORE_TYPE_BINARY : VK_SEMAPHORE_TYPE_TIMELINE; - vkSemaphoreTypeCreateInfo.initialValue = initialValue == 0xFFFFFFFFFFFFFFFF ? 0 : initialValue; - vkSemaphoreCreateInfo.pNext = &vkSemaphoreTypeCreateInfo; - - renderDevice->VkCreateSemaphore(renderDevice->GetVkDevice(), &vkSemaphoreCreateInfo, renderDevice->GetVkAllocationCallbacks(), &semaphore); - - setName(renderDevice, semaphore, VK_OBJECT_TYPE_SEMAPHORE, name); - break; - } - case Type::EVENT: { - VkEventCreateInfo vkEventCreateInfo{ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO }; - renderDevice->VkCreateEvent(renderDevice->GetVkDevice(), &vkEventCreateInfo, renderDevice->GetVkAllocationCallbacks(), &event); - break; - } - } - } - - [[nodiscard]] VkFence GetVkFence() const { return fence; } - [[nodiscard]] VkSemaphore GetVkSemaphore() const { return semaphore; } - [[nodiscard]] VkEvent GetVkEvent() const { return event; } - - void Wait(const VulkanRenderDevice* renderDevice) { - if (State()) { - auto result = renderDevice->VkWaitForFences(renderDevice->GetVkDevice(), 1u, &fence, true, 0xFFFFFFFFFFFFFFFF); - if (result == VK_ERROR_DEVICE_LOST) { - renderDevice->Log(u8"Error: device lost", RenderDevice::MessageSeverity::ERROR); - } - } - } - - void Reset(const VulkanRenderDevice* renderDevice) { - switch (SyncType) { - case Type::FENCE: renderDevice->VkResetFences(renderDevice->GetVkDevice(), 1u, &fence); break; - case Type::SEMAPHORE: break; - case Type::EVENT: renderDevice->VkResetEvent(renderDevice->GetVkDevice(), event); break; - } - - Release(); - } - - void Signal() { - ++counter; - } - - void Release() { - --counter; - } - - void Set(const VulkanRenderDevice* renderDevice) { - renderDevice->VkSetEvent(renderDevice->GetVkDevice(), event); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - switch (SyncType) { - case Type::FENCE: renderDevice->VkDestroyFence(renderDevice->GetVkDevice(), fence, renderDevice->GetVkAllocationCallbacks()); debugClear(fence); break; - case Type::SEMAPHORE : renderDevice->VkDestroySemaphore(renderDevice->GetVkDevice(), semaphore, renderDevice->GetVkAllocationCallbacks()); debugClear(semaphore); break; - case Type::EVENT: renderDevice->VkDestroyEvent(renderDevice->GetVkDevice(), event, renderDevice->GetVkAllocationCallbacks()); debugClear(event); break; - } - } - - static void Wait(const VulkanRenderDevice* render_device, const GTSL::Range semaphores, const GTSL::Range values) { - GTSL::StaticVector vk_semaphores; - - for (auto& e : semaphores) { - vk_semaphores.EmplaceBack(e.GetVkSemaphore()); - } - - VkSemaphoreWaitInfo vk_semaphore_wait_info{ VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, nullptr, 0, vk_semaphores.GetLength(), vk_semaphores.GetData(), values.begin() }; - render_device->vkWaitSemaphores(render_device->GetVkDevice(), &vk_semaphore_wait_info, ~0ULL); - } - - bool State() const { return counter; } - private: - VkFence fence = nullptr; - VkSemaphore semaphore = nullptr; - VkEvent event = nullptr; - GTSL::uint64 counter = 0; - - Type SyncType; - }; -} diff --git a/src/GAL/Vulkan/VulkanTexture.h b/src/GAL/Vulkan/VulkanTexture.h deleted file mode 100644 index 9c94fcdd..00000000 --- a/src/GAL/Vulkan/VulkanTexture.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include "Vulkan.h" -#include "VulkanMemory.h" -#include "VulkanRenderDevice.h" -#include "GAL/Texture.h" -#include "GAL/Texture.h" - -namespace GAL -{ - class VulkanTexture final : public Texture { - public: - VulkanTexture() = default; - VulkanTexture(VkImage i) : image(i) {} - - void GetMemoryRequirements(const VulkanRenderDevice* renderDevice, MemoryRequirements* memoryRequirements, TextureUse uses, - FormatDescriptor format, GTSL::Extent3D extent, Tiling tiling, GTSL::uint8 mipLevels) { - - VkImageCreateInfo vkImageCreateInfo{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - vkImageCreateInfo.imageType = ToVulkanType(extent); - vkImageCreateInfo.extent = ToVulkan(extent); - vkImageCreateInfo.mipLevels = mipLevels; - vkImageCreateInfo.arrayLayers = 1; - vkImageCreateInfo.format = ToVulkan(MakeFormatFromFormatDescriptor(format)); - vkImageCreateInfo.tiling = ToVulkan(tiling); - vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - vkImageCreateInfo.usage = ToVulkan(uses, format); - vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - vkImageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - renderDevice->VkCreateImage(renderDevice->GetVkDevice(), &vkImageCreateInfo, renderDevice->GetVkAllocationCallbacks(), &image); - - VkMemoryRequirements vkMemoryRequirements; - renderDevice->VkGetImageMemoryRequirements(renderDevice->GetVkDevice(), image, &vkMemoryRequirements); - memoryRequirements->Size = static_cast(vkMemoryRequirements.size); - memoryRequirements->Alignment = static_cast(vkMemoryRequirements.alignment); - memoryRequirements->MemoryTypes = vkMemoryRequirements.memoryTypeBits; - } - - void Initialize(const VulkanRenderDevice* renderDevice, const GTSL::StringView name, const VulkanDeviceMemory deviceMemory, const GTSL::uint32 offset) { - setName(renderDevice, image, VK_OBJECT_TYPE_IMAGE, name); - renderDevice->VkBindImageMemory(renderDevice->GetVkDevice(), image, deviceMemory.GetVkDeviceMemory(), offset); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyImage(renderDevice->GetVkDevice(), image, renderDevice->GetVkAllocationCallbacks()); - debugClear(image); - } - - [[nodiscard]] VkImage GetVkImage() const { return image; } - - private: - VkImage image = nullptr; - }; - - class VulkanTextureView final : public TextureView { - public: - VulkanTextureView() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, const GTSL::Range name, const VulkanTexture texture, const FormatDescriptor formatDescriptor, const GTSL::Extent3D extent, const GTSL::uint8 mipLevels) { - VkImageViewCreateInfo vkImageViewCreateInfo{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - vkImageViewCreateInfo.image = texture.GetVkImage(); - vkImageViewCreateInfo.viewType = ToVkImageViewType(extent); - vkImageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; vkImageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; vkImageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; vkImageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - vkImageViewCreateInfo.format = ToVulkan(MakeFormatFromFormatDescriptor(formatDescriptor)); - vkImageViewCreateInfo.subresourceRange.aspectMask = ToVulkan(formatDescriptor.Type); - vkImageViewCreateInfo.subresourceRange.baseMipLevel = 0; - vkImageViewCreateInfo.subresourceRange.levelCount = mipLevels; - vkImageViewCreateInfo.subresourceRange.baseArrayLayer = 0; - vkImageViewCreateInfo.subresourceRange.layerCount = 1; - - renderDevice->VkCreateImageView(renderDevice->GetVkDevice(), &vkImageViewCreateInfo, renderDevice->GetVkAllocationCallbacks(), &imageView); - setName(renderDevice, imageView, VK_OBJECT_TYPE_IMAGE_VIEW, name); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroyImageView(renderDevice->GetVkDevice(), imageView, renderDevice->GetVkAllocationCallbacks()); - debugClear(imageView); - } - - [[nodiscard]] VkImageView GetVkImageView() const { return imageView; } - - private: - VkImageView imageView = nullptr; - - friend class VulkanRenderContext; - }; - - class VulkanSampler final : public Sampler { - public: - VulkanSampler() = default; - - void Initialize(const VulkanRenderDevice* renderDevice, const GTSL::uint8 anisotropy) { - VkSamplerCreateInfo vkSamplerCreateInfo{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; - vkSamplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - vkSamplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - vkSamplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - vkSamplerCreateInfo.minFilter = VK_FILTER_LINEAR; vkSamplerCreateInfo.magFilter = VK_FILTER_LINEAR; - vkSamplerCreateInfo.maxAnisotropy = static_cast(anisotropy == 0 ? 1 : anisotropy); - vkSamplerCreateInfo.anisotropyEnable = static_cast(anisotropy); - vkSamplerCreateInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - vkSamplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - vkSamplerCreateInfo.unnormalizedCoordinates = VK_FALSE; - vkSamplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER; - vkSamplerCreateInfo.compareEnable = VK_FALSE; - vkSamplerCreateInfo.mipLodBias = 0.0f; - vkSamplerCreateInfo.minLod = 0.0f; - vkSamplerCreateInfo.maxLod = 0.0f; - - renderDevice->VkCreateSampler(renderDevice->GetVkDevice(), &vkSamplerCreateInfo, renderDevice->GetVkAllocationCallbacks(), &sampler); - //setName(renderDevice, sampler, VK_OBJECT_TYPE_SAMPLER, createInfo.Name); - } - - void Destroy(const VulkanRenderDevice* renderDevice) { - renderDevice->VkDestroySampler(renderDevice->GetVkDevice(), sampler, renderDevice->GetVkAllocationCallbacks()); - debugClear(sampler); - } - - [[nodiscard]] VkSampler GetVkSampler() const { return sampler; } - private: - VkSampler sampler{ nullptr }; - }; -} diff --git a/src/application.rs b/src/application.rs new file mode 100644 index 00000000..4c49570f --- /dev/null +++ b/src/application.rs @@ -0,0 +1,202 @@ +//! The application module contains the application trait and some alternative implementations.\ +//! An application is the main entry point of the engine and is responsible for initializing and deinitializing the engine. +//! It also contains the main loop of the engine. +//! An application MUST be a singleton and created before any other engine functionality is used.\ +//! All state associated with the application/process should be stored in an application. + +/// The application trait is the main entry point of the engine. +/// It is responsible for initializing and deinitializing the engine. +/// It also contains the main loop of the engine. +/// An application MUST be a singleton and created before any other engine functionality is used.\ +/// All state associated with the application/process should be stored in an application. +pub trait Application { + /// Creates a new application with the given name. + fn new(name: &str) -> Self; + + /// Initializes the application with the given arguments. + fn initialize(&mut self, arguments: std::env::Args); + + /// Returns the name of the application. + fn get_name(&self) -> String; + + fn tick(&mut self); + + /// Deinitializes the application. + fn deinitialize(&mut self); +} + +pub struct BaseApplication { + name: String, +} + +impl Application for BaseApplication { + fn new(name: &str) -> BaseApplication { + BaseApplication { name: String::from(name) } + } + + fn initialize(&mut self, arguments: std::env::Args) { + println!("\x1b[32m\x1b[1mByte-Engine\x1b[0m"); + println!("Initializing \x1b[4m{}\x1b[24m application with parameters: {}.", self.name, arguments.collect::>().join(", ")); + + println!("Initialized base Byte-Engine application!"); + } + + fn deinitialize(&mut self) { + println!("Deinitializing base Byte-Engine application..."); + + println!("Deinitialized base Byte-Engine application."); + } + + fn tick(&mut self) { return; } + + fn get_name(&self) -> String { self.name.clone() } +} + +use crate::{orchestrator, window_system, render_system}; + +pub struct OrchestratedApplication { + application: BaseApplication, + orchestrator: orchestrator::Orchestrator, + last_tick_time: std::time::Instant, + close: bool, +} + +impl Application for OrchestratedApplication { + fn new(name: &str) -> Self { + let application = Application::new(name); + let orchestrator = orchestrator::Orchestrator::new(); + + OrchestratedApplication { application, orchestrator, last_tick_time: std::time::Instant::now(), close: false } + } + + fn initialize(&mut self, arguments: std::env::Args) { + self.application.initialize(arguments); + self.orchestrator.initialize(); + } + + fn deinitialize(&mut self) { + self.orchestrator.deinitialize(); + self.application.deinitialize(); + } + + fn tick(&mut self) { + let target_tick_duration = std::time::Duration::from_millis(16); + let elapsed = self.last_tick_time.elapsed(); + + if elapsed < target_tick_duration { + std::thread::sleep(target_tick_duration - elapsed); + } + + self.last_tick_time = std::time::Instant::now(); + + self.orchestrator.update(); + } + + fn get_name(&self) -> String { self.application.get_name() } +} + +impl OrchestratedApplication { + pub fn close(&mut self) { + self.close = true; + } + + pub fn get_name(&self) -> String { self.application.get_name() } + + pub fn get_orchestrator(&self) -> &orchestrator::Orchestrator { &self.orchestrator } + pub fn get_mut_orchestrator(&mut self) -> &mut orchestrator::Orchestrator { &mut self.orchestrator } +} + +pub struct GraphicsApplication { + application: OrchestratedApplication, + file_tracker: crate::file_tracker::FileTracker, + window_system_handle: Option, + render_system_handle: Option, +} + +impl Application for GraphicsApplication { + fn new(name: &str) -> Self { + let application = OrchestratedApplication::new(name); + + GraphicsApplication { application, file_tracker: crate::file_tracker::FileTracker::new(), window_system_handle: None, render_system_handle: None } + } + + fn initialize(&mut self, arguments: std::env::Args) { + self.application.initialize(arguments); + + let mut window_system = window_system::WindowSystem::new(); + let mut render_system = render_system::RenderSystem::new(); + + let window_handle = window_system.create_window("Main Window", crate::Extent { width: 1920, height: 1080, depth: 1 }, "main_window"); + + render_system.bind_to_window(window_system.get_os_handles(window_handle)); + + self.window_system_handle = Some(self.application.get_mut_orchestrator().add_system(window_system)); + //self.render_system_handle = Some(self.application.get_mut_orchestrator().add_system(render_system)); + + self.file_tracker.watch(std::path::Path::new("configuration.json")); + } + + fn get_name(&self) -> String { self.application.get_name() } + + fn deinitialize(&mut self) { + self.application.deinitialize(); + } + + fn tick(&mut self) { + self.application.tick(); + self.file_tracker.poll(); + } +} + +impl GraphicsApplication { + pub fn close(&mut self) { + self.application.close(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn create_base_application() { + let mut app = BaseApplication::new("Test"); + app.initialize(std::env::args()); + + assert!(app.get_name() == "Test"); + + app.deinitialize(); + } + + #[test] + fn create_orchestrated_application() { + let mut app = OrchestratedApplication::new("Test"); + app.initialize(std::env::args()); + + assert!(app.get_name() == "Test"); + + app.deinitialize(); + } + + #[test] + fn create_graphics_application() { + let mut app = GraphicsApplication::new("Test"); + app.initialize(std::env::args()); + + assert!(app.get_name() == "Test"); + + let start_time = std::time::Instant::now(); + + while !app.application.close { + app.tick(); + + println!("Tick!"); + + if start_time.elapsed().as_secs() > 1 { + app.close(); + } + } + + app.deinitialize(); + } +} \ No newline at end of file diff --git a/src/beshader_compiler.rs b/src/beshader_compiler.rs new file mode 100644 index 00000000..5f1a9c71 --- /dev/null +++ b/src/beshader_compiler.rs @@ -0,0 +1,431 @@ +//! The beshader_compiler module implements a compiler for the beshader language. +//! The beshader language is a simple, Rust-like language that is used to describe shaders. +//! This module relies on the [`shader_generator`](crate::shader_generator) module to generate the actual shader code. +//! +//! # Example beShader +//! +//! ```glsl +//! struct Light { +//! position: vec3, +//! color: vec3, +//! } +//! +//! fn main() -> void { +//! gl_Position = vec4(0.0, 0.0, 0.0, 1.0); +//! } +//! ``` + +fn tokenize(source: &str) -> Vec { + let interrupt = |c: char| -> bool { + return c.is_whitespace(); + }; + + let can_sequence_continue = |sequence: &str, c: char| -> bool { + if sequence.len() == 0 { return true; } + + let last = sequence.chars().last().unwrap(); + + if last.is_alphabetic() { + return c.is_alphanumeric() || c == '_'; + } else if last.is_numeric() { + return c.is_numeric() || c == '.'; + } else if last == '.' { + return c.is_numeric(); + } else if last == '_' { + return c.is_alphanumeric() || c == '_'; + } else if last == '-' && c == '>' { + return true; + } else { + return false; + } + }; + + let mut tokens = Vec::new(); + let mut chars = source.chars(); + let mut iterator = chars.next(); + + 'outer: loop { + let mut token = String::new(); + + 'inner: loop { + match iterator { + Some(c) => { + if interrupt(c) { + iterator = chars.next(); + break 'inner; + } else if can_sequence_continue(&token, c) { + token.push(c); + iterator = chars.next(); + } else { + break 'inner; + } + }, + None => { + if token.len() > 0 { + tokens.push(token); + } + + break 'outer; + }, + } + } + + if token.len() > 0 { + tokens.push(token); + } + } + + return tokens; +} + +struct Node { + class: String, + name: String, + children: Vec, + properties: std::collections::HashMap>, +} + +enum ParsingFailReasons { + /// The parser does not handle this type of syntax. + NotMine, + /// The parser started handling a sequence of tokens, but it encountered a syntax error. + BadSyntax, +} + +type ParsingResult<'a> = Result<(Node, std::slice::Iter<'a, String>), ParsingFailReasons>; + +fn parse_macro(iterator: std::slice::Iter<'_, String>) -> ParsingResult { + let mut iter = iterator; + + let hash = iter.next().unwrap(); + + if hash != "#" { return Err(ParsingFailReasons::NotMine); } + + let square_bracket = iter.next().unwrap(); + + if square_bracket != "[" { return Err(ParsingFailReasons::NotMine); } + + let name = iter.next().unwrap(); + + if !name.chars().next().unwrap().is_alphabetic() { return Err(ParsingFailReasons::BadSyntax); } + + let close_square_bracket = iter.next().unwrap(); + + if close_square_bracket != "]" { return Err(ParsingFailReasons::BadSyntax); } + + let root_node = Node { class: "macro".to_owned(), name: name.to_owned(), children: Vec::new(), properties: std::collections::HashMap::new() }; + + return Ok((root_node, iter)); +} + +fn parse_struct(iterator: std::slice::Iter<'_, String>) -> ParsingResult { + let mut root_node = Node { class: "struct".to_owned(), name: String::new(), children: Vec::new(), properties: std::collections::HashMap::new() }; + + let mut iter = iterator; + + let name = iter.next().unwrap(); + + if !name.chars().next().unwrap().is_alphabetic() { return Err(ParsingFailReasons::NotMine); } + + let colon = iter.next().unwrap(); + + if colon != ":" { return Err(ParsingFailReasons::NotMine); } + + let struct_token = iter.next().unwrap(); + + if struct_token != "struct" { return Err(ParsingFailReasons::NotMine); } + + root_node.name = name.to_owned(); + + let open_brace = iter.next().unwrap(); + + if open_brace != "{" { return Err(ParsingFailReasons::BadSyntax); } + + let mut current_node = &mut root_node; + + 'field: while let Some(v) = iter.next() { + if v == "}" { + break; + } else if v == "," { + continue; + } + + let colon = iter.next().unwrap(); + + if colon != ":" { return Err(ParsingFailReasons::BadSyntax); } + + let type_name = iter.next().unwrap(); + + if !type_name.chars().next().unwrap().is_alphabetic() { return Err(ParsingFailReasons::BadSyntax); } + + root_node.children.push(Node { class: "field".to_owned(), name: v.to_owned(), children: Vec::new(), properties: std::collections::HashMap::new() }); + } + + return Ok((root_node, iter)); +} + +fn parse_statement(iterator: std::slice::Iter<'_, String>) -> ParsingResult { + let mut root_node = Node { class: "statement".to_owned(), name: String::new(), children: Vec::new(), properties: std::collections::HashMap::new() }; + + let mut iter = iterator; + + while let Some(v) = iter.next() { + if v == ";" { + break; + } + + dbg!(&v); + + root_node.children.push(Node { class: "expression".to_owned(), name: v.to_owned(), children: Vec::new(), properties: std::collections::HashMap::new() }); + } + + return Ok((root_node, iter)); +} + +fn parse_function(iterator: std::slice::Iter<'_, String>) -> ParsingResult { + let mut root_node = Node { class: "function".to_owned(), name: String::new(), children: Vec::new(), properties: std::collections::HashMap::new() }; + + let mut iter = iterator; + + let name = iter.next().unwrap(); + + if !name.chars().next().unwrap().is_alphabetic() { + return Err(ParsingFailReasons::NotMine); + } + + root_node.name = name.to_owned(); + + let colon = iter.next().unwrap(); + + if colon != ":" { + return Err(ParsingFailReasons::NotMine); + } + + let fn_token = iter.next().unwrap(); + + if fn_token != "fn" { return Err(ParsingFailReasons::NotMine); } + + let open_brace = iter.next().unwrap(); + + if open_brace != "(" { + return Err(ParsingFailReasons::BadSyntax); + } + + let close_brace = iter.next().unwrap(); + + if close_brace != ")" { + return Err(ParsingFailReasons::BadSyntax); + } + + let arrow = iter.next().unwrap(); + + if arrow != "->" { + return Err(ParsingFailReasons::BadSyntax); + } + + let return_type = iter.next().unwrap(); + + if !return_type.chars().next().unwrap().is_alphabetic() { + return Err(ParsingFailReasons::BadSyntax); + } + + root_node.properties.insert("return_type".to_owned(), vec![Node { class: "type".to_owned(), name: return_type.to_owned(), children: Vec::new(), properties: std::collections::HashMap::new() }]); + + let open_brace = iter.next().unwrap(); + + if open_brace != "{" { + return Err(ParsingFailReasons::BadSyntax); + } + + loop { + if let Ok(r) = parse_statement(iter.clone()) { + iter = r.1; + root_node.children.push(r.0); + } else { + return Err(ParsingFailReasons::BadSyntax); + } + + // check if iter is close brace + if iter.clone().peekable().peek().unwrap().as_str() == "}" { + iter.next(); + break; + } + } + + return Ok((root_node, iter)); +} + +fn parse(tokens: Vec) -> Result { + let mut root_node = Node { class: "root".to_owned(), name: "root".to_owned(), children: Vec::new(), properties: std::collections::HashMap::new() }; + + let mut iter = tokens.iter(); + + loop { + let result; + + if let Ok(r) = parse_struct(iter.clone()) { + result = r; + } else if let Ok(r) = parse_function(iter.clone()) { + result = r; + } else if let Ok(r) = parse_macro(iter.clone()) { + iter = r.1; + continue; + //result = r; + } else { + return Err(()); // No parser could handle the expression. + } + + root_node.children.push(result.0); + + iter = result.1; + + if iter.len() == 0 { + break; + } + } + + return Ok(root_node); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tokenization() { + let source = "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }"; + let tokens = tokenize(source); + assert_eq!(tokens, vec!["void", "main", "(", ")", "{", "gl_Position", "=", "vec4", "(", "0.0", ",", "0.0", ",", "0.0", ",", "1.0", ")", ";", "}"]); + } + + #[test] + fn test_tokenization2() { + let source = "fn main() -> void { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }"; + let tokens = tokenize(source); + assert_eq!(tokens, vec!["fn", "main", "(", ")", "->", "void", "{", "gl_Position", "=", "vec4", "(", "0.0", ",", "0.0", ",", "0.0", ",", "1.0", ")", ";", "}"]); + } + + #[test] + fn test_tokenization3() { + let source = "struct Light { position: vec3, color: vec3, data: Data, array: [u8; 4] };"; + let tokens = tokenize(source); + assert_eq!(tokens, vec!["struct", "Light", "{", "position", ":", "vec3", ",", "color", ":", "vec3", ",", "data", ":", "Data", "<", "int", ">", ",", "array", ":", "[", "u8", ";", "4", "]", "}", ";"]); + } + + #[test] + fn test_parse_struct() { + let source = " +Light: struct { + position: vec3, + color: vec3 +}"; + + let tokens = tokenize(source); + let nodes = parse(tokens); + + assert_eq!(nodes.is_ok(), true); + + let root_node = nodes.unwrap(); + + assert_eq!(&root_node.class, "root"); + assert_eq!(&root_node.name, "root"); + assert_eq!(root_node.children.len(), 1); + + let struct_node = &root_node.children[0]; + + assert_eq!(&struct_node.class, "struct"); + assert_eq!(&struct_node.name, "Light"); + assert_eq!(struct_node.children.len(), 2); + + let position_node = &struct_node.children[0]; + + assert_eq!(&position_node.class, "field"); + assert_eq!(&position_node.name, "position"); + assert_eq!(position_node.children.len(), 0); + + let color_node = &struct_node.children[1]; + + assert_eq!(&color_node.class, "field"); + assert_eq!(&color_node.name, "color"); + assert_eq!(color_node.children.len(), 0); + } + + #[test] + fn test_parse_function() { + let source = " +main: fn () -> void { + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); +}"; + + let tokens = tokenize(source); + let nodes = parse(tokens); + + assert_eq!(nodes.is_ok(), true); + + let root_node = nodes.unwrap(); + + assert_eq!(&root_node.class, "root"); + assert_eq!(&root_node.name, "root"); + assert_eq!(root_node.children.len(), 1); + + let function_node = &root_node.children[0]; + + assert_eq!(&function_node.class, "function"); + assert_eq!(&function_node.name, "main"); + assert_eq!(function_node.children.len(), 1); + + let statement_node = &function_node.children[0]; + + assert_eq!(&statement_node.class, "statement"); + assert_eq!(&statement_node.name, ""); + assert_eq!(statement_node.children.len(), 12); + } + + #[test] + fn test_parse_struct_and_function() { + let source = " +Light: struct { + position: vec3, + color: vec3 +} + +#[vertex] +main: fn () -> void { + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); +}"; + + let tokens = tokenize(source); + let nodes = parse(tokens); + + assert_eq!(nodes.is_ok(), true); + + let root_node = nodes.unwrap(); + + assert_eq!(&root_node.class, "root"); + assert_eq!(&root_node.name, "root"); + assert_eq!(root_node.children.len(), 2); + + let struct_node = &root_node.children[0]; + + assert_eq!(&struct_node.class, "struct"); + assert_eq!(&struct_node.name, "Light"); + assert_eq!(struct_node.children.len(), 2); + + let position_node = &struct_node.children[0]; + + assert_eq!(&position_node.class, "field"); + assert_eq!(&position_node.name, "position"); + + let color_node = &struct_node.children[1]; + + assert_eq!(&color_node.class, "field"); + assert_eq!(&color_node.name, "color"); + + let function_node = &root_node.children[1]; + + assert_eq!(&function_node.class, "function"); + assert_eq!(&function_node.name, "main"); + assert_eq!(function_node.children.len(), 2); + } +} \ No newline at end of file diff --git a/src/executor.rs b/src/executor.rs new file mode 100644 index 00000000..2b478871 --- /dev/null +++ b/src/executor.rs @@ -0,0 +1,178 @@ +struct Dispatcher { + sep: std::sync::Mutex<(Executor, Spawner)>, +} + +pub struct TimerFuture { + shared_state: std::sync::Arc>, +} + +/// Shared state between the future and the waiting thread +struct SharedState { + /// Whether or not the sleep time has elapsed + completed: bool, + + /// The waker for the task that `TimerFuture` is running on. + /// The thread can use this after setting `completed = true` to tell + /// `TimerFuture`'s task to wake up, see that `completed = true`, and + /// move forward. + waker: Option, +} + +impl futures::Future for TimerFuture { + type Output = (); + fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll { + // Look at the shared state to see if the timer has already completed. + let mut shared_state = self.shared_state.lock().unwrap(); + if shared_state.completed { + std::task::Poll::Ready(()) + } else { + // Set waker so that the thread can wake up the current task + // when the timer has completed, ensuring that the future is polled + // again and sees that `completed = true`. + // + // It's tempting to do this once rather than repeatedly cloning + // the waker each time. However, the `TimerFuture` can move between + // tasks on the executor, which could cause a stale waker pointing + // to the wrong task, preventing `TimerFuture` from waking up + // correctly. + // + // N.B. it's possible to check for this using the `Waker::will_wake` + // function, but we omit that here to keep things simple. + shared_state.waker = Some(cx.waker().clone()); + std::task::Poll::Pending + } + } +} + +impl TimerFuture { + /// Create a new `TimerFuture` which will complete after the provided + /// timeout. + pub fn new(duration: std::time::Duration) -> Self { + let shared_state = std::sync::Arc::new(std::sync::Mutex::new(SharedState { + completed: false, + waker: None, + })); + + // Spawn the new thread + let thread_shared_state = shared_state.clone(); + + std::thread::spawn(move || { + std::thread::sleep(duration); + let mut shared_state = thread_shared_state.lock().unwrap(); + // Signal that the timer has completed and wake up the last + // task on which the future was polled, if one exists. + shared_state.completed = true; + if let Some(waker) = shared_state.waker.take() { + waker.wake() // Get the executor to poll the future again. + } + }); + + TimerFuture { shared_state } + } +} + +/// Task executor that receives tasks off of a channel and executes them. +pub struct Executor { + /// Thread safe queue of finished tasks. + ready_queue: std::sync::mpsc::Receiver>, +} + +/// Spawner spawns new futures onto the task channel. +#[derive(Clone)] +pub struct Spawner { + task_sender: std::sync::mpsc::SyncSender>, +} + +/// A future that can reschedule itself to be polled by an executor. +struct Task { + future: std::sync::Mutex>>, + task_sender: std::sync::mpsc::SyncSender>, +} + +pub fn new_executor_and_spawner() -> (Executor, Spawner) { + // Maximum number of tasks to allow queueing in the channel at once. + const MAX_QUEUED_TASKS: usize = 10_000; + + let (task_sender, ready_queue) = std::sync::mpsc::sync_channel(MAX_QUEUED_TASKS); + (Executor { ready_queue }, Spawner { task_sender }) +} + +use futures::FutureExt; +// The timer we wrote in the previous section: +//use timer_future::TimerFuture; + +impl Spawner { + /// Spawn a future onto the task channel. + pub fn spawn(&self, future: impl std::future::Future + Send + 'static) { + let future = future.boxed(); + let task = std::sync::Arc::new(Task { + future: std::sync::Mutex::new(Some(future)), + task_sender: self.task_sender.clone(), + }); + self.task_sender.send(task).expect("too many tasks queued"); + } +} + +impl futures::task::ArcWake for Task { + fn wake_by_ref(arc_self: &std::sync::Arc) { + let cloned = arc_self.clone(); + arc_self.task_sender.send(cloned).expect("too many tasks queued"); + } +} + +impl Executor { + fn run(&self) { + while let Ok(task) = self.ready_queue.recv_timeout(std::time::Duration::from_millis(16)) { + let mut future_slot = task.future.lock().unwrap(); + if let Some(mut future) = future_slot.take() { + let waker = futures::task::waker_ref(&task); + let context = &mut futures::task::Context::from_waker(&*waker); + if let std::task::Poll::Pending = future.as_mut().poll(context) { + *future_slot = Some(future); + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let (executor, spawner) = new_executor_and_spawner(); + + spawner.spawn(async { + println!("howdy!"); + // Wait for our timer future to complete after two seconds. + TimerFuture::new(std::time::Duration::new(2, 0)).await; + println!("done!"); + }); + + drop(spawner); + + executor.run(); + } + + // #[test] + // fn test_systems_as_parameters() { + // let mut dispatcher = Dispatcher::new(); + + // let test_system = TestSystem::new(); + + // let system_handle = dispatcher.add_system(test_system); + + // async fn task(orchestrator: &Orchestrator<'static>) { + // // let test_system = orchestrator.get_system::(system_handle).await; + + // // let test_system = test_system.lock().unwrap(); + + // // assert_eq!(test_system.get_value(), 0); + // }; + + // dispatcher.execute_task_2(task); + + // dispatcher.update(); + // } +} \ No newline at end of file diff --git a/src/file_tracker.rs b/src/file_tracker.rs new file mode 100644 index 00000000..118ffe5b --- /dev/null +++ b/src/file_tracker.rs @@ -0,0 +1,116 @@ +//! The file tracker implements an easy to use file tracking system. +//! Directories can be watched during runtime and the file tracker will emit events when files are created, modified or deleted. Events will also be emitted for files that were changed when the watcher was offline. + +use std::path::Path; + +use notify::{Watcher, RecursiveMode}; +use polodb_core; + +pub struct FileTracker { + db: polodb_core::Database, + watcher: notify::RecommendedWatcher, + rx: std::sync::mpsc::Receiver>, +} + +impl FileTracker { + pub fn new() -> FileTracker { + let db = polodb_core::Database::open_file("files.db").unwrap(); + + let (tx, rx) = std::sync::mpsc::channel(); + + let mut watcher = notify::RecommendedWatcher::new(tx, notify::Config::default()).unwrap(); + + let col = db.collection::("files"); + + for doc in col.find(None).unwrap() { + let d = doc.unwrap(); + let path = d.get_str("path").unwrap(); + let path = Path::new(path); + + if !path.exists() { + // TODO: emit delete event + // TODO: Delete document + continue; + } + + let metadata = std::fs::metadata(path).unwrap(); + let time = metadata.modified().unwrap(); + let _m = time.duration_since(std::time::UNIX_EPOCH).unwrap().as_millis(); + + dbg!(&d); + dbg!(_m as u64); + + if d.get_i64("last_modified").unwrap() as u64 != _m as u64 { + println!("File changed: {:?}", path); + + db.collection::("files").update_one(polodb_core::bson::doc! { + "path": path.to_str().unwrap(), + }, polodb_core::bson::doc! { + "$set": { + "last_modified": _m as i64, + } + }).unwrap(); + } + + watcher.watch(path, RecursiveMode::Recursive); + } + + FileTracker { + db, + watcher, + rx, + } + } + + pub fn watch(&mut self, path: &Path) -> bool { + let result = self.watcher.watch(path, RecursiveMode::Recursive); + + if result.is_err() { + println!("Failed to watch path: {:?}", path); + return false; + } + + let metadata = std::fs::metadata(path).unwrap(); + let time = metadata.modified().unwrap(); + let _m = time.duration_since(std::time::UNIX_EPOCH).unwrap().as_millis(); + + let res = self.db.collection::("files").find_one(polodb_core::bson::doc! { "path": path.to_str().unwrap(),}).unwrap(); + + if !res.is_some() { + self.db.collection("files").insert_one(polodb_core::bson::doc! { + "path": path.to_str().unwrap(), + "last_modified": _m as i64, + }).unwrap(); + } + + true + } + + pub fn unwatch(&mut self, path: &Path) -> bool { + let result = self.watcher.unwatch(path); + + if result.is_err() { + return false; + } + + // self.db.collection("files").delete_one(polodb_core::bson::doc! { + // "path": path.to_str().unwrap(), + // }).unwrap(); + + true + } + + pub fn poll(&self) -> () { + let mut events = Vec::new(); + + loop { + match self.rx.try_recv() { + Ok(event) => { + dbg!(&event); + events.push(event); + } + Err(_) => break, + } + } + } +} \ No newline at end of file diff --git a/src/gdeflate.rs b/src/gdeflate.rs new file mode 100644 index 00000000..a955fd1c --- /dev/null +++ b/src/gdeflate.rs @@ -0,0 +1,1228 @@ +static MIN_BLOCK_LENGTH: usize = 10000; +static GDEFLATE_PAGE_SIZE: usize = 65536; +static OUTPUT_END_PADDING: usize = 8; +const NUM_STREAMS: usize = 32; +static BITS_PER_PACKET: usize = 32; + +static SUPPORT_NEAR_OPTIMAL_PARSING: bool = true; + +static MATCHFINDER_MEM_ALIGNMENT: usize = 32; + +struct Compressor { + libdeflater_compressor: libdeflater::Compressor, + compression_level: u32, + method: u32, + min_size_to_compress: usize, + max_search_depth: usize, + nice_match_length: usize, + num_optim_passes: usize, +} + +impl Compressor { + pub fn new(compression_level: u32) -> Self { + Compressor { + libdeflater_compressor: libdeflater::Compressor::new(libdeflater::CompressionLvl::new(compression_level as i32).unwrap()), + compression_level, + method: 0, + min_size_to_compress: 0, + max_search_depth: 0, + nice_match_length: 0, + num_optim_passes: 0, + } + } +} + +fn libdeflate_alloc_gdeflate_compressor(compression_level: u32) -> Compressor { + if compression_level < 0 || compression_level > 12 { panic!() } + + let size = if SUPPORT_NEAR_OPTIMAL_PARSING { + if compression_level >= 8 { + 1 + } else { + if compression_level >= 1 { + 0 + } else { + 0 + } + } + } else { + if compression_level >= 1 { + 0 + } else { + 0 + } + }; + + let mut c = Compressor::new(compression_level); + + /* + * The higher the compression level, the more we should bother trying to + * compress very small inputs. + */ + c.min_size_to_compress = 56 as usize - (compression_level as usize * 4 as usize); + + let method; + let max_search_depth; + let nice_match_length; + let num_optim_passes; + + match compression_level { + 0 => { + method = 0; + max_search_depth = 0; + nice_match_length = 0; + num_optim_passes = 0; + }, + 1 => { + method = 1; + max_search_depth = 2; + nice_match_length = 8; + num_optim_passes = 0; + }, + 2 => { + method = 1; + max_search_depth = 6; + nice_match_length = 10; + num_optim_passes = 0; + }, + 3 => { + method = 1; + max_search_depth = 12; + nice_match_length = 14; + num_optim_passes = 0; + }, + 4 => { + method = 1; + max_search_depth = 24; + nice_match_length = 24; + num_optim_passes = 0; + }, + 5 => { + method = 2; + max_search_depth = 20; + nice_match_length = 30; + num_optim_passes = 0; + }, + 6 => { + method = 2; + max_search_depth = 40; + nice_match_length = 65; + num_optim_passes = 0; + }, + 7 => { + method = 2; + max_search_depth = 100; + nice_match_length = 130; + num_optim_passes = 0; + }, + 8 => { + method = 3; // Near optimal + max_search_depth = 12; + nice_match_length = 20; + num_optim_passes = 1; + }, + 9 => { + method = 3; // Near optimal + max_search_depth = 16; + nice_match_length = 26; + num_optim_passes = 2; + }, + 10 => { + method = 3; // Near optimal + max_search_depth = 30; + nice_match_length = 50; + num_optim_passes = 2; + }, + 11 => { + method = 3; // Near optimal + max_search_depth = 60; + nice_match_length = 80; + num_optim_passes = 3; + }, + _ => { + method = 3; // Near optimal + max_search_depth = 100; + nice_match_length = 133; + num_optim_passes = 4; + } + } + + c.method = method; + c.max_search_depth = max_search_depth; + c.nice_match_length = nice_match_length; + c.num_optim_passes = num_optim_passes; + + // deflate_init_offset_slot_fast(c); + // deflate_init_static_codes(c); + // deflate_init_length_slot(); + + return c; +} + +/// Returns the maximum number of bytes that libdeflate_gdeflate_compress() may write to out_pages. +/// This is an upper bound on the size of the compressed data, but the actual size may be smaller. +/// The caller must ensure that out_pages is large enough to hold the compressed data. +/// This number WILL be larger or equal to the size of the uncompressed data. +fn libdeflate_gdeflate_compress_bound(_compressor: &Compressor, in_nbytes: usize, out_npages: &mut usize) -> usize { + /* + * The worst case is all uncompressed blocks where one block has length + * <= MIN_BLOCK_LENGTH and the others have length MIN_BLOCK_LENGTH. + * Each uncompressed block has 5 bytes of overhead: 1 for BFINAL, BTYPE, + * and alignment to a byte boundary; 2 for LEN; and 2 for NLEN. + */ + let max_num_blocks = std::cmp::max(std::primitive::usize::div_ceil(in_nbytes, MIN_BLOCK_LENGTH), 1); + let npages = in_nbytes.div_ceil(GDEFLATE_PAGE_SIZE); + + *out_npages = npages; + + ((5 * max_num_blocks) + GDEFLATE_PAGE_SIZE + 1 + OUTPUT_END_PADDING + (NUM_STREAMS * BITS_PER_PACKET) / 8) * npages +} + +fn gdeflate_compress(c: &mut Compressor, in_bytes: &[u8], out_pages: &[&[u8]]) -> usize { + let mut out_nbytes = 0; + let mut npages = out_pages.len(); + let upper_bound = libdeflate_gdeflate_compress_bound(c, in_bytes.len(), &mut npages); + let page_upper_bound = upper_bound / npages; + + if out_pages.len() != npages { return 0 as usize } + + for page in 0..npages { + let comp_page_nbytes; + let page_nbytes = if in_bytes.len() > GDEFLATE_PAGE_SIZE { GDEFLATE_PAGE_SIZE } else { in_bytes.len() }; + + if out_pages[page].len() < page_upper_bound { return 0 as usize } + + let mut out_deflate_data = Vec::with_capacity(page_upper_bound); + + unsafe { + out_deflate_data.set_len(page_upper_bound); + } + + comp_page_nbytes = match c.method { + 0 => { // No compression + return 0 as usize; + }, + 1 => { // Greedy matching + c.libdeflater_compressor.deflate_compress(&in_bytes[page*page_nbytes..page*page_nbytes+page_nbytes], out_deflate_data.as_mut_slice()).unwrap() + }, + 2 => { // Lazy matching + c.libdeflater_compressor.deflate_compress(&in_bytes[page*page_nbytes..page*page_nbytes+page_nbytes], out_deflate_data.as_mut_slice()).unwrap() + }, + 3 => { // Near optimal + c.libdeflater_compressor.deflate_compress(&in_bytes[page*page_nbytes..page*page_nbytes+page_nbytes], out_deflate_data.as_mut_slice()).unwrap() + }, + _ => { return 0 as usize; } + }; + + //comp_page_nbytes = (*c->impl)(c, in_bytes, page_nbytes, out_pages[page].data, page_upper_bound); + + //out_pages[page].len() = comp_page_nbytes; + + /* Page did not fit - bail out. */ + if comp_page_nbytes == 0 { return 0 as usize } + + out_nbytes += comp_page_nbytes; + } + + out_nbytes +} + +/* + * The main DEFLATE decompressor structure. Since this implementation only + * supports full buffer decompression, this structure does not store the entire + * decompression state, but rather only some arrays that are too large to + * comfortably allocate on the stack. + */ + + +const DEFLATE_MAX_NUM_SYMS: usize = 288; +const LITLEN_ENOUGH: usize = 1334; +const PRECODE_ENOUGH: usize = 128; + +struct L { + lens: [u8; DEFLATE_NUM_LITLEN_SYMS + DEFLATE_NUM_OFFSET_SYMS + DEFLATE_MAX_LENS_OVERRUN], + precode_decode_table: [u32; PRECODE_ENOUGH], +} + +struct U { + precode_lens: [u8; DEFLATE_NUM_PRECODE_SYMS], + l: L, + litlen_decode_table: [u32; LITLEN_ENOUGH], +} + +struct Decompressor { + libdefalter_decompressor: libdeflater::Decompressor, + offset_decode_table: [u32; OFFSET_ENOUGH], + /* used only during build_decode_table() */ + sorted_syms: [u16; DEFLATE_MAX_NUM_SYMS], + u: U, + static_codes_loaded: bool, +} + +/* + * GDeflate deferred copy state structure. + */ +#[derive(Copy, Clone)] +struct gdeflate_deferred_copy { + length: u32, + out_next: *mut u32, +} + +/* + * GDeflate state structure. + */ +struct gdeflate_state { + bitbuf: [u64; NUM_STREAMS], + bitsleft: [u32; NUM_STREAMS], + copies: [gdeflate_deferred_copy; NUM_STREAMS], + idx: usize, +} + +impl gdeflate_state { + pub fn new() -> Self { + gdeflate_state { + bitbuf: [0; NUM_STREAMS], + bitsleft: [0; NUM_STREAMS], + copies: [gdeflate_deferred_copy { length: 0, out_next: 0 as *mut u32 }; NUM_STREAMS], + idx: 0, + } + } + + /* + * Does the bitbuffer variable currently contain at least 'n' bits? + */ + pub fn HAVE_BITS(&self, n: u32) -> bool { self.bitsleft[self.idx as usize] >= n } + + /* + * Does the bitbuffer variable currently contain at least 'n' bits? + */ + pub fn BITS(&self, n: usize) -> usize { (self.bitbuf[self.idx as usize] & (((1u64 << n) - 1) as u64)) as usize } + + /* + * Remove the next 'n' bits from the bitbuffer variable. + */ + pub fn REMOVE_BITS(&mut self, n: usize) -> usize { self.bitbuf[self.idx as usize] >>= n; self.bitsleft[self.idx as usize] -= n as u32; self.bitsleft[self.idx as usize] as usize } + + /* + * Remove and return the next 'n' bits from the bitbuffer variable. + */ + pub fn POP_BITS(&mut self, n: usize) -> usize { let tmp32 = self.BITS(n); self.REMOVE_BITS(n); tmp32 } + + /* + * Reset GDeflate stream index. + */ + fn RESET(&mut self) { self.idx = 0 } + + /* + * Load more bits from the input buffer until the specified number of bits is + * present in the bitbuffer variable. 'n' cannot be too large; see MAX_ENSURE + * and CAN_ENSURE(). + */ + fn ENSURE_BITS(&self, n: u32, in_next: &mut *const u8) { + if !self.HAVE_BITS(n) { + self.bitbuf[self.idx as usize] |= (unsafe { *(*in_next as *const u32 ) } as u64) << self.bitsleft[self.idx as usize]; + *in_next = unsafe { (*in_next).add(BITS_PER_PACKET/8) }; + self.bitsleft[self.idx as usize] += BITS_PER_PACKET as u32; + } + } + + /* + * Setup copy advance method depending on a number of streams used. + */ + fn ADVANCE_COPIES(&self, is_copy: u32) -> u32 { + assert!(NUM_STREAMS == 32); + is_copy.rotate_right(1) + } + + /* + * Advance GDeflate stream index. Refill bits if necessary. + */ + fn ADVANCE(&mut self, is_copy: u32, in_next: &mut *const u8) { + self.ENSURE_BITS(LOW_WATERMARK_BITS, in_next); + self.idx = (self.idx + 1) % NUM_STREAMS as usize; + self.ADVANCE_COPIES(is_copy); + } +} + +const LOW_WATERMARK_BITS: u32 = 32; +const HUFFDEC_SUBTABLE_POINTER: usize = 0x80000000; +const OFFSET_TABLEBITS: usize = 8; +const HUFFDEC_RESULT_SHIFT: u32 = 8; +const HUFFDEC_LENGTH_MASK: usize = 0xFF; +const HUFFDEC_EXTRA_OFFSET_BITS_SHIFT: usize = 16; +const HUFFDEC_OFFSET_BASE_MASK: usize = (1 << HUFFDEC_EXTRA_OFFSET_BITS_SHIFT) - 1; +const OFFSET_ENOUGH: usize = 402; + +fn repeat_byte(b: u8) -> u64 { + let mut v: u64; + + v = b as u64; + v |= v << 8; + v |= v << 16; + v |= v << 32; // This only works on 64 bits. + return v; +} + +#[inline(always)] +fn do_copy(decompressor: &mut Decompressor, s: &mut gdeflate_state, out: &mut [u8], out_end: *mut u8) -> libdeflater::DecompressionError { + let mut entry: usize; + let mut offset: usize; + let mut src: *const u8; + let mut dst: *mut u8; + let mut tmp32: u32; + let length = s.copies[s.idx as usize].length; + let out_next = s.copies[s.idx as usize].out_next as *mut u8; + + entry = decompressor.offset_decode_table[s.BITS(OFFSET_TABLEBITS) as usize] as usize; + + if entry & HUFFDEC_SUBTABLE_POINTER != 0 { + s.REMOVE_BITS(OFFSET_TABLEBITS); + entry = decompressor.offset_decode_table[(((entry >> HUFFDEC_RESULT_SHIFT) & 0xFFFF) + s.BITS(entry & HUFFDEC_LENGTH_MASK)) as usize] as usize; + } + + s.REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK); + + entry >>= HUFFDEC_RESULT_SHIFT; + offset = (entry & HUFFDEC_OFFSET_BASE_MASK) + s.POP_BITS(entry >> HUFFDEC_EXTRA_OFFSET_BITS_SHIFT); + + unsafe { + src = out_next.offset(-(offset as isize)); + } + + dst = out_next; + + let unaligned_access_is_fast = true; // Assuming unaligned access is fast in Rust + let wordbytes = std::mem::size_of::(); + + if unaligned_access_is_fast && unsafe { out_end.offset_from(out_next) } >= wordbytes as isize && length as usize >= wordbytes { + if offset >= wordbytes { + unsafe { + while dst < out_next.offset(-(wordbytes as isize)) { + //copy_word_unaligned(src, dst); + *(dst as *mut u64) = *(src as *const u64); + src = src.offset(wordbytes as isize); + dst = dst.offset(wordbytes as isize); + } + while dst < out_next { + *dst = *src; + src = src.offset(1); + dst = dst.offset(1); + } + } + } else if offset == 1 { + unsafe { + let v = repeat_byte(*src); + while dst < out_next.offset(-(wordbytes as isize)) { + //store_word_unaligned(v, dst); + *(dst as *mut u64) = v; + dst = dst.offset(wordbytes as isize); + } + while dst < out_next { + *dst = v as u8; + dst = dst.offset(1); + } + } + } else { + unsafe { + *dst = *src; + dst = dst.offset(1); + src = src.offset(1); + *dst = *src; + dst = dst.offset(1); + src = src.offset(1); + while dst < out_next { + *dst = *src; + dst = dst.offset(1); + src = src.offset(1); + } + } + } + } else { + unsafe { + *dst = *src; + dst = dst.offset(1); + src = src.offset(1); + *dst = *src; + dst = dst.offset(1); + src = src.offset(1); + while dst < out_next { + *dst = *src; + dst = dst.offset(1); + src = src.offset(1); + } + } + } + + libdeflater::DecompressionError::BadData +} + +const DEFLATE_NUM_PRECODE_SYMS: usize = 19; +const DEFLATE_NUM_LITLEN_SYMS: usize = 288; +const DEFLATE_NUM_OFFSET_SYMS: usize = 32; +const DEFLATE_MAX_PRE_CODEWORD_LEN: usize = 7; +const PRECODE_TABLEBITS: usize = 7; +const DEFLATE_MAX_LENS_OVERRUN: usize = 137; +const DEFLATE_BLOCKTYPE_UNCOMPRESSED: usize = 0; +const DEFLATE_BLOCKTYPE_STATIC_HUFFMAN: usize = 1; +const DEFLATE_BLOCKTYPE_DYNAMIC_HUFFMAN: usize = 2; +const HUFFDEC_LENGTH_BASE_SHIFT: u32 = 8; +const HUFFDEC_LITERAL: usize = 0x40000000; +const HUFFDEC_EXTRA_LENGTH_BITS_MASK: usize = 0xFF; +const LITLEN_TABLEBITS: usize = 10; +const HUFFDEC_END_OF_BLOCK_LENGTH: usize = 0; + +/* Shift a decode result into its position in the decode table entry. */ +fn HUFFDEC_RESULT_ENTRY(result: usize) -> u32 { (result as u32) << HUFFDEC_RESULT_SHIFT } + +/* The decode result for each precode symbol. There is no special optimization + * for the precode; the decode result is simply the symbol value. */ +static precode_decode_results: [u32; DEFLATE_NUM_PRECODE_SYMS] = [ + HUFFDEC_RESULT_ENTRY(0) , HUFFDEC_RESULT_ENTRY(1) , HUFFDEC_RESULT_ENTRY(2) , HUFFDEC_RESULT_ENTRY(3) , + HUFFDEC_RESULT_ENTRY(4) , HUFFDEC_RESULT_ENTRY(5) , HUFFDEC_RESULT_ENTRY(6) , HUFFDEC_RESULT_ENTRY(7) , + HUFFDEC_RESULT_ENTRY(8) , HUFFDEC_RESULT_ENTRY(9) , HUFFDEC_RESULT_ENTRY(10) , HUFFDEC_RESULT_ENTRY(11) , + HUFFDEC_RESULT_ENTRY(12) , HUFFDEC_RESULT_ENTRY(13) , HUFFDEC_RESULT_ENTRY(14) , HUFFDEC_RESULT_ENTRY(15) , + HUFFDEC_RESULT_ENTRY(16) , HUFFDEC_RESULT_ENTRY(17) , HUFFDEC_RESULT_ENTRY(18) , +]; + +/* + * Build a table for fast decoding of symbols from a Huffman code. As input, + * this function takes the codeword length of each symbol which may be used in + * the code. As output, it produces a decode table for the canonical Huffman + * code described by the codeword lengths. The decode table is built with the + * assumption that it will be indexed with "bit-reversed" codewords, where the + * low-order bit is the first bit of the codeword. This format is used for all + * Huffman codes in DEFLATE. + * + * @decode_table + * The array in which the decode table will be generated. This array must + * have sufficient length; see the definition of the ENOUGH numbers. + * @lens + * An array which provides, for each symbol, the length of the + * corresponding codeword in bits, or 0 if the symbol is unused. This may + * alias @decode_table, since nothing is written to @decode_table until all + * @lens have been consumed. All codeword lengths are assumed to be <= + * @max_codeword_len but are otherwise considered untrusted. If they do + * not form a valid Huffman code, then the decode table is not built and + * %false is returned. + * @num_syms + * The number of symbols in the code, including all unused symbols. + * @decode_results + * An array which provides, for each symbol, the actual value to store into + * the decode table. This value will be directly produced as the result of + * decoding that symbol, thereby moving the indirection out of the decode + * loop and into the table initialization. + * @table_bits + * The log base-2 of the number of main table entries to use. + * @max_codeword_len + * The maximum allowed codeword length for this Huffman code. + * Must be <= DEFLATE_MAX_CODEWORD_LEN. + * @sorted_syms + * A temporary array of length @num_syms. + * + * Returns %true if successful; %false if the codeword lengths do not form a + * valid Huffman code. + */ +fn build_decode_table(u32 decode_table[], const len_t lens[], const unsigned num_syms, const u32 decode_results[], const unsigned table_bits, const unsigned max_codeword_len, u16 *sorted_syms) -> bool +{ + unsigned len_counts[DEFLATE_MAX_CODEWORD_LEN + 1]; + unsigned offsets[DEFLATE_MAX_CODEWORD_LEN + 1]; + unsigned sym; /* current symbol */ + unsigned codeword; /* current codeword, bit-reversed */ + unsigned len; /* current codeword length in bits */ + unsigned count; /* num codewords remaining with this length */ + u32 codespace_used; /* codespace used out of '2^max_codeword_len' */ + unsigned cur_table_end; /* end index of current table */ + unsigned subtable_prefix; /* codeword prefix of current subtable */ + unsigned subtable_start; /* start index of current subtable */ + unsigned subtable_bits; /* log2 of current subtable length */ + + /* Count how many codewords have each length, including 0. */ + for (len = 0; len <= max_codeword_len; len++) + len_counts[len] = 0; + for (sym = 0; sym < num_syms; sym++) + len_counts[lens[sym]]++; + + /* + * Sort the symbols primarily by increasing codeword length and + * secondarily by increasing symbol value; or equivalently by their + * codewords in lexicographic order, since a canonical code is assumed. + * + * For efficiency, also compute 'codespace_used' in the same pass over + * 'len_counts[]' used to build 'offsets[]' for sorting. + */ + + /* Ensure that 'codespace_used' cannot overflow. */ + STATIC_ASSERT(sizeof(codespace_used) == 4); + STATIC_ASSERT(UINT32_MAX / (1U << (DEFLATE_MAX_CODEWORD_LEN - 1)) >= + DEFLATE_MAX_NUM_SYMS); + + offsets[0] = 0; + offsets[1] = len_counts[0]; + codespace_used = 0; + for (len = 1; len < max_codeword_len; len++) { + offsets[len + 1] = offsets[len] + len_counts[len]; + codespace_used = (codespace_used << 1) + len_counts[len]; + } + codespace_used = (codespace_used << 1) + len_counts[len]; + + for (sym = 0; sym < num_syms; sym++) + sorted_syms[offsets[lens[sym]]++] = sym; + + sorted_syms += offsets[0]; /* Skip unused symbols */ + + /* lens[] is done being used, so we can write to decode_table[] now. */ + + /* + * Check whether the lengths form a complete code (exactly fills the + * codespace), an incomplete code (doesn't fill the codespace), or an + * overfull code (overflows the codespace). A codeword of length 'n' + * uses proportion '1/(2^n)' of the codespace. An overfull code is + * nonsensical, so is considered invalid. An incomplete code is + * considered valid only in two specific cases; see below. + */ + + /* overfull code? */ + if (unlikely(codespace_used > (1U << max_codeword_len))) + return false; + + /* incomplete code? */ + if (unlikely(codespace_used < (1U << max_codeword_len))) { + u32 entry; + unsigned i; + + if (codespace_used == 0) { + /* + * An empty code is allowed. This can happen for the + * offset code in DEFLATE, since a dynamic Huffman block + * need not contain any matches. + */ + + /* sym=0, len=1 (arbitrary) */ + entry = decode_results[0] | 1; + } else { + /* + * Allow codes with a single used symbol, with codeword + * length 1. The DEFLATE RFC is unclear regarding this + * case. What zlib's decompressor does is permit this + * for the litlen and offset codes and assume the + * codeword is '0' rather than '1'. We do the same + * except we allow this for precodes too, since there's + * no convincing reason to treat the codes differently. + * We also assign both codewords '0' and '1' to the + * symbol to avoid having to handle '1' specially. + */ + if (codespace_used != (1U << (max_codeword_len - 1)) || + len_counts[1] != 1) + return false; + entry = decode_results[*sorted_syms] | 1; + } + /* + * Note: the decode table still must be fully initialized, in + * case the stream is malformed and contains bits from the part + * of the codespace the incomplete code doesn't use. + */ + for (i = 0; i < (1U << table_bits); i++) + decode_table[i] = entry; + return true; + } + + /* + * The lengths form a complete code. Now, enumerate the codewords in + * lexicographic order and fill the decode table entries for each one. + * + * First, process all codewords with len <= table_bits. Each one gets + * '2^(table_bits-len)' direct entries in the table. + * + * Since DEFLATE uses bit-reversed codewords, these entries aren't + * consecutive but rather are spaced '2^len' entries apart. This makes + * filling them naively somewhat awkward and inefficient, since strided + * stores are less cache-friendly and preclude the use of word or + * vector-at-a-time stores to fill multiple entries per instruction. + * + * To optimize this, we incrementally double the table size. When + * processing codewords with length 'len', the table is treated as + * having only '2^len' entries, so each codeword uses just one entry. + * Then, each time 'len' is incremented, the table size is doubled and + * the first half is copied to the second half. This significantly + * improves performance over naively doing strided stores. + * + * Note that some entries copied for each table doubling may not have + * been initialized yet, but it doesn't matter since they're guaranteed + * to be initialized later (because the Huffman code is complete). + */ + codeword = 0; + len = 1; + while ((count = len_counts[len]) == 0) + len++; + cur_table_end = 1U << len; + while (len <= table_bits) { + /* Process all 'count' codewords with length 'len' bits. */ + do { + unsigned bit; + + /* Fill the first entry for the current codeword. */ + decode_table[codeword] = + decode_results[*sorted_syms++] | len; + + if (codeword == cur_table_end - 1) { + /* Last codeword (all 1's) */ + for (; len < table_bits; len++) { + memcpy(&decode_table[cur_table_end], + decode_table, + cur_table_end * + sizeof(decode_table[0])); + cur_table_end <<= 1; + } + return true; + } + /* + * To advance to the lexicographically next codeword in + * the canonical code, the codeword must be incremented, + * then 0's must be appended to the codeword as needed + * to match the next codeword's length. + * + * Since the codeword is bit-reversed, appending 0's is + * a no-op. However, incrementing it is nontrivial. To + * do so efficiently, use the 'bsr' instruction to find + * the last (highest order) 0 bit in the codeword, set + * it, and clear any later (higher order) 1 bits. But + * 'bsr' actually finds the highest order 1 bit, so to + * use it first flip all bits in the codeword by XOR'ing + * it with (1U << len) - 1 == cur_table_end - 1. + */ + bit = 1U << bsr32(codeword ^ (cur_table_end - 1)); + codeword &= bit - 1; + codeword |= bit; + } while (--count); + + /* Advance to the next codeword length. */ + do { + if (++len <= table_bits) { + memcpy(&decode_table[cur_table_end], + decode_table, + cur_table_end * sizeof(decode_table[0])); + cur_table_end <<= 1; + } + } while ((count = len_counts[len]) == 0); + } + + /* Process codewords with len > table_bits. These require subtables. */ + cur_table_end = 1U << table_bits; + subtable_prefix = -1; + subtable_start = 0; + for (;;) { + u32 entry; + unsigned i; + unsigned stride; + unsigned bit; + + /* + * Start a new subtable if the first 'table_bits' bits of the + * codeword don't match the prefix of the current subtable. + */ + if ((codeword & ((1U << table_bits) - 1)) != subtable_prefix) { + subtable_prefix = (codeword & ((1U << table_bits) - 1)); + subtable_start = cur_table_end; + /* + * Calculate the subtable length. If the codeword has + * length 'table_bits + n', then the subtable needs + * '2^n' entries. But it may need more; if fewer than + * '2^n' codewords of length 'table_bits + n' remain, + * then the length will need to be incremented to bring + * in longer codewords until the subtable can be + * completely filled. Note that because the Huffman + * code is complete, it will always be possible to fill + * the subtable eventually. + */ + subtable_bits = len - table_bits; + codespace_used = count; + while (codespace_used < (1U << subtable_bits)) { + subtable_bits++; + codespace_used = (codespace_used << 1) + + len_counts[table_bits + subtable_bits]; + } + cur_table_end = subtable_start + (1U << subtable_bits); + + /* + * Create the entry that points from the main table to + * the subtable. This entry contains the index of the + * start of the subtable and the number of bits with + * which the subtable is indexed (the log base 2 of the + * number of entries it contains). + */ + decode_table[subtable_prefix] = + HUFFDEC_SUBTABLE_POINTER | + HUFFDEC_RESULT_ENTRY(subtable_start) | + subtable_bits; + } + + /* Fill the subtable entries for the current codeword. */ + entry = decode_results[*sorted_syms++] | (len - table_bits); + i = subtable_start + (codeword >> table_bits); + stride = 1U << (len - table_bits); + do { + decode_table[i] = entry; + i += stride; + } while (i < cur_table_end); + + /* Advance to the next codeword. */ + if (codeword == (1U << len) - 1) /* last codeword (all 1's)? */ + return true; + bit = 1U << bsr32(codeword ^ ((1U << len) - 1)); + codeword &= bit - 1; + codeword |= bit; + count--; + while (count == 0) + count = len_counts[++len]; + } +} + +/* Build the decode table for the precode. */ +fn build_precode_decode_table(d: &mut Decompressor) -> bool { + /* When you change TABLEBITS, you must change ENOUGH, and vice versa! */ + assert!(PRECODE_TABLEBITS == 7 && PRECODE_ENOUGH == 128); + + return build_decode_table(d.u.l.precode_decode_table, d.u.precode_lens, DEFLATE_NUM_PRECODE_SYMS, precode_decode_results, PRECODE_TABLEBITS, DEFLATE_MAX_PRE_CODEWORD_LEN, d.sorted_syms); +} + +fn FUNCNAME(decompressor: &mut Decompressor, in_: *const u8, in_nbytes: usize, out: *mut u8, out_nbytes_avail: usize, actual_in_nbytes_ret: &mut usize, actual_out_nbytes_ret: &mut usize) { + let out_next = out; + let out_end = unsafe { out_next.add(out_nbytes_avail) }; + let in_next = in_; + let in_end = unsafe { in_next.add(in_nbytes) }; + let mut state = gdeflate_state::new(); + + let i; + let is_final_block; + let block_type; + let len; + let num_litlen_syms; + let num_offset_syms; + let tmp32; + let is_copy = 0; + + /* Starting to read GDeflate stream. */ + state.RESET(); + + for n in 0..NUM_STREAMS { + state.bitbuf[n] = 0; + state.bitsleft[n] = 0; + state.copies[n].length = 0; + state.ADVANCE(is_copy, &mut in_next); // Will advance pointer + } + + let IS_COPY = || is_copy & 1; + let COPY_COMPLETE = || is_copy &= !1; + + let next_block = || { + /* Starting to read the next block. */ + state.RESET(); + + /* BFINAL: 1 bit */ + is_final_block = state.POP_BITS(1); + + /* BTYPE: 2 bits */ + block_type = state.POP_BITS(2); + + state.ENSURE_BITS(LOW_WATERMARK_BITS, &mut in_next); + + if block_type == DEFLATE_BLOCKTYPE_DYNAMIC_HUFFMAN { + /* Dynamic Huffman block. */ + + /* The order in which precode lengths are stored. */ + static deflate_precode_lens_permutation: [u8; DEFLATE_NUM_PRECODE_SYMS as usize] = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + + let mut num_explicit_precode_lens; + + /* Read the codeword length counts. */ + + assert!(DEFLATE_NUM_LITLEN_SYMS == ((1 << 5) - 1) + 257); + num_litlen_syms = state.POP_BITS(5) + 257; + + assert!(DEFLATE_NUM_OFFSET_SYMS == ((1 << 5) - 1) + 1); + num_offset_syms = state.POP_BITS(5) + 1; + + assert!(DEFLATE_NUM_PRECODE_SYMS == ((1 << 4) - 1) + 4); + num_explicit_precode_lens = state.POP_BITS(4) + 4; + + decompressor.static_codes_loaded = false; + + state.ENSURE_BITS(LOW_WATERMARK_BITS, &mut in_next); + + /* Read the precode codeword lengths. */ + assert!(DEFLATE_MAX_PRE_CODEWORD_LEN == (1 << 3) - 1); + for i in 0..num_explicit_precode_lens { + decompressor.u.precode_lens[deflate_precode_lens_permutation[i] as usize] = state.POP_BITS(3) as u8; // WHAT? + + state.ADVANCE(is_copy, &mut in_next); + } + + for i in num_explicit_precode_lens..DEFLATE_NUM_PRECODE_SYMS { + decompressor.u.precode_lens[deflate_precode_lens_permutation[i] as usize] = 0; + } + + /* Build the decode table for the precode. */ + assert!(build_precode_decode_table(&mut decompressor)); + + state.RESET(); + + /* Expand the literal/length and offset codeword lengths. */ + for i in 0..((num_litlen_syms + num_offset_syms) as usize) { + let mut entry: usize; + let mut presym; + let mut rep_val; + let mut rep_count; + + /* (The code below assumes that the precode decode table + * does not have any subtables.) */ + assert!(PRECODE_TABLEBITS == DEFLATE_MAX_PRE_CODEWORD_LEN); + + /* Read the next precode symbol. */ + entry = decompressor.u.l.precode_decode_table[state.BITS(DEFLATE_MAX_PRE_CODEWORD_LEN)] as usize; + state.REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK); + + presym = entry >> HUFFDEC_RESULT_SHIFT; + + if presym < 16 { + /* Explicit codeword length */ + decompressor.u.l.lens[i] = presym as u8; // Weird cast + i += 1; + state.ADVANCE(is_copy, &mut in_next); + continue; + } + + /* Run-length encoded codeword lengths */ + + /* Note: we don't need verify that the repeat count + * doesn't overflow the number of elements, since we + * have enough extra spaces to allow for the worst-case + * overflow (138 zeroes when only 1 length was + * remaining). + * + * In the case of the small repeat counts (presyms 16 + * and 17), it is fastest to always write the maximum + * number of entries. That gets rid of branches that + * would otherwise be required. + * + * It is not just because of the numerical order that + * our checks go in the order 'presym < 16', 'presym == + * 16', and 'presym == 17'. For typical data this is + * ordered from most frequent to least frequent case. + */ + assert!(DEFLATE_MAX_LENS_OVERRUN == 138 - 1); + + if presym == 16 { + /* Repeat the previous length 3 - 6 times */ + assert!(i != 0); + rep_val = decompressor.u.l.lens[i - 1]; + assert!(3 + ((1 << 2) - 1) == 6); + rep_count = 3 + state.POP_BITS(2); + decompressor.u.l.lens[i + 0] = rep_val; + decompressor.u.l.lens[i + 1] = rep_val; + decompressor.u.l.lens[i + 2] = rep_val; + decompressor.u.l.lens[i + 3] = rep_val; + decompressor.u.l.lens[i + 4] = rep_val; + decompressor.u.l.lens[i + 5] = rep_val; + i += rep_count; + } else if presym == 17 { + /* Repeat zero 3 - 10 times */ + assert!(3 + ((1 << 3) - 1) == 10); + rep_count = 3 + state.POP_BITS(3); + decompressor.u.l.lens[i + 0] = 0; + decompressor.u.l.lens[i + 1] = 0; + decompressor.u.l.lens[i + 2] = 0; + decompressor.u.l.lens[i + 3] = 0; + decompressor.u.l.lens[i + 4] = 0; + decompressor.u.l.lens[i + 5] = 0; + decompressor.u.l.lens[i + 6] = 0; + decompressor.u.l.lens[i + 7] = 0; + decompressor.u.l.lens[i + 8] = 0; + decompressor.u.l.lens[i + 9] = 0; + i += rep_count; + } else { + /* Repeat zero 11 - 138 times */ + assert!(11 + ((1 << 7) - 1) == 138); + rep_count = 11 + state.POP_BITS(7); + memset(&decompressor.u.l.lens[i], 0, rep_count * sizeof(decompressor.u.l.lens[i])); + i += rep_count; + } + + state.ADVANCE(is_copy, &mut in_next); + } + } else if block_type == DEFLATE_BLOCKTYPE_UNCOMPRESSED { + + /* Uncompressed block: copy 'len' bytes literally from the input + * buffer to the output buffer. */ + + /* Count bits in the bit buffers. */ + let mut num_buffered_bits = 0; + for n in 0..NUM_STREAMS { + num_buffered_bits += state.bitsleft[n]; + } + + unsafe { + assert!(in_end.sub_ptr(in_next).add((num_buffered_bits as usize + 7)/8) as usize >= 2); + } + + len = state.POP_BITS(16); + + if unsafe { len > out_end.sub_ptr(out_next) } { + return; // LIBDEFLATE_INSUFFICIENT_SPACE; + } + + unsafe { + assert!(len <= in_end.sub_ptr(in_next).add((num_buffered_bits as usize + 7)/8)); + } + + while len != 0 { + unsafe { + *out_next = state.POP_BITS(8) as u8; // Weird cast + out_next = out_next.add(1); + } + + len -= 1; + state.ADVANCE(is_copy, &mut in_next); + } + + block_done(); + } else { + assert!(block_type == DEFLATE_BLOCKTYPE_STATIC_HUFFMAN); + + /* + * Static Huffman block: build the decode tables for the static + * codes. Skip doing so if the tables are already set up from + * an earlier static block; this speeds up decompression of + * degenerate input of many empty or very short static blocks. + * + * Afterwards, the remainder is the same as decompressing a + * dynamic Huffman block. + */ + + if decompressor.static_codes_loaded { + have_decode_tables(); + } + + decompressor.static_codes_loaded = true; + + assert!(DEFLATE_NUM_LITLEN_SYMS == 288); + assert!(DEFLATE_NUM_OFFSET_SYMS == 32); + + decompressor.u.l.lens[0..144] = [8u8; 144]; + decompressor.u.l.lens[144..256] = 9u8; + decompressor.u.l.lens[256..280] = 7u8; + decompressor.u.l.lens[280..288] = 8u8; + + decompressor.u.l.lens[288..288 + 32] = 5u8; + + num_litlen_syms = 288; + num_offset_syms = 32; + } + + /* Decompressing a Huffman block (either dynamic or static) */ + + assert!(build_offset_decode_table(d, num_litlen_syms, num_offset_syms)); + assert!(build_litlen_decode_table(d, num_litlen_syms, num_offset_syms)); + }; + + let block_done = || { + /* Run the outstanding deferred copies. */ + + for n in 0..NUM_STREAMS { + if IS_COPY() != 0 { + do_copy(decompressor, &mut state, out, out_end); + + COPY_COMPLETE(); + } + + state.ADVANCE(is_copy as u32, &mut in_next); + } + + /* Finished decoding a block. */ + + if !(is_final_block != 0) { + next_block(); + } + }; + + let have_decode_tables = || { + state.RESET(); + + /* + * Stores a deferred copy in current GDeflate stream. + */ + let STORE_COPY = |len: usize, out: *mut u8| { + state.copies[state.idx].length = len as u32; + state.copies[state.idx].out_next = out as *mut u32; + is_copy |= 1; + }; + + /* The main GDEFLATE decode loop */ + loop { + let mut entry: usize; + let mut length; + + if IS_COPY() == 0 { // WHATCH OUT + /* Decode a litlen symbol. */ + entry = decompressor.u.litlen_decode_table[state.BITS(LITLEN_TABLEBITS)] as usize; + + if (entry & HUFFDEC_SUBTABLE_POINTER) != 0 { + /* Litlen subtable required (uncommon case) */ + state.REMOVE_BITS(LITLEN_TABLEBITS); + entry = decompressor.u.litlen_decode_table[((entry >> HUFFDEC_RESULT_SHIFT) & 0xFFFF) + state.BITS(entry & HUFFDEC_LENGTH_MASK)] as usize; + } + + state.REMOVE_BITS(entry & HUFFDEC_LENGTH_MASK); + + if (entry & HUFFDEC_LITERAL) != 0 { + /* Literal */ + if out_next == out_end { + return; // LIBDEFLATE_INSUFFICIENT_SPACE; + } + + unsafe { + *out_next = (entry >> HUFFDEC_RESULT_SHIFT) as u8; + out_next = out_end.add(1); + } + + state.ADVANCE(is_copy, &mut in_next); + + continue; + } + + /* Match or end-of-block */ + + entry >>= HUFFDEC_RESULT_SHIFT; + + /* Pop the extra length bits and add them to the length base to + * produce the full length. */ + length = (entry >> HUFFDEC_LENGTH_BASE_SHIFT) + state.POP_BITS(entry & HUFFDEC_EXTRA_LENGTH_BITS_MASK); + + /* The match destination must not end after the end of the + * output buffer. For efficiency, combine this check with the + * end-of-block check. We're using 0 for the special + * end-of-block length, so subtract 1 and it turn it into + * SIZE_MAX. */ + assert!(HUFFDEC_END_OF_BLOCK_LENGTH == 0); + if length - 1 >= unsafe { out_end.sub_ptr(out_next) } { + if length != HUFFDEC_END_OF_BLOCK_LENGTH { + return; // LIBDEFLATE_INSUFFICIENT_SPACE; + } + + block_done(); + } + + /* Store copy for use later. */ + STORE_COPY(length, out_next); + + /* Advance output stream. */ + unsafe { out_next = out_next.add(length); } + } else { + let res = do_copy(decompressor, &mut state, out, out_end); + + COPY_COMPLETE(); + } + + state.ADVANCE(is_copy, &mut in_next); + } + }; + + /* That was the last block. */ + + /* Optionally return the actual number of bytes read */ + *actual_in_nbytes_ret = unsafe { in_next.sub_ptr(in_); } + + /* Optionally return the actual number of bytes written */ + *actual_out_nbytes_ret = unsafe { out_next.sub_ptr(out); } + + if out_next != out_end { + return; // LIBDEFLATE_SHORT_OUTPUT; + } + + return; // LIBDEFLATE_SUCCESS; +} + +struct libdeflate_gdeflate_in_page { + /* Compressed GDEFLATE page data. */ + data: *const u8, + /* Size in bytes of compressed GDEFLATE page. */ + nbytes: usize, +} + +fn libdeflate_gdeflate_decompress(decompressor: &mut Decompressor, in_pages: &[libdeflate_gdeflate_in_page], out: *mut u8, out_nbytes_avail: usize, actual_out_nbytes_ret: &mut usize) +{ + let out_bytes = out; + + if in_pages.len() == 0 { + return; // LIBDEFLATE_BAD_DATA; + } + + for npage in 0..in_pages.len() { + let page_out_nbytes_ret: usize; let page_in_nbytes_ret: usize; + + decompress_impl(decompressor, in_pages[npage].data, in_pages[npage].nbytes, out_bytes, out_nbytes_avail, &page_in_nbytes_ret, &page_out_nbytes_ret); + + out_bytes += page_out_nbytes_ret; + out_nbytes_avail -= page_out_nbytes_ret; + + *actual_out_nbytes_ret += page_out_nbytes_ret; + } + + return; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_compressor() { + let mut c = libdeflate_alloc_gdeflate_compressor(12); + + let mut vec = Vec::with_capacity(65536*2); + + for i in 0..65536*2 { + vec.push(i as u8); + } + + let mut page1 = Vec::with_capacity(66000); + let mut page2 = Vec::with_capacity(66000); + + unsafe { + page1.set_len(66000); + page2.set_len(66000); + } + + let final_size = gdeflate_compress(&mut c, &vec, &[page1.as_mut_slice(), page2.as_mut_slice()]); + + assert!(final_size > 0); + + let decompressor = Decompressor::new(); + + let pages = [ + libdeflate_gdeflate_in_page { + data: page1.as_ptr(), + nbytes: 66000 + }, + libdeflate_gdeflate_in_page { + data: page2.as_ptr(), + nbytes: 66000 + } + ]; + + let out = vec![0u8; 65536*2]; + + unsafe { + out.set_len(65536*2); + } + + let mut actual_out_nbytes_ret: usize = 0; + + libdeflate_gdeflate_decompress(decompressor, &pages, out.as_mut_ptr(), 65536*2, &mut actual_out_nbytes_ret); + + assert_eq!(actual_out_nbytes_ret, 65536*2); + + for (a, b) in vec.iter().zip(out.iter()) { + assert_eq!(a, b); + } + } +} \ No newline at end of file diff --git a/src/input_manager.rs b/src/input_manager.rs new file mode 100644 index 00000000..ea896fa7 --- /dev/null +++ b/src/input_manager.rs @@ -0,0 +1,1193 @@ +//! The input manager is responsible for managing HID devices and their events and properties. +//! +//! # Concepts +//! ## Device Class +//! A device class represents a type of device. Such as a keyboard, mouse, or gamepad. +//! ## Input Source +//! An input source is a source of input on a device class/type. Such as the UP key on a keyboard or the left trigger on a gamepad. +//! ## Input Destination +//! An input destination is a destination of input on a device. Such as the rumble motors on a gamepad. +//! ## Input Event +//! An input event is an application specific event that is triggered by a combination of input sources. +//! For example move sideways is triggered by the left and right keys being pressed. +//! +//! # Usage +//! +//! To use the input manager first you must register a device class/type. +//! ```rust +//! let keyboard_device_class_handle = input_manager.register_device_class("Keyboard"); +//! ``` +//! Then you must register input sources on the device class/type. +//! ```rust +//! let up_input_source = input_manager.register_input_source(&keyboard_device_class_handle, "Up"); +//! let down_input_source = input_manager.register_input_source(&keyboard_device_class_handle, "Down"); +//! let left_input_source = input_manager.register_input_source(&keyboard_device_class_handle, "Left"); +//! let right_input_source = input_manager.register_input_source(&keyboard_device_class_handle, "Right"); +//! ``` +//! Then you must create a device of the device class/type. A device is an instance of a device class/type and will be tied to a device the user can control. +//! ```rust +//! let keyboard_device = input_manager.create_device(&keyboard_device_class_handle); +//! ``` +//! Then you must register your own input events. This are application specific events that are triggered by a combination of input sources. +//! ```rust +//! let move_longitudinally_input_event = input_manager.register_input_event("MoveLongitudinally", &[ +//! InputEventDescription { +//! input_source: InputSourceAction::Name("Keyboard.Up"), +//! mapping: Value::Float(1.0), +//! function: Some(Function::Linear), +//! }, +//! InputEventDescription { +//! input_source: InputSourceAction::Name("Keyboard.Down"), +//! mapping: Value::Float(-1.0), +//! function: Some(Function::Linear), +//! },]); +//! ``` +//! Then you can record input source actions. This is when an input source is pressed or released. This will trigger the input events. +//! ```rust +//! input_manager.record_input_source_action(keyboard_device, InputSourceAction::Name("Keyboard.Up"), Value::Bool(true)); +//! ``` +//! Or +//! ```rust +//! input_manager.record_input_source_action(keyboard_device, InputSourceAction::Handle(up_input_source), Value::Bool(true)); +//! ``` +//! Then you can get the value of an input event. This is the value of the input event based on the input sources that triggered it. +//! ```rust +//! let value = input_manager.get_input_event_value(move_longitudinally_input_event); +//! ``` +//! You can also get the value of an input source. This is the last value of the input source that was recorded. +//! ```rust +//! let value = input_manager.get_input_source_value(keyboard_device, InputSourceAction::Name("Keyboard.Up")); +//! ``` +//! +//! # TODO +//! - [ ] Clamp input source values to their min and max values. +//! - [ ] Add deadzone support. +//! - [ ] Remove panics. +//! - [ ] Add device class and device grouping. + +use crate::{RGBA, Vector2, Vector3, insert_return_length, Quaternion}; + +/// A device class represents a type of device. Such as a keyboard, mouse, or gamepad. +/// It can have associated input sources, such as the UP key on a keyboard or the left trigger on a gamepad. +struct DeviceClass { + /// The name of the device class. + name: String, +} + +#[derive(Copy, Clone)] +pub struct InputSourceDescription { + /// The value the input source will have when it's first registered and no events have been recorded for it. + default: T, + /// The value the input source will have when it's released. + rest: T, + /// The minimum value the input source can have. + min: T, + /// The maximum value the input source can have. + max: T, +} + +impl InputSourceDescription { + pub fn new(default: T, rest: T, min: T, max: T) -> Self { + InputSourceDescription { + default, + rest, + min, + max, + } + } +} + +/// An input source is a source of input on a device class/type. Such as the UP key on a keyboard or the left trigger on a gamepad. +struct InputSource { + /// The device class the input source is associated with. + device_class_handle: DeviceClassHandle, + /// The name of the input source. + name: String, + /// The type of the input source. + type_: InputTypes, +} + +#[derive(Copy, Clone)] +/// An input source action is a way to reference an input source. +/// It can be referenced by it's name or by it's handle. +/// It's provided as a convenience to the developer. +pub enum InputSourceAction { + /// Refer to the input source by it's handle. + Handle(InputSourceHandle), + /// Refer to the input source by it's name. + Name(&'static str) +} + +#[derive(Copy, Clone)] +pub enum InputTypes { + Bool(InputSourceDescription), + Unicode(InputSourceDescription), + Float(InputSourceDescription), + Int(InputSourceDescription), + Rgba(InputSourceDescription), + Vector2(InputSourceDescription), + Vector3(InputSourceDescription), + Quaternion(InputSourceDescription), +} + +#[derive(Debug, Copy, Clone, PartialEq)] +/// A simple "typeless" container for several underlying types. +/// Can be used to store any of these types, but will be usually used to traffic record and input event values. +pub enum Value { + /// A boolean value. + Bool(bool), + /// A unicode character. + Unicode(char), + /// A floating point value. + Float(f32), + /// An integer value. + Int(i32), + /// An RGBA color value. + Rgba(RGBA), + /// A 2D point value. + Vector2(Vector2), + /// A 3D point value. + Vector3(Vector3), + /// A quaternion. + Quaternion(Quaternion), +} + +#[derive(Copy, Clone)] +/// Enumerates the different functions that can be applied to an input event. +pub enum Function { + Boolean, + Threshold, + Linear, +} + +pub struct InputEventDescription { + pub input_source: InputSourceAction, + pub mapping: Value, + pub function: Option +} + +#[derive(Copy, Clone, PartialEq)] +pub struct InputSourceRecord { + input_source_handle: InputSourceHandle, + value: Value, + time: std::time::SystemTime, +} + +impl PartialOrd for InputSourceRecord { + fn partial_cmp(&self, other: &Self) -> Option { + self.time.partial_cmp(&other.time) + } +} + +struct InputSourceState { + value: Value, + time: std::time::SystemTime, +} + +struct InputSourceMapping { + input_source_handle: InputSourceHandle, + mapping: Value, + function: Option, +} + +/// Enumerates the different types of types of values the input manager can handle. +enum Types { + /// A boolean value. + Bool, + /// A unicode character. + Unicode, + /// A floating point value. + Float, + /// An integer value. + Int, + /// A 2D point value. + Vector2, + /// A 3D point value. + Vector3, + /// A quaternion. + Quaternion, + /// An RGBA color value. + Rgba, +} + +/// An input event is an application specific event that is triggered by a combination of input sources. +struct InputEvent { + name: String, + type_: Types, + min: Value, + max: Value, + input_event_descriptions: Vec, + /// The stack is a list of input source records that simultaneous, connected, and currently active. + /// The stack is used to determine the value of the input event. + /// The stack is ordered by the time the input source was first pressed. + /// An element is popped when it's corresponding input source is released. + /// Example: + /// - Input source `A` is pressed. + /// (Value is A) + /// - Input source `B` is pressed. + /// (Value is B) + /// - Input source `B` is released. + /// (Value is A) + /// - Input source `B` is pressed. + /// (Value is B) + /// - Input source `A` is released. + /// (Value is B) + /// - Input source `B` is released. + /// (Value is None) + stack: Vec, +} + +/// A device represents a particular instance of a device class. Such as the current keyboard, or a specific gamepad. +/// This is useful for when you want to have multiple devices of the same type. Such as multiple gamepads(player 0, player 1, etc). +struct Device { + device_class_handle: DeviceClassHandle, + index: u32, + input_source_states: std::collections::HashMap, +} + +pub struct InputSourceEventState { + device_handle: DeviceHandle, + value: Value, +} + +/// The input event state is the value of an input event. +pub struct InputEventState { + /// The device that triggered the input event. + device_handle: DeviceHandle, + /// The handle to the input event. + input_event_handle: InputEventHandle, + /// The value of the input event. + value: Value, +} + +#[derive(Copy, Clone, PartialEq, Eq)] +/// Handle to an input device class. +pub struct DeviceClassHandle(u32); + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +/// Handle to an input source. +pub struct InputSourceHandle(u32); + +#[derive(Clone, PartialEq, Eq, Debug)] +/// Handle to an device. +pub struct DeviceHandle(u32); + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +/// Handle to an input event. +pub struct InputEventHandle(u32); + +/// The input manager is responsible for managing input devices and input events. +pub struct InputManager { + device_classes: Vec, + input_sources: Vec, + devices: Vec, + records: Vec, + input_events: Vec, +} + +impl InputManager { + /// Creates a new input manager. + pub fn new() -> Self { + InputManager { + device_classes: Vec::new(), + input_sources: Vec::new(), + devices: Vec::new(), + records: Vec::new(), + input_events: Vec::new(), + } + } + + /// Registers a device class/type. + /// + /// One example is a keyboard. + /// + /// # Arguments + /// + /// * `name` - The name of the device type. **Should be pascalcase.** + /// + /// # Example + /// + /// ``` + /// # use byte_engine::input_manager::InputManager; + /// # let mut input_manager = InputManager::new(); + /// input_manager.register_device_class("Keyboard"); + /// ``` + pub fn register_device_class(&mut self, name: &str) -> DeviceClassHandle { + let device_class = DeviceClass { + name: name.to_string(), + }; + + DeviceClassHandle(insert_return_length(&mut self.device_classes, device_class) as u32) + } + + /// Registers an input source on a device class. + /// + /// One example is the UP key on a keyboard. + /// + /// The input source is associated with a device class/type. + /// The input source has a default value assigned from the `value_type` param. + /// + /// # Arguments + /// + /// * `device_handle` - The handle of the device. + /// * `name` - The name of the input source. + /// * `value_type` - The type of the value of the input source. + /// + /// # Example + /// + /// ```rust + /// # use byte_engine::input_manager::{InputManager, InputTypes, InputSourceDescription}; + /// # let mut input_manager = InputManager::new(); + /// # let keyboard_device_class_handle = input_manager.register_device_class("Keyboard"); + /// input_manager.register_input_source(&keyboard_device_class_handle, "Up", InputTypes::Bool(InputSourceDescription::new(false, false))); + /// ``` + pub fn register_input_source(&mut self, device_handle: &DeviceClassHandle, name: &str, value_type: InputTypes) -> InputSourceHandle { + let input_source = InputSource { + device_class_handle: device_handle.clone(), + name: name.to_string(), + type_: value_type, + }; + + InputSourceHandle(insert_return_length(&mut self.input_sources, input_source) as u32) + } + + /// Registers an input destination on a device. + /// + /// One example is the rumble motors on a gamepad. + /// + /// The input destination is associated with a device. + /// + /// # Arguments + /// * `device_handle` - The handle of the device. + /// * `name` - The name of the input destination. + /// * `value_type` - The type of the value of the input destination. + /// + /// # Example + /// ```rust + /// # use byte_engine::input_manager::{InputManager, InputTypes, InputSourceDescription}; + /// # let mut input_manager = InputManager::new(); + /// # let gamepad_device_class_handle = input_manager.register_device_class("Gamepad"); + /// input_manager.register_input_destination(&gamepad_device_class_handle, "Rumble", InputTypes::Float(InputSourceDescription::new(0f32, 0f32, 0f32, 1f32))); + /// ``` + pub fn register_input_destination(&mut self, device_class_handle: &DeviceClassHandle, name: &str, value_type: InputTypes) -> InputSourceHandle { + InputSourceHandle(0) + } + + /// Creates an instance of a device class. + /// This represents a particular device of a device class. Such as a single controller or a keyboard. + /// + /// # Arguments + /// + /// * `device_class_handle` - The handle of the device class. + /// + /// # Example + /// + /// ```rust + /// # use byte_engine::input_manager::InputManager; + /// # let mut input_manager = InputManager::new(); + /// # let keyboard_device_class_handle = input_manager.register_device_class("Keyboard"); + /// let keyboard_device = input_manager.create_device(&keyboard_device_class_handle); + /// ``` + pub fn create_device(&mut self, device_class_handle: &DeviceClassHandle) -> DeviceHandle { + let device_class = &self.device_classes[device_class_handle.0 as usize]; + + let other_device = self.devices.iter().filter(|d| d.device_class_handle.0 == device_class_handle.0).min_by_key(|d| d.index); + + let index = match other_device { + Some(device) => device.index + 1, + None => 0, + }; + + let input_source_handles = self.input_sources.iter().enumerate().filter(|i| i.1.device_class_handle == *device_class_handle).map(|i| InputSourceHandle(i.0 as u32)).collect::>(); + + let mut input_source_states = std::collections::HashMap::with_capacity(input_source_handles.len()); + + for input_source_handle in input_source_handles { + let input_source = &self.input_sources[input_source_handle.0 as usize]; + + let input_source_state = InputSourceState { + value: match input_source.type_ { + InputTypes::Bool(description) => Value::Bool(description.default), + InputTypes::Unicode(description) => Value::Unicode(description.default), + InputTypes::Float(description) => Value::Float(description.default), + InputTypes::Int(description) => Value::Int(description.default), + InputTypes::Rgba(description) => Value::Rgba(description.default), + InputTypes::Vector2(description) => Value::Vector2(description.default), + InputTypes::Vector3(description) => Value::Vector3(description.default), + InputTypes::Quaternion(description) => Value::Quaternion(description.default), + }, + time: std::time::SystemTime::now(), + }; + + input_source_states.insert(input_source_handle, input_source_state); + } + + let device = Device { + device_class_handle: device_class_handle.clone(), + index, + input_source_states, + }; + + DeviceHandle(insert_return_length(&mut self.devices, device) as u32) + } + + /// Registers an input event. + /// + /// One example is a "move forward" being pressed. + /// + /// - Action: + /// - Action: Returns the action value. + /// - Character: Returns a character when the action is pressed. + /// - Linear: Returns a float value when the action is pressed. + /// - 2D: Returns a 2D point when the action is pressed. + /// - 3D: Returns a 3D point when the action is pressed. + /// - Quaternion: Returns a quaternion when the action is pressed. + /// - RGBA: Returns a RGBA color when the action is pressed. + /// - Character: + /// - Action: Returns an action value when the character is pressed. + /// - Character: Returns the character value. + /// - Linear: Returns a float value when the character is pressed. + /// - 2D: Returns a 2D point when the character is pressed. + /// - 3D: Returns a 3D point when the character is pressed. + /// - Quaternion: Returns a quaternion when the character is pressed. + /// - RGBA: Returns a RGBA color when the character is pressed. + /// - Linear: + /// - Action: Returns an action value when the float value is reached. + /// - Character: Returns a character when the float value is reached. + /// - Linear: Returns the float value. + /// - 2D: Interpolates between two 2D points based on the range of the float value. + /// - 3D: Interpolates between two 3D points based on the range of the float value. + /// - Quaternion: Interpolates between two quaternions based on the range of the float value. + /// - RGBA: Interpolates between two RGBA colors based on the range of the float value. + /// - 2D: + /// - Action: Returns an action value when the 2D point is reached. + /// - Character: Returns a character when the 2D point is reached. + /// - Linear: Returns a float value when the 2D point is reached. + /// - 2D: Returns the 2D point. + /// - 3D: Returns a 3D point when the 2D point is reached. + /// - Quaternion: Returns a quaternion when the 2D point is reached. + /// - RGBA: Returns a RGBA color when the 2D point is reached. + /// - 3D: + /// - Action: Returns an action value when the 3D point is reached. + /// - Character: Returns a character when the 3D point is reached. + /// - Linear: Returns a float value when the 3D point is reached. + /// - 2D: Returns a 2D point when the 3D point is reached. + /// - 3D: Returns the 3D point. + /// - Quaternion: Returns a quaternion when the 3D point is reached. + /// - RGBA: Returns a RGBA color when the 3D point is reached. + /// - Quaternion: + /// - Action: Returns an action value when the quaternion is reached. + /// - Character: Returns a character when the quaternion is reached. + /// - Linear: Returns a float value when the quaternion is reached. + /// - 2D: Returns a 2D point when the quaternion is reached. + /// - 3D: Returns a 3D point when the quaternion is reached. + /// - Quaternion: Returns the quaternion. + /// - RGBA: Returns a RGBA color when the quaternion is reached. + /// - RGBA: + /// - Action: Returns an action value when the RGBA color is reached. + /// - Character: Returns a character when the RGBA color is reached. + /// - Linear: Returns a float value when the RGBA color is reached. + /// - 2D: Returns a 2D point when the RGBA color is reached. + /// - 3D: Returns a 3D point when the RGBA color is reached. + /// - Quaternion: Returns a quaternion when the RGBA color is reached. + /// - RGBA: Returns the RGBA color. + fn register_input_event(&mut self, name: &str, min: Value, max: Value, input_events: &[InputEventDescription]) -> InputEventHandle { + let type_ = match (min, max) { + (Value::Bool(_), Value::Bool(_)) => Types::Bool, + (Value::Unicode(_), Value::Unicode(_)) => Types::Unicode, + (Value::Float(_), Value::Float(_)) => Types::Float, + (Value::Int(_), Value::Int(_)) => Types::Int, + (Value::Rgba(_), Value::Rgba(_)) => Types::Rgba, + (Value::Vector2(_), Value::Vector2(_)) => Types::Vector2, + (Value::Vector3(_), Value::Vector3(_)) => Types::Vector3, + (Value::Quaternion(_), Value::Quaternion(_)) => Types::Quaternion, + _ => panic!("Min and max value types do not match!"), + }; + + let input_event = InputEvent { + name: name.to_string(), + type_, + min, max, + input_event_descriptions: input_events.iter().map(|input_event| { + InputSourceMapping { + input_source_handle: self.to_input_source_handle(&input_event.input_source), + mapping: input_event.mapping, + function: input_event.function, + } + }).collect::>(), + stack: Vec::new(), + }; + + InputEventHandle(insert_return_length(&mut self.input_events, input_event) as u32) + } + + /// Records an input source action. + /// + /// One example is the UP key on a keyboard being pressed. + fn record_input_source_action(&mut self, device_handle: &DeviceHandle, input_source_action: InputSourceAction, value: Value) { + let input_source = self.get_input_source_from_input_source_action(&input_source_action); + + let matches = match input_source.type_ { + InputTypes::Bool(_) => std::mem::discriminant(&value) == std::mem::discriminant(&Value::Bool(false)), + InputTypes::Unicode(_) => std::mem::discriminant(&value) == std::mem::discriminant(&Value::Unicode('\0')), + InputTypes::Float(_) => std::mem::discriminant(&value) == std::mem::discriminant(&Value::Float(0f32)), + InputTypes::Int(_) => std::mem::discriminant(&value) == std::mem::discriminant(&Value::Int(0)), + InputTypes::Rgba(_) => std::mem::discriminant(&value) == std::mem::discriminant(&Value::Rgba(RGBA { r: 0f32, g: 0f32, b: 0f32, a: 0f32 })), + InputTypes::Vector2(_) => std::mem::discriminant(&value) == std::mem::discriminant(&&Value::Vector2(Vector2 { x: 0f32, y: 0f32 })), + InputTypes::Vector3(_) => std::mem::discriminant(&value) == std::mem::discriminant(&Value::Vector3(Vector3 { x: 0f32, y: 0f32, z: 0f32 })), + InputTypes::Quaternion(_) => std::mem::discriminant(&value) == std::mem::discriminant(&Value::Quaternion(Quaternion { x: 0f32, y: 0f32, z: 0f32, w: 0f32 })), + }; + + if !matches { + println!("Tried to record an extraneous type into input source: {}", input_source.name); + return; + } // Value type does not match input source declared type, so don't record. + + let input_source_handle = self.to_input_source_handle(&input_source_action); + + let device = &mut self.devices[device_handle.0 as usize]; + + let input_source_state = device.input_source_states.get_mut(&input_source_handle); + + if input_source_state.is_none() { + // TODO: log warning and handle gracefully. + panic!("Input source state not found!"); + } + + let input_source_state = input_source_state.unwrap(); + + let time = std::time::SystemTime::now(); + + input_source_state.value = value; + input_source_state.time = time; + + let record = InputSourceRecord { + input_source_handle, + value, + time, + }; + + self.records.push(record); + + if let Value::Bool(boo) = value { + let input_events = self.input_events.iter_mut().filter(|ie| ie.input_event_descriptions.iter().any(|ied| ied.input_source_handle == input_source_handle)); + + if boo { + for input_event in input_events { + input_event.stack.push(record); + } + } else { + for input_event in input_events { + input_event.stack.retain(|r| r.input_source_handle != input_source_handle); + } + } + } + } + + /// Gets the input source action from the input source action. + pub fn get_input_source_record(&self, device_handle: &DeviceHandle, input_source_action: InputSourceAction) -> InputSourceRecord { + let input_source = self.get_input_source_from_input_source_action(&input_source_action); + + let device = self.get_device(device_handle); + let state = &device.input_source_states[&self.to_input_source_handle(&input_source_action)]; + + InputSourceRecord { + input_source_handle: InputSourceHandle(0), + value: state.value, + time: state.time + } + } + + pub fn get_input_source_value(&self, device_handle: &DeviceHandle, input_source_action: InputSourceAction) -> Value { + let input_source = self.get_input_source_from_input_source_action(&input_source_action); + + let device = self.get_device(device_handle); + let state = &device.input_source_states[&self.to_input_source_handle(&input_source_action)]; + + state.value + } + + pub fn get_input_source_values(&self, input_source_action: InputSourceAction) -> Vec { + let input_source = self.get_input_source_from_input_source_action(&input_source_action); + + self.devices.iter().enumerate().map(|(i, device)| { + let device_handle = DeviceHandle(i as u32); + + InputSourceEventState { + value: self.get_input_source_value(&device_handle, input_source_action), + device_handle, + } + }).collect::>() + } + + /// Gets the value of an input event. + pub fn get_input_event_value(&self, input_event_handle: InputEventHandle, device_handle: &DeviceHandle) -> InputEventState { + let input_event = &self.input_events[input_event_handle.0 as usize]; + + let input_sources_values = input_event.input_event_descriptions.iter().map(|input_event_description| { + (self.get_input_source_record(device_handle, InputSourceAction::Handle(input_event_description.input_source_handle)), input_event_description.input_source_handle, input_event_description) + }).collect::>(); + + // Assume linear event, boolean input sources, last event takes precedence + + let value = match input_event.type_ { + Types::Float => { + let (min, max) = match (input_event.min, input_event.max) { + (Value::Float(min), Value::Float(max)) => (min, max), + _ => panic!("Min and max value types do not match!"), + }; + + let (input_source_value, input_source_mapping_value) = if let Some(last) = input_event.stack.last() { + if let Value::Bool(value) = last.value { + let event_description_for_input_source = input_event.input_event_descriptions.iter().find(|description| description.input_source_handle == last.input_source_handle).unwrap(); + + ( + if value { 1f32 } else { 0f32 }, + match event_description_for_input_source.mapping { + Value::Bool(value) => if value { 1f32 } else { 0f32 }, + Value::Unicode(_) => 0f32, + Value::Float(value) => value, + Value::Int(value) => value as f32, + Value::Rgba(value) => value.r, + Value::Vector2(value) => value.x, + Value::Vector3(value) => value.x, + Value::Quaternion(value) => value.x, + } + ) + } else { + panic!("Last value is not a boolean!"); + } + } else { + let mapping_for_most_recent_input_source = input_sources_values.iter().max_by_key(|x| x.0.time).unwrap(); + + (match mapping_for_most_recent_input_source.0.value { + Value::Bool(value) => if value { 1f32 } else { 0f32 }, + Value::Unicode(_) => 0f32, + Value::Float(value) => value, + Value::Int(value) => value as f32, + Value::Rgba(value) => value.r, + Value::Vector2(value) => value.x, + Value::Vector3(value) => value.x, + Value::Quaternion(value) => value.x, + }, + match mapping_for_most_recent_input_source.2.mapping { + Value::Bool(value) => if value { 1f32 } else { 0f32 }, + Value::Unicode(_) => 0f32, + Value::Float(value) => value, + Value::Int(value) => value as f32, + Value::Rgba(value) => value.r, + Value::Vector2(value) => value.x, + Value::Vector3(value) => value.x, + Value::Quaternion(value) => value.x, + }) + }; + + Value::Float(input_source_value * input_source_mapping_value) + } + _ => panic!("Not implemented!"), + }; + + InputEventState { + device_handle: device_handle.clone(), + input_event_handle, + value, + } + } + + fn get_input_source_from_input_source_action(&self, input_source_action: &InputSourceAction) -> &InputSource { + &self.input_sources[self.to_input_source_handle(input_source_action).0 as usize] + } + + fn get_device(&self, device_handle: &DeviceHandle) -> &Device { + &self.devices[device_handle.0 as usize] + } + + fn to_input_source_handle(&self, input_source_action: &InputSourceAction) -> InputSourceHandle { + match input_source_action { + InputSourceAction::Handle(handle) => *handle, + InputSourceAction::Name(name) => { + let tokens = (*name).split('.'); + + let input_device_class = self.device_classes.iter().enumerate().find(|(_, device_class)| device_class.name == tokens.clone().next().unwrap()); + + if let Some(_) = input_device_class { + let input_source = self.input_sources.iter().enumerate().find(|(_, input_source)| input_source.name == tokens.clone().last().unwrap()); + + if let Some(input_source) = input_source { + InputSourceHandle(input_source.0 as u32) + } else { + panic!("Input source not found!"); + } + } else { + panic!("Input device not found!"); + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn declare_keyboard_input_device_class(input_manager: &mut InputManager) -> DeviceClassHandle { + let device_class_handle = input_manager.register_device_class("Keyboard"); + + let key_source_description = InputTypes::Bool(InputSourceDescription::new(false, false, false, true)); + + let up_input_source = input_manager.register_input_source(&device_class_handle, "Up", key_source_description); + let down_input_source = input_manager.register_input_source(&device_class_handle, "Down", key_source_description); + let left_input_source = input_manager.register_input_source(&device_class_handle, "Left", key_source_description); + let right_input_source = input_manager.register_input_source(&device_class_handle, "Right", key_source_description); + + let key_source_description = InputTypes::Unicode(InputSourceDescription::new('\0', '\0', '\0', 'Z')); + + let a_input_source = input_manager.register_input_source(&device_class_handle, "Character", key_source_description); + + device_class_handle + } + + fn declare_gamepad_input_device_class(input_manager: &mut InputManager) -> DeviceClassHandle { + let device_class_handle = input_manager.register_device_class("Gamepad"); + + let key_source_description = InputTypes::Float(InputSourceDescription::new(0.0f32, 0.0f32, 0.0f32, 1.0f32)); + + let up_input_source = input_manager.register_input_source(&device_class_handle, "LeftTrigger", key_source_description); + let down_input_source = input_manager.register_input_source(&device_class_handle, "RighTrigger", key_source_description); + + let key_source_description = InputTypes::Vector2(InputSourceDescription::new(Vector2::zero(), Vector2::zero(), Vector2 { x: -1.0, y: -1.0, }, Vector2 { x: 1.0, y: 1.0, })); + + let a_input_source = input_manager.register_input_source(&device_class_handle, "LeftStick", key_source_description); + let b_input_source = input_manager.register_input_source(&device_class_handle, "RightStick", key_source_description); + + let light_source_description = InputTypes::Rgba(InputSourceDescription::new(RGBA { r: 0.0f32, g: 0.0f32, b: 0.0f32, a: 0.0f32 }, RGBA { r: 0.0f32, g: 0.0f32, b: 0.0f32, a: 0.0f32 }, RGBA { r: 0.0f32, g: 0.0f32, b: 0.0f32, a: 0.0f32 }, RGBA { r: 1.0f32, g: 1.0f32, b: 1.0f32, a: 1.0f32 })); + + let light_destination = input_manager.register_input_destination(&device_class_handle, "Light", light_source_description); + + device_class_handle + } + + fn declare_vr_headset_input_device_class(input_manager: &mut InputManager) -> DeviceClassHandle { + let device_class_handle = input_manager.register_device_class("Headset"); + + let source_description = InputTypes::Vector3(InputSourceDescription::new(Vector3::new(0f32, 1.80f32, 0f32), Vector3::new(0f32, 0f32, 0f32), Vector3::min(), Vector3::max())); + + let position_input_source = input_manager.register_input_source(&device_class_handle, "Position", source_description); + + let source_description = InputTypes::Quaternion(InputSourceDescription::new(Quaternion::identity(), Quaternion::identity(), Quaternion::min(), Quaternion::max())); + + let rotation_input_source = input_manager.register_input_source(&device_class_handle, "Orientation", source_description); + + device_class_handle + } + + fn declare_funky_input_device_class(input_manager: &mut InputManager) -> DeviceClassHandle { + let device_class_handle = input_manager.register_device_class("Funky"); + + let source_description = InputTypes::Int(InputSourceDescription::new(0, 0, 0, 3)); + + let funky_input_source = input_manager.register_input_source(&device_class_handle, "Int", source_description); + + let source_description = InputTypes::Rgba(InputSourceDescription::new(RGBA { r: 0.0f32, g: 0.0f32, b: 0.0f32, a: 0.0f32 }, RGBA { r: 0.0f32, g: 0.0f32, b: 0.0f32, a: 0.0f32 }, RGBA { r: 0.0f32, g: 0.0f32, b: 0.0f32, a: 0.0f32 }, RGBA { r: 1.0f32, g: 1.0f32, b: 1.0f32, a: 1.0f32 })); + + input_manager.register_input_source(&device_class_handle, "Rgba", source_description); + + device_class_handle + } + + #[test] + fn create_device_class() { + let mut input_manager = InputManager::new(); + + let device_class_handle = input_manager.register_device_class("Keyboard"); + } + + #[test] + fn create_input_sources() { + let mut input_manager = InputManager::new(); + + let gamepad_class_handle = input_manager.register_device_class("Gamepad"); + + declare_keyboard_input_device_class(&mut input_manager); + + let stick_source_description = InputTypes::Vector2(InputSourceDescription::new(Vector2::zero(), Vector2::zero(), Vector2 { x: -1.0, y: -1.0, }, Vector2 { x: 1.0, y: 1.0, })); + + let gamepad_left_stick_input_source = input_manager.register_input_source(&gamepad_class_handle, "LeftStick", stick_source_description); + let gamepad_right_stick_input_source = input_manager.register_input_source(&gamepad_class_handle, "RightStick", stick_source_description); + + let trigger_source_description = InputTypes::Float(InputSourceDescription { default: 0.0, rest: 0.0, min: 0.0, max: 1.0 }); + + let trigger_input_source = input_manager.register_input_source(&gamepad_class_handle, "LeftTrigger", trigger_source_description); + } + + #[test] + fn record_bool_input_source_actions() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_keyboard_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Keyboard.Up"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Bool(false)); // Must be false by default(declared in "declare_keyboard_input_device_class"). + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Bool(true)); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Bool(false)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Bool(false)); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Bool(false)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Bool(false)); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Bool(false)); + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Bool(true)); // Must be true after recording multiple times without querying the value. + + input_manager.record_input_source_action(&device, handle, Value::Float(98f32)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Bool(true)); // Must keep the previous value if the type is different. + } + + #[test] + fn record_unicode_input_source_actions() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_keyboard_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Keyboard.Character"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Unicode('\0')); // Must be false by default(declared in "declare_keyboard_input_device_class"). + + input_manager.record_input_source_action(&device, handle, Value::Unicode('a')); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Unicode('a')); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Unicode('\0')); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Unicode('\0')); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Unicode('\0')); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Unicode('\0')); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Unicode('\0')); + input_manager.record_input_source_action(&device, handle, Value::Unicode('a')); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Unicode('a')); // Must be true after recording multiple times without querying the value. + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Unicode('a')); // Must keep the previous value if the type is different. + } + + #[test] + fn record_int_input_source_actions() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_funky_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Funky.Int"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Int(0)); // Must be false by default(declared in "declare_keyboard_input_device_class"). + + input_manager.record_input_source_action(&device, handle, Value::Int(1)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Int(1)); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Int(0)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Int(0)); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Int(0)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Int(0)); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Int(0)); + input_manager.record_input_source_action(&device, handle, Value::Int(1)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Int(1)); // Must be true after recording multiple times without querying the value. + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Int(1)); // Must keep the previous value if the type is different. + } + + #[test] + fn record_float_input_source_actions() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_gamepad_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Gamepad.LeftTrigger"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Float(0.0f32)); // Must be false by default(declared in "declare_gamepad_input_device_class"). + + input_manager.record_input_source_action(&device, handle, Value::Float(1f32)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Float(1f32)); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Float(0f32)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Float(0f32)); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Float(0f32)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Float(0f32)); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Float(0f32)); + input_manager.record_input_source_action(&device, handle, Value::Float(1f32)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Float(1f32)); // Must be true after recording multiple times without querying the value. + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Float(1f32)); // Must keep the previous value if the type is different. + } + + #[test] + fn record_vector2_input_source_action() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_gamepad_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Gamepad.LeftStick"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector2(Vector2 { x: 0f32, y: 0f32, })); // Must be false by default(declared in "declare_gamepad_input_device_class"). + + input_manager.record_input_source_action(&device, handle, Value::Vector2(Vector2 { x: 1f32, y: 1f32, })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector2(Vector2 { x: 1f32, y: 1f32, })); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Vector2(Vector2 { x: 0f32, y: 0f32, })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector2(Vector2 { x: 0f32, y: 0f32, })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Vector2(Vector2 { x: 0f32, y: 0f32, })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector2(Vector2 { x: 0f32, y: 0f32, })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Vector2(Vector2 { x: 0f32, y: 0f32, })); + input_manager.record_input_source_action(&device, handle, Value::Vector2(Vector2 { x: 1f32, y: 1f32, })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector2(Vector2 { x: 1f32, y: 1f32, })); // Must be true after recording multiple times without querying the value. + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector2(Vector2 { x: 1f32, y: 1f32, })); // Must keep the previous value if the type is different. + } + + #[test] + fn record_vector3_input_source_actions() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_vr_headset_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Headset.Position"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector3(Vector3 { x: 0f32, y: 1.8f32, z: 0f32 })); + + input_manager.record_input_source_action(&device, handle, Value::Vector3(Vector3 { x: 1f32, y: 1f32, z: 1f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector3(Vector3 { x: 1f32, y: 1f32, z: 1f32 })); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Vector3(Vector3 { x: 0f32, y: 0f32, z: 0f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector3(Vector3 { x: 0f32, y: 0f32, z: 0f32 })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Vector3(Vector3 { x: 0f32, y: 0f32, z: 0f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector3(Vector3 { x: 0f32, y: 0f32, z: 0f32 })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Vector3(Vector3 { x: 0f32, y: 0f32, z: 0f32 })); + input_manager.record_input_source_action(&device, handle, Value::Vector3(Vector3 { x: 1f32, y: 1f32, z: 1f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector3(Vector3 { x: 1f32, y: 1f32, z: 1f32 })); // Must be true + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Vector3(Vector3 { x: 1f32, y: 1f32, z: 1f32 })); // Must keep the previous value if the type is different. + } + + #[test] + fn record_quaternion_input_source_actions() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_vr_headset_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Headset.Orientation"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Quaternion(Quaternion { x: 0f32, y: 0f32, z: 0f32, w: 1f32 })); + + input_manager.record_input_source_action(&device, handle, Value::Quaternion(Quaternion { x: 1f32, y: 1f32, z: 1f32, w: 1f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Quaternion(Quaternion { x: 1f32, y: 1f32, z: 1f32, w: 1f32 })); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Quaternion(Quaternion { x: 0f32, y: 0f32, z: 0f32, w: 0f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Quaternion(Quaternion { x: 0f32, y: 0f32, z: 0f32, w: 0f32 })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Quaternion(Quaternion { x: 0f32, y: 0f32, z: 0f32, w: 0f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Quaternion(Quaternion { x: 0f32, y: 0f32, z: 0f32, w: 0f32 })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Quaternion(Quaternion { x: 0f32, y: 0f32, z: 0f32, w: 0f32 })); + input_manager.record_input_source_action(&device, handle, Value::Quaternion(Quaternion { x: 1f32, y: 1f32, z: 1f32, w: 0f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Quaternion(Quaternion { x: 1f32, y: 1f32, z: 1f32, w: 0f32 })); // Must be true + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Quaternion(Quaternion { x: 1f32, y: 1f32, z: 1f32, w: 0f32 })); // Must keep the previous value if the type is different. + } + + #[test] + fn record_rgba_input_source_actions() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_funky_input_device_class(&mut input_manager); + + let device = input_manager.create_device(&device_class_handle); + + let handle = InputSourceAction::Name("Funky.Rgba"); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Rgba(RGBA { r: 0f32, g: 0f32, b: 0f32, a: 0f32 })); + + input_manager.record_input_source_action(&device, handle, Value::Rgba(RGBA { r: 1f32, g: 1f32, b: 1f32, a: 1f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Rgba(RGBA { r: 1f32, g: 1f32, b: 1f32, a: 1f32 })); // Must be true after recording. + + input_manager.record_input_source_action(&device, handle, Value::Rgba(RGBA { r: 0f32, g: 0f32, b: 0f32, a: 0f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Rgba(RGBA { r: 0f32, g: 0f32, b: 0f32, a: 0f32 })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Rgba(RGBA { r: 0f32, g: 0f32, b: 0f32, a: 0f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Rgba(RGBA { r: 0f32, g: 0f32, b: 0f32, a: 0f32 })); // Must be false after recording. + + input_manager.record_input_source_action(&device, handle, Value::Rgba(RGBA { r: 0f32, g: 0f32, b: 0f32, a: 0f32 })); + input_manager.record_input_source_action(&device, handle, Value::Rgba(RGBA { r: 1f32, g: 1f32, b: 1f32, a: 1f32 })); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Rgba(RGBA { r: 1f32, g: 1f32, b: 1f32, a: 1f32 })); // Must be true + + input_manager.record_input_source_action(&device, handle, Value::Bool(true)); + + assert_eq!(input_manager.get_input_source_value(&device, handle), Value::Rgba(RGBA { r: 1f32, g: 1f32, b: 1f32, a: 1f32 })); // Must keep the previous value if the type is different. + } + + #[test] + fn create_input_events() { + let mut input_manager = InputManager::new(); + + declare_keyboard_input_device_class(&mut input_manager); + + let input_event = input_manager.register_input_event("MoveLongitudinally", Value::Float(-1f32), Value::Float(1f32), &[ + InputEventDescription { + input_source: InputSourceAction::Name("Keyboard.Up"), + mapping: Value::Float(1.0), + function: Some(Function::Linear), + }, + InputEventDescription { + input_source: InputSourceAction::Name("Keyboard.Down"), + mapping: Value::Float(-1.0), + function: Some(Function::Linear), + },]); + } + + #[test] + fn get_float_input_event_from_bool_input_source() { + let mut input_manager = InputManager::new(); + + let device_class_handle = declare_keyboard_input_device_class(&mut input_manager); + + let input_event = input_manager.register_input_event("MoveLongitudinally", Value::Float(-1f32), Value::Float(1f32), &[ + InputEventDescription { + input_source: InputSourceAction::Name("Keyboard.Up"), + mapping: Value::Float(1.0), + function: Some(Function::Linear), + }, + InputEventDescription { + input_source: InputSourceAction::Name("Keyboard.Down"), + mapping: Value::Float(-1.0), + function: Some(Function::Linear), + },]); + + let device_handle = input_manager.create_device(&device_class_handle); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.device_handle, device_handle); + assert_eq!(value.value, Value::Float(0f32)); // Default value must be 0. + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Up"), Value::Bool(true)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(1.0)); // Must be 1.0 after recording. + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Up"), Value::Bool(false)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(0.0)); // Must be 0.0 after recording. + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Down"), Value::Bool(true)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(-1.0)); // Must be -1.0 after recording. + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Down"), Value::Bool(false)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(0.0)); // Must be 0.0 after recording. + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Up"), Value::Bool(true)); + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Down"), Value::Bool(true)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(-1.0)); // Must be -1.0 after recording down after up while up is still pressed. + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Up"), Value::Bool(false)); + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Down"), Value::Bool(false)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(0.0)); // Must be 0.0 after recording + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Up"), Value::Bool(true)); + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Down"), Value::Bool(true)); + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Up"), Value::Bool(false)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(-1.0)); // Must be -1.0 after releasing up while down down is still pressed. + + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Up"), Value::Bool(true)); + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Down"), Value::Bool(true)); + input_manager.record_input_source_action(&device_handle, InputSourceAction::Name("Keyboard.Down"), Value::Bool(false)); + + let value = input_manager.get_input_event_value(input_event, &device_handle); + + assert_eq!(value.value, Value::Float(1.0)); // Must be 1.0 after releasing down while up is still pressed. + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..ad6c6a71 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,192 @@ +//! # Byte-Engine +//! Byte-Engine is a Rust powered game engine. It is designed to be efficient, fast and easy to use; with simple, composable patterns + +#![feature(int_roundings)] +#![feature(ptr_sub_ptr)] +#![feature(iter_advance_by)] +#![warn(missing_docs)] +#![warn(missing_doc_code_examples)] + +pub mod application; +pub mod orchestrator; +pub mod window_system; +pub mod render_system; +pub mod render_backend; +pub mod vulkan_render_backend; +pub mod render_debugger; +pub mod resource_manager; +pub mod shader_generator; +pub mod input_manager; +pub mod file_tracker; +pub mod beshader_compiler; +pub mod executor; +//pub mod gdeflate; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Extent { + pub width: u32, + pub height: u32, + pub depth: u32, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Vector2 { + pub x: f32, + pub y: f32, +} + +impl Vector2 { + pub fn new(x: f32, y: f32) -> Vector2 { + Vector2 { + x: x, + y: y, + } + } + + pub fn zero() -> Vector2 { + Vector2 { + x: 0.0, + y: 0.0, + } + } + + pub fn one() -> Vector2 { + Vector2 { + x: 1.0, + y: 1.0, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Vector3 { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl Vector3 { + pub fn new(x: f32, y: f32, z: f32) -> Vector3 { + Vector3 { + x: x, + y: y, + z: z, + } + } + + pub fn min() -> Vector3 { + Vector3 { + x: f32::MIN, + y: f32::MIN, + z: f32::MIN, + } + } + + pub fn max() -> Vector3 { + Vector3 { + x: f32::MAX, + y: f32::MAX, + z: f32::MAX, + } + } + + pub fn zero() -> Vector3 { + Vector3 { + x: 0.0, + y: 0.0, + z: 0.0, + } + } + + pub fn one() -> Vector3 { + Vector3 { + x: 1.0, + y: 1.0, + z: 1.0, + } + } + + pub fn x_axis() -> Vector3 { + Vector3 { + x: 1.0, + y: 0.0, + z: 0.0, + } + } + + pub fn y_axis() -> Vector3 { + Vector3 { + x: 0.0, + y: 1.0, + z: 0.0, + } + } + + pub fn z_axis() -> Vector3 { + Vector3 { + x: 0.0, + y: 0.0, + z: 1.0, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Quaternion { + pub x: f32, + pub y: f32, + pub z: f32, + pub w: f32, +} + +impl Quaternion { + pub fn new(x: f32, y: f32, z: f32, w: f32) -> Quaternion { + Quaternion { + x: x, + y: y, + z: z, + w: w, + } + } + + pub fn identity() -> Quaternion { + Quaternion { + x: 0.0, + y: 0.0, + z: 0.0, + w: 1.0, + } + } + + pub fn min() -> Quaternion { + Quaternion { + x: f32::MIN, + y: f32::MIN, + z: f32::MIN, + w: f32::MIN, + } + } + + pub fn max() -> Quaternion { + Quaternion { + x: f32::MAX, + y: f32::MAX, + z: f32::MAX, + w: f32::MAX, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct RGBA { + pub r: f32, + pub g: f32, + pub b: f32, + pub a: f32, +} + +fn insert_return_length(collection: &mut Vec, value: T) -> usize { + let length = collection.len(); + collection.push(value); + return length; +} \ No newline at end of file diff --git a/src/orchestrator.rs b/src/orchestrator.rs new file mode 100644 index 00000000..e47d2ae7 --- /dev/null +++ b/src/orchestrator.rs @@ -0,0 +1,217 @@ +//! The orchestrator synchronizes and manages most of the application data. +//! It contains systems and task to accomplish that feat. + +// pub struct Arc { +// inner: *mut u8, +// p: std::marker::PhantomData, +// } + +// impl Arc { +// fn new(inner: U) -> Arc { +// unsafe { +// let u = std::boxed::Box::new(inner); +// Arc { +// inner: std::boxed::Box::into_raw(u) as *mut u8, +// p: std::marker::PhantomData, +// } +// } +// } + +// fn jesus(&self) -> Arc { +// unsafe { +// Arc { +// inner: self.inner, +// p: std::marker::PhantomData, +// } +// } +// } +// } + +// impl std::ops::Deref for Arc { +// type Target = T; + +// fn deref(&self) -> &Self::Target { +// unsafe { &*(self.inner as *const T) } +// } +// } + +// TODO: implement Drop + +/// System handle is a handle to a system in an [`Orchestrator`] +pub struct SystemHandle(u32); + +/// A system is a collection of components and logic to operate on them. +pub trait System { + /// Casts a system to a [`std::any::Any`] reference. + fn as_any(&self) -> &dyn std::any::Any; +} + +/// An orchestrator is a collection of systems that are updated in parallel. +pub struct Orchestrator { + sep: std::sync::Mutex<(crate::executor::Executor, crate::executor::Spawner)>, + systems_data: SystemsData, + tasks: Vec, +} + +unsafe impl Send for Orchestrator {} + +struct SystemsData { + systems: Vec>>, +} + +trait SystemLock { + fn pls(&self) -> std::sync::Mutex<&T>; +} + +struct Task { + function: std::boxed::Box, +} + +type OrchestratorHandle = std::sync::Arc; + +impl Orchestrator { + pub fn new() -> Orchestrator { + Orchestrator { + sep: std::sync::Mutex::new(crate::executor::new_executor_and_spawner()), + systems_data: SystemsData { systems: Vec::new() }, + tasks: Vec::new(), + } + } + + pub fn initialize(&self) {} + pub fn deinitialize(&self) {} + + pub fn update(&mut self) { + for task in self.tasks.iter() { + (task.function)(self); + } + + self.tasks.clear(); + } + + pub fn add_system(&mut self, system: T) -> SystemHandle { + let system_handle = SystemHandle(self.systems_data.systems.len() as u32); + self.systems_data.systems.push(std::sync::Arc::new(std::sync::Mutex::new(system))); + system_handle + } + + pub fn execute_task_standalone(&self, task: impl std::future::Future + Send + 'static) { + self.sep.lock().unwrap().1.spawn(task); + } + + pub fn execute_task(&self, task: F) where F: FnOnce(std::sync::Arc>, OrchestratorHandle) -> R, R: std::future::Future + Send + 'static { + self.sep.lock().unwrap().1.spawn(async move { + }); + } + + // pub fn execute_task_2(&self, task: F) where F: FnOnce(std::sync::RwLock) -> R, R: std::future::Future + Send { + // self.sep.lock().unwrap().1.spawn(async move { + // task(std::sync::RwLock::new(self)).await; + // }); + // } + + pub fn execute_task_sync(&mut self, task: F) { + self.tasks.push(Task { function: std::boxed::Box::new(task) }); + } + + // pub fn get_system(&self, system_handle: SystemHandle) -> Arc where T: System + Send { + // self.systems_data.systems[system_handle.0 as usize].jesus() + // } +} + +#[cfg(test)] +mod tests { + use super::*; + + struct TestSystem { + value: u32, + } + + impl System for TestSystem { + fn as_any(&self) -> &dyn std::any::Any { + self + } + } + + impl TestSystem { + fn new() -> TestSystem { + TestSystem { value: 0 } + } + + async fn update(&mut self) { + self.value += 1; + } + + async fn task(&self, orchestrator: OrchestratorHandle) { + println!("{}", self.value); + } + + fn get_value(&self) -> u32 { + self.value + } + } + + #[test] + fn test_one_off_task() { + let mut orchestrator = Orchestrator::new(); + + let mut test_system_handle = TestSystem::new(); + + orchestrator.execute_task_standalone(async move { + assert_eq!(test_system_handle.get_value(), 0); + test_system_handle.update().await; + assert_eq!(test_system_handle.get_value(), 1); + }); + + orchestrator.update(); + } + + #[test] + fn test_systems() { + let mut orchestrator = Orchestrator::new(); + + let test_system = TestSystem::new(); + + let system_handle = orchestrator.add_system(test_system); + + //orchestrator.execute_task(TestSystem::task); + + orchestrator.update(); + } + + // #[test] + // fn test_parameters() { + // let mut orchestrator = Orchestrator::new(); + + // let mut test_system_handle = TestSystem::new(); + + // let task = || async move { + // assert_eq!(test_system_handle.get_value(), 0); + + // test_system_handle.update().await; + + // assert_eq!(test_system_handle.get_value(), 1); + // }; + + // orchestrator.execute_task_1(task); + + // orchestrator.update(); + // } + + #[test] + fn sync_task() { + let mut orchestrator = Orchestrator::new(); + + let test_system = TestSystem::new(); + + let system_handle = orchestrator.add_system(test_system); + + fn task(o: &Orchestrator) { + println!("howdy!"); + } + + orchestrator.execute_task_sync(task); + + orchestrator.update(); + } +} \ No newline at end of file diff --git a/src/render_backend.rs b/src/render_backend.rs new file mode 100644 index 00000000..88d2abc5 --- /dev/null +++ b/src/render_backend.rs @@ -0,0 +1,727 @@ +//! The RenderBackend trait is the interface between the engine and the graphics API. +//! It provides an abstraction layer for the graphics API(Vulkan, DX12, etc). +//! It is used by the engine to create and manage resources, and to submit commands to the GPU.\ +//! It is the lowest level abstraction for performing graphics operations. + +use crate::vulkan_render_backend; + +/// Enumerates the types of command buffers that can be created. +pub enum CommandBufferType { + /// A command buffer that can perform graphics operations. Draws, blits, presentations, etc. + GRAPHICS, + /// A command buffer that can perform compute operations. Dispatches, etc. + COMPUTE, + /// A command buffer that is optimized for transfer operations. Copies, etc. + TRANSFER +} + +/// Enumerates the types of buffers that can be created. +pub enum BufferType { + /// A buffer that can be used as a vertex buffer. + VERTEX, + /// A buffer that can be used as an index buffer. + INDEX, + /// A buffer that can be used as a uniform buffer. + UNIFORM, + /// A buffer that can be used as a storage buffer. + STORAGE, + /// A buffer that can be used as an indirect buffer. + INDIRECT +} + +/// Enumerates the types of shaders that can be created. +pub enum ShaderTypes { + /// A vertex shader. + Vertex, + /// A fragment shader. + Fragment, + /// A compute shader. + Compute +} + +#[derive(PartialEq, Eq, Clone, Copy)] +/// Enumerates the formats that textures can have. +pub enum TextureFormats { + /// 8 bit unsigned per component normalized RGBA. + RGBAu8, + /// 16 bit unsigned per component normalized RGBA. + RGBAu16, + /// 32 bit unsigned per component normalized RGBA. + RGBAu32, + /// 16 bit float per component RGBA. + RGBAf16, + /// 32 bit float per component RGBA. + RGBAf32, + /// 10 bit unsigned for R, G and 11 bit unsigned for B normalized RGB. + RGBu10u10u11, + /// 8 bit unsigned per component normalized BGRA. + BGRAu8, + /// 32 bit float depth. + Depth32, +} + +#[derive(Clone, Copy)] +/// Stores the information of a buffer. +pub union Buffer { + /// The information of a buffer. + pub vulkan_buffer: vulkan_render_backend::Buffer, +} + +#[derive(Clone, Copy)] +/// Stores the information of a descriptor set layout. +pub union DescriptorSetLayout { + /// The information of a descriptor set layout. + pub vulkan_descriptor_set_layout: vulkan_render_backend::DescriptorSetLayout, +} + +#[derive(Clone, Copy)] +/// Stores the information of a texture. +pub union Texture { + pub(crate) vulkan_texture: vulkan_render_backend::Texture, +} + +#[derive(Clone, Copy)] +/// Stores the information of a texture view. +pub union TextureView { + pub(crate) vulkan_texture_view: vulkan_render_backend::TextureView, +} + +#[derive(Clone, Copy)] +/// Stores the information of a shader. +pub union Shader { + /// The information of a shader. + pub vulkan_shader: vulkan_render_backend::Shader, +} + +#[derive(Clone, Copy)] +/// Stores the information of a swapchain. +pub union Swapchain { + /// The information of a swapchain. + pub vulkan_swapchain: vulkan_render_backend::Swapchain, +} + +#[derive(Clone, Copy)] +/// Stores the information of a surface. +pub union Surface { + /// The information of a surface. + pub vulkan_surface: vulkan_render_backend::Surface, +} + +#[derive(Clone, Copy)] +/// Stores the information of a synchronizer. +pub union Synchronizer { + /// The information of a synchronizer. + pub vulkan_synchronizer: vulkan_render_backend::Synchronizer, +} + +#[derive(Clone, Copy)] +/// Stores the information of a pipeline layout. +pub union PipelineLayout { + /// The information of a pipeline layout. + pub vulkan_pipeline_layout: vulkan_render_backend::PipelineLayout, +} + +#[derive(Clone, Copy)] +/// Stores the information of a pipeline. +pub union Pipeline { + /// The information of a pipeline. + pub vulkan_pipeline: vulkan_render_backend::Pipeline, +} + +#[derive(Clone, Copy)] +/// Stores the information of a command buffer. +pub union CommandBuffer { + /// The information of a command buffer. + pub vulkan_command_buffer: vulkan_render_backend::CommandBuffer, +} + +#[derive(Clone, Copy)] +/// Stores the information of an allocation. +pub struct Allocation { + pub(crate) vulkan_allocation: vulkan_render_backend::Allocation, + pub(crate) pointer: *mut u8, +} + +#[derive(Clone, Copy)] +/// Stores the information of a memory region. +pub struct Memory<'a> { + /// The allocation that the memory region is associated with. + pub allocation: &'a Allocation, + /// The offset of the memory region. + pub offset: u64, + /// The size of the memory region. + pub size: u64, +} + +#[derive(Clone, Copy)] +/// Stores the information of an attachment. +pub struct AttachmentInformation { + /// The texture view of the attachment. + pub texture_view: TextureView, + /// The format of the attachment. + pub format: TextureFormats, + /// The layout of the attachment. + pub layout: Layouts, + /// The clear color of the attachment. + pub clear: Option, + /// The resource uses of the attachment. + pub resource_use: Layouts, + /// Whether to load the contents of the attchment when starting a render pass. + pub load: bool, + /// Whether to store the contents of the attachment when ending a render pass. + pub store: bool, +} + +#[derive(Clone, Copy)] +/// Stores the information of a texture copy. +pub struct TextureCopy { + /// The source texture. + pub source: Texture, + /// The destination texture. + pub destination: Texture, + /// The images extent. + pub extent: crate::Extent, +} + +#[derive(Clone, Copy)] +/// Stores the information of a memory backed resource. +pub struct MemoryBackedResourceCreationResult { + pub(crate) resource: T, + pub(crate) size: u64, +} + +use bitflags::bitflags; + +bitflags! { + #[derive(Clone, Copy, PartialEq, Eq)] + /// Bit flags for the available access policies. + pub struct AccessPolicies : u8 { + /// Will perform read access. + const READ = 0b00000001; + /// Will perform write access. + const WRITE = 0b00000010; + } +} + +#[derive(Clone, Copy)] +/// Stores the information of a barrier. +pub enum Barrier { + /// A texture barrier. + Texture(Texture), +} + +bitflags! { + #[derive(Clone, Copy, PartialEq, Eq)] + /// Bit flags for the available pipeline stages. + pub struct Stages : u64 { + /// No stage. + const NONE = 0b00000000; + /// The vertex stage. + const VERTEX = 0b00000001; + /// The fragment stage. + const FRAGMENT = 0b00000010; + /// The compute stage. + const COMPUTE = 0b00000100; + /// The transfer stage. + const TRANSFER = 0b00001000; + } +} + +#[derive(Clone, Copy)] +/// Stores the information of a transition state. +pub struct TransitionState { + /// The stages this transition will either wait or block on. + pub stage: Stages, + /// The type of access that will be done on the resource by the process the operation that requires this transition. + pub access: AccessPolicies, + /// The layout of the resource. + pub layout: Layouts, +} + +/// Stores the information of a barrier descriptor. +pub struct BarrierDescriptor { + /// The barrier. + pub barrier: Barrier, + /// The state of the resource previous to the barrier. If None, the resource state will be discarded. + pub source: Option, + /// The state of the resource after the barrier. + pub destination: TransitionState, +} + +bitflags! { + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + /// Bit flags for the available resource uses. + pub struct Uses : u32 { + /// Resource will be used as a vertex buffer. + const Vertex = 1 << 0; + /// Resource will be used as an index buffer. + const Index = 1 << 1; + /// Resource will be used as a uniform buffer. + const Uniform = 1 << 2; + /// Resource will be used as a storage buffer. + const Storage = 1 << 3; + /// Resource will be used as an indirect buffer. + const Indirect = 1 << 4; + /// Resource will be used as a texture. + const Texture = 1 << 5; + /// Resource will be used as a render target. + const RenderTarget = 1 << 6; + /// Resource will be used as a depth stencil. + const DepthStencil = 1 << 7; + /// Resource will be used as an acceleration structure. + const AccelerationStructure = 1 << 8; + /// Resource will be used as a transfer source. + const TransferSource = 1 << 9; + /// Resource will be used as a transfer destination. + const TransferDestination = 1 << 10; + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +/// Enumerates the available layouts. +pub enum Layouts { + /// The layout is undefined. We don't mind what the layout is. + Undefined, + /// The texture will be used as render target. + RenderTarget, + /// The texture will be used in a transfer operation. + Transfer, + /// The texture will be used as a presentation source. + Present, + /// The texture will be used as a read only sample source. + Texture, +} + +#[derive(Clone, Copy)] +/// Enumerates the available descriptor types. +pub enum DescriptorType { + /// A uniform buffer. + UniformBuffer, + /// A storage buffer. + StorageBuffer, + /// A combined image sampler. + SampledImage, + /// A storage image. + StorageImage, + /// A sampler. + Sampler +} + +#[derive(Clone, Copy)] +/// Stores the information of a sampler. +pub struct Sampler { + /// The Vulkan backend implementation object for a sampler. + pub vulkan_sampler: vulkan_render_backend::Sampler, +} + +/// Stores the information of a descriptor set layout binding. +pub struct DescriptorSetLayoutBinding { + /// The binding of the descriptor set layout binding. + pub binding: u32, + /// The descriptor type of the descriptor set layout binding. + pub descriptor_type: DescriptorType, + /// The number of descriptors in the descriptor set layout binding. + pub descriptor_count: u32, + /// The stages the descriptor set layout binding will be used in. + pub stage_flags: Stages, + /// The immutable samplers of the descriptor set layout binding. + pub immutable_samplers: Option>, +} + +#[derive(Clone, Copy)] +/// Stores the information of a descriptor set. +pub union DescriptorSet { + /// The Vulkan backend implementation object for a descriptor set. + pub vulkan_descriptor_set: vulkan_render_backend::DescriptorSet, +} + +/// Stores the information of a descriptor. +pub enum DescriptorInfo { + /// A buffer descriptor. + Buffer { + /// The buffer of the descriptor. + buffer: Buffer, + /// The offset to start reading from inside the buffer. + offset: u64, + /// How much to read from the buffer after `offset`. + range: u64, + }, + /// A texture descriptor. + Texture { + /// The texture of the descriptor. + texture: TextureView, + /// The format of the texture. + format: TextureFormats, + /// The layout of the texture. + layout: Layouts, + }, + /// A sampler descriptor. + Sampler { + /// The sampler of the descriptor. + sampler: u32, + } +} + +/// Stores the information of a descriptor set write. +pub struct DescriptorSetWrite { + /// The descriptor set to write to. + pub descriptor_set: DescriptorSet, + /// The binding to write to. + pub binding: u32, + /// The index of the array element to write to in the binding(if the binding is an array). + pub array_element: u32, + /// The type of the descriptor. + pub descriptor_type: DescriptorType, + /// Information describing the descriptor. + pub descriptor_info: DescriptorInfo, +} + +/// Describes the details of the memory layout of a particular texture. +pub struct ImageSubresourceLayout { + /// The offset inside a memory region where the texture will read it's first texel from. + pub offset: u64, + /// The size of the texture in bytes. + pub size: u64, + /// The row pitch of the texture. + pub row_pitch: u64, + /// The array pitch of the texture. + pub array_pitch: u64, + /// The depth pitch of the texture. + pub depth_pitch: u64, +} + +/// Describes the properties of a particular surface. +pub struct SurfaceProperties { + /// The current extent of the surface. + pub extent: crate::Extent, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +/// Enumerates the states of a swapchain's validity for presentation. +pub enum SwapchainStates { + /// The swapchain is valid for presentation. + Ok, + /// The swapchain is suboptimal for presentation. + Suboptimal, + /// The swapchain can't be used for presentation. + Invalid, +} + +/// The RenderBackend trait is the interface between the engine and the graphics API. +/// It provides an abstraction layer for the graphics API(Vulkan, DX12, etc). +/// It is used by the engine to create and manage resources, and to submit commands to the GPU.\ +/// It is the lowest level abstraction for performing graphics operations. +pub trait RenderBackend { + + /// Creates a descriptor set layout. + /// Descriptor set layouts are used to describe the layout of a descriptor set. + fn create_descriptor_set_layout(&self, bindings: &[DescriptorSetLayoutBinding]) -> DescriptorSetLayout; + + /// Creates a pipeline layout. + /// Pipeline layouts are used to describe the layout of a pipeline. + /// Pipeline layouts are composed of descriptor set layouts and push constants. + fn create_pipeline_layout(&self, descriptor_set_layouts: &[DescriptorSetLayout]) -> PipelineLayout; + + /// Creates a descriptor set. + /// Descriptor sets are used to describe the resources used by a shader. + /// Descriptor sets are a particular instance of a descriptor set layout. + fn create_descriptor_set(&self, descriptor_set_layout: &DescriptorSetLayout, bindings: &[DescriptorSetLayoutBinding]) -> DescriptorSet; + + /// Writes to a descriptor set. + fn write_descriptors(&self, descriptor_set_writes: &[DescriptorSetWrite]); + + /// Creates a shader. + /// Shaders are used to describe the operations performed by the GPU. + /// + /// # Arguments + /// * `stage` - The type of shader to create. + /// * `shader` - The shader code. + fn create_shader(&self, stage: ShaderTypes, shader: &[u8]) -> Shader; + + /// Creates a pipeline. + /// Pipelines are used to describe the operations performed by the GPU. + /// + /// # Arguments + /// * `pipeline_layout` - The pipeline layout to use. + /// * `shaders` - The shaders to use. + fn create_pipeline(&self, pipeline_layout: &PipelineLayout, shaders: &[Shader]) -> Pipeline; + + /// Allocates a region of memory. + /// + /// # Arguments + /// * `size` - The size of the memory region to allocate. + /// * `device_accesses` - The device accesses that will be performed on the memory region. + /// + /// # Returns + /// * `Allocation` - The allocated memory region. + fn allocate_memory(&self, size: u64, device_accesses: crate::render_system::DeviceAccesses) -> Allocation; + + /// Returns a pointer to the start of the memory region. + /// + /// # Arguments + /// * `allocation` - The allocation to get the pointer for. + /// + /// # Returns + /// * `*mut u8` - A pointer to the start of the memory region. Null if the allocation is not mapped. + fn get_allocation_pointer(&self, allocation: &Allocation) -> *mut u8; + + /// Creates a buffer. + /// Buffers are used to store data on the GPU. + /// + /// # Arguments + /// * `size` - The size of the buffer. + /// * `resource_uses` - The resource uses of the buffer. + /// + /// # Returns + /// * `MemoryBackedResourceCreationResult` - The created buffer. + fn create_buffer(&self, size: u64, resource_uses: Uses) -> MemoryBackedResourceCreationResult; + + /// Creates a texture. + /// Textures are used to store images on the GPU. + /// + /// # Arguments + /// * `extent` - The extent of the texture. + /// * `format` - The format of the texture. + /// * `resource_uses` - The resource uses of the texture. + /// * `device_accesses` - The device accesses that will be performed on the texture. + /// * `access_policies` - The access policies of the texture. + /// * `mip_levels` - The number of mip levels of the texture. + /// + /// # Returns + /// * `MemoryBackedResourceCreationResult` - The created texture. + fn create_texture(&self, extent: crate::Extent, format: TextureFormats, resource_uses: Uses, device_accesses: crate::render_system::DeviceAccesses, access_policies: AccessPolicies, mip_levels: u32) -> MemoryBackedResourceCreationResult; + + /// Creates a sampler. + /// Samplers are used to describe how textures are sampled on the GPU. + /// + /// # Returns + /// * `Sampler` - The created sampler. + fn create_sampler(&self) -> Sampler; + + /// Gets tne memory layout of a texture. + /// + /// # Arguments + /// * `texture` - The texture to get the memory layout of. + /// * `mip_level` - The mip level to get the memory layout of. + /// + /// # Returns + /// * `ImageSubresourceLayout` - The memory layout of the texture. + fn get_image_subresource_layout(&self, texture: &Texture, mip_level: u32) -> ImageSubresourceLayout; + + /// Associates a buffer with a region of memory. + /// + /// # Arguments + /// * `memory` - The memory to associate the buffer with. + /// * `resource_creation_info` - The buffer to associate with the memory. + fn bind_buffer_memory(&self, memory: Memory, resource_creation_info: &MemoryBackedResourceCreationResult); + + /// Associates a texture with a region of memory. + /// + /// # Arguments + /// * `memory` - The memory to associate the texture with. + /// * `resource_creation_info` - The texture to associate with the memory. + fn bind_texture_memory(&self, memory: Memory, resource_creation_info: &MemoryBackedResourceCreationResult); + + /// Creates a synchronizer. + /// Synchronizers are used to synchronize operations between the CPU and GPU and GPU to GPU. + /// + /// # Arguments + /// * `signaled` - Whether the synchronizer should be intialized as signaled. + fn create_synchronizer(&self, signaled: bool) -> Synchronizer; + + /// Creates a texture view. + /// Texture views are used to describe how textures are accessed on the GPU. + /// + /// # Arguments + /// * `texture` - The texture to create the texture view for. + /// * `format` - The format of the texture view. + /// * `mip_levels` - The number of mip levels of the texture view. + /// + /// # Returns + /// * `TextureView` - The created texture view. + fn create_texture_view(&self, texture: &Texture, format: TextureFormats, mip_levels: u32) -> TextureView; + + /// Creates a surface. + /// Surfaces are used to describe the surface of a window. + /// + /// # Arguments + /// * `window_os_handles` - The OS handles of the window. + /// + /// # Returns + /// * `Surface` - The created surface. + fn create_surface(&self, window_os_handles: crate::window_system::WindowOsHandles) -> Surface; + + /// Gets the properties of a surface. + /// + /// # Arguments + /// * `surface` - The surface to get the properties of. + /// + /// # Returns + /// * `SurfaceProperties` - The properties of the surface. + fn get_surface_properties(&self, surface: &Surface) -> SurfaceProperties; + + /// Creates a swapchain. + /// Swapchains are used to describe the swapchain of a window. + /// + /// # Arguments + /// * `surface` - The surface to create the swapchain for. + /// * `extent` - The extent of the swapchain. + /// * `buffer_count` - The number of buffers in the swapchain. + /// + /// # Returns + /// * `Swapchain` - The created swapchain. + fn create_swapchain(&self, surface: &Surface, extent: crate::Extent, buffer_count: u32) -> Swapchain; + + /// Gets the images of a swapchain. + /// + /// # Arguments + /// * `swapchain` - The swapchain to get the images of. + /// + /// # Returns + /// * `Vec` - The images of the swapchain. + fn get_swapchain_images(&self, swapchain: &Swapchain) -> Vec; + + /// Creates a command buffer. + /// Command buffers are used to record commands to be executed on the GPU. + /// + /// # Arguments + /// + /// # Returns + /// * `CommandBuffer` - The created command buffer. + fn create_command_buffer(&self) -> CommandBuffer; + + /// Begins recording commands to a command buffer. + /// A command buffer must be set to recording mode before commands can be recorded to it. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to begin recording commands to. + fn begin_command_buffer_recording(&self, command_buffer: &CommandBuffer); + + /// Ends recording commands to a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to end recording commands to. + fn end_command_buffer_recording(&self, command_buffer: &CommandBuffer); + + /// Begins a render pass. + /// Render passes are used to describe the operations performed by the GPU. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to begin the render pass on. + /// * `extent` - The extent of the render pass. + /// * `attachments` - The attachments of the render pass. + fn start_render_pass(&self, command_buffer: &CommandBuffer, extent: crate::Extent, attachments: &[AttachmentInformation]); + + /// Ends a render pass. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to end the render pass on. + fn end_render_pass(&self, command_buffer: &CommandBuffer); + + /// Binds a shader to a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to bind the shader to. + /// * `shader` - The shader to bind. + fn bind_shader(&self, command_buffer: &CommandBuffer, shader: &Shader); + + /// Binds a pipeline to a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to bind the pipeline to. + /// * `pipeline` - The pipeline to bind. + fn bind_pipeline(&self, command_buffer: &CommandBuffer, pipeline: &Pipeline); + + /// Binds a push constant to a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to bind the push constant to. + /// * `pipeline_layout` - The pipeline layout to bind the push constant to. + /// * `offset` - The offset of the push constant. + /// * `data` - The data of the push constant. + fn write_to_push_constant(&self, command_buffer: &CommandBuffer, pipeline_layout: &PipelineLayout, offset: u32, data: &[u8]); + + /// Binds a descriptor set to a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to bind the descriptor set to. + /// * `pipeline_layout` - The pipeline layout to bind the descriptor set to. + /// * `descriptor_set` - The descriptor set to bind. + /// * `index` - The index of the descriptor set. + fn bind_descriptor_set(&self, command_buffer: &CommandBuffer, pipeline_layout: &PipelineLayout, descriptor_set: &DescriptorSet, index: u32); + + /// Binds a vertex buffer to a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to bind the vertex buffer to. + /// * `buffer` - The buffer to bind. + fn bind_vertex_buffer(&self, command_buffer: &CommandBuffer, buffer: &Buffer); + + /// Binds an index buffer to a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to bind the index buffer to. + /// * `buffer` - The buffer to bind. + fn bind_index_buffer(&self, command_buffer: &CommandBuffer, buffer: &Buffer); + + /// Performs a draw call. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to perform the draw call on. + /// * `index_count` - The number of indices to draw. + /// * `instance_count` - The number of instances to draw. + /// * `first_index` - The first index to draw. + /// * `vertex_offset` - The vertex offset. + /// * `first_instance` - The first instance to draw. + fn draw_indexed(&self, command_buffer: &CommandBuffer, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32); + + /// Performs a barrier. + /// Pipeline barriers synchronize memory accesses between commands. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to perform the barrier on. + /// * `barriers` - The barriers to perform. + fn execute_barriers(&self, command_buffer: &CommandBuffer, barriers: &[crate::render_backend::BarrierDescriptor]); + + /// Copies textures to other textures. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to perform the copy on. + /// * `copies` - The copies to perform. + fn copy_textures(&self, command_buffer: &CommandBuffer, copies: &[TextureCopy]); + + /// Executes a command buffer. + /// + /// # Arguments + /// * `command_buffer` - The command buffer to execute. + /// * `wait_for` - The synchronizer to wait for. + /// * `signal` - The synchronizer to signal. + fn execute(&self, command_buffer: &CommandBuffer, wait_for: Option<&crate::render_backend::Synchronizer>, signal: &crate::render_backend::Synchronizer); + + /// Acquires an image from a swapchain. + /// + /// # Arguments + /// * `swapchain` - The swapchain to acquire the image from. + /// * `image_available` - The synchronizer to signal when the image is available. + /// + /// # Returns + /// * `u32` - The index of the acquired image. + fn acquire_swapchain_image(&self, swapchain: &Swapchain, image_available: &Synchronizer) -> (u32, SwapchainStates); + + /// Presents an image to a swapchain. + /// + /// # Arguments + /// * `swapchain` - The swapchain to present the image to. + /// * `wait_for` - The synchronizer to wait for. + /// * `image_index` - The index of the image to present. + fn present(&self, swapchain: &Swapchain, wait_for: &Synchronizer, image_index: u32); + + /// Waits for a synchronizer. + /// + /// # Arguments + /// * `synchronizer` - The synchronizer to wait for. + fn wait(&self, synchronizer: &Synchronizer); + + /// Return the number of logs that have been created. + fn get_log_count(&self) -> u32; +} \ No newline at end of file diff --git a/src/render_debugger.rs b/src/render_debugger.rs new file mode 100644 index 00000000..796a2765 --- /dev/null +++ b/src/render_debugger.rs @@ -0,0 +1,34 @@ +//! # Render Debugger +//! +//! The render debugger module provides facilities to connect to a render debugger and capture frames for analysis and debugging. + +use renderdoc::{RenderDoc, V141}; + +/// The render debugger allow the application to connect to a render debugger and capture frames for analysis and debugging. +/// It provides an abstraction over different render debugging tools. +/// It supports RenderDoc. +pub struct RenderDebugger { + renderdoc: Option>, +} + +impl RenderDebugger { + /// Creates a new render debugger instance. + /// It will automatically detect any available render debugger and connect to it. + pub fn new() -> RenderDebugger { + RenderDebugger { renderdoc: RenderDoc::new().ok() } + } + + /// Starts a frame capture on the render debugger. + pub fn start_frame_capture(&mut self) { + if let Some(renderdoc) = &mut self.renderdoc { + renderdoc.start_frame_capture(std::ptr::null_mut(), std::ptr::null_mut()); + } + } + + /// Ends a frame capture on the render debugger. + pub fn end_frame_capture(&mut self) { + if let Some(renderdoc) = &mut self.renderdoc { + renderdoc.end_frame_capture(std::ptr::null_mut(), std::ptr::null_mut()); + } + } +} \ No newline at end of file diff --git a/src/render_system.rs b/src/render_system.rs new file mode 100644 index 00000000..ebbad55a --- /dev/null +++ b/src/render_system.rs @@ -0,0 +1,1916 @@ +//! The [`RenderSystem`] implements easy to use rendering functionality. +//! It provides useful abstractions to interact with the GPU. +//! It's not tied to any particular render pipeline implementation. + +use std::collections::HashMap; +use std::hash::Hasher; + +use crate::{window_system, orchestrator::System, Extent}; +use crate::{render_backend, insert_return_length, render_debugger}; + +/// Returns the best value from a slice of values based on a score function. +pub fn select_by_score(values: &[T], score: impl Fn(&T) -> i64) -> Option<&T> { + let mut best_score = -1 as i64; + let mut best_value: Option<&T> = None; + + for value in values { + let score = score(value); + + if score > best_score { + best_score = score; + best_value = Some(value); + } + } + + best_value +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct PipelineLayoutHandle(u32); + +struct PipelineLayout { + pipeline_layout: crate::render_backend::PipelineLayout, +} + +struct CommandBuffer { + frame_handle: Option, + next: Option, + command_buffer: crate::render_backend::CommandBuffer, +} + +struct Shader { + shader: crate::render_backend::Shader, +} + +struct Pipeline { + pipeline: crate::render_backend::Pipeline, +} + +struct Texture { + frame_handle: Option, + next: Option, + parent: Option, + texture: crate::render_backend::Texture, + texture_view: Option, + allocation_handle: AllocationHandle, + extent: Extent, + role: String, +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct SamplerHandle(u32); + +struct Sampler { + sampler: render_backend::Sampler, +} + +pub enum ShaderSourceType { + GLSL, + SPIRV, +} + +#[derive(Hash)] +pub enum DataTypes { + Float, + Float2, + Float3, + Float4, + Int, + Int2, + Int3, + Int4, + UInt, + UInt2, + UInt3, + UInt4, +} + +#[derive(Hash)] +pub struct VertexElement { + pub name: String, + pub format: DataTypes, + pub shuffled: bool, +} + +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct BufferHandle(u32); + +struct Buffer { + frame_handle: Option, + next: Option, + buffer: crate::render_backend::Buffer, + size: u64, + pointer: *mut u8, +} + +struct Mesh { + vertex_buffer: Buffer, + index_buffer: Buffer, + vertex_layout_hash: u64, + index_count: u32, +} + +struct Allocation { + allocation: crate::render_backend::Allocation, +} + +use bitflags::bitflags; + +bitflags! { + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + pub struct DeviceAccesses: u16 { + const CpuRead = 1 << 0; + const CpuWrite = 1 << 1; + const GpuRead = 1 << 2; + const GpuWrite = 1 << 3; + } +} + +#[derive(Clone, Copy)] +pub struct CommandBufferHandle(u32); + +struct Synchronizer { + frame_handle: Option, + next: Option, + synchronizer: crate::render_backend::Synchronizer, +} + +pub struct ShaderHandle(u32); +pub struct PipelineHandle(u32); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct TextureHandle(u32); + +pub struct MeshHandle(u32); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct SurfaceHandle(u32); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct SynchronizerHandle(u32); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct DescriptorSetLayoutHandle(u32); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct DescriptorSetHandle(u32); + +pub struct AttachmentInfo { + pub(crate) texture: TextureHandle, + pub(crate) format: crate::render_backend::TextureFormats, + pub(crate) clear: Option, + pub(crate) load: bool, + pub(crate) store: bool, +} + +pub struct CommandBufferRecording<'a> { + render_system: &'a RenderSystem, + command_buffer: CommandBufferHandle, + frame_handle: Option, + in_render_pass: bool, + /// `texture_states` is used to perform resource tracking on textures.\ It is mainly useful for barriers and transitions and copies. + texture_states: HashMap, +} + +impl CommandBufferRecording<'_> { + pub fn new(render_system: &'_ RenderSystem, command_buffer: CommandBufferHandle, frame_handle: Option) -> CommandBufferRecording<'_> { + CommandBufferRecording { + render_system, + command_buffer, + frame_handle, + in_render_pass: false, + texture_states: HashMap::new(), + } + } + + /// Retrieves the current state of a texture.\ + /// If the texture has no known state, it will return a default state with undefined layout. This is useful for the first transition of a texture.\ + /// If the texture has a known state, it will return the known state. + fn get_texture_state(&self, texture_handle: TextureHandle) -> Option { + if let Some(state) = self.texture_states.get(&texture_handle) { + Some(*state) + } else { + None + } + } + + /// Inserts or updates state for a texture.\ + /// If the texture has no known state, it will insert the given state.\ + /// If the texture has a known state, it will update it with the given state. + /// It will return the given state. + /// This is useful to perform a transition on a texture. + fn upsert_texture_state(&mut self, texture_handle: TextureHandle, texture_state: crate::render_backend::TransitionState) -> crate::render_backend::TransitionState { + self.texture_states.insert(texture_handle, texture_state); + texture_state + } + + /// Enables recording on the command buffer. + pub fn begin(&self) { + self.render_system.render_backend.begin_command_buffer_recording(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer); + } + + /// Starts a render pass on the GPU. + /// A render pass is a particular configuration of render targets which will be used simultaneously to render certain imagery. + pub fn start_render_pass(&mut self, extent: Extent, attachments: &[AttachmentInfo]) { + let barriers = attachments.iter().map(|attachment| crate::render_backend::BarrierDescriptor { + barrier: crate::render_backend::Barrier::Texture(self.render_system.get_texture(self.frame_handle, attachment.texture).texture), + source: self.get_texture_state(attachment.texture), + destination: self.upsert_texture_state(attachment.texture, crate::render_backend::TransitionState { + layout: crate::render_backend::Layouts::RenderTarget, + stage: crate::render_backend::Stages::FRAGMENT, + access: crate::render_backend::AccessPolicies::WRITE, + }), + }).collect::>(); + + self.render_system.render_backend.execute_barriers(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &barriers); + + let mut attachment_information = Vec::new(); + + for attachment in attachments { + attachment_information.push(crate::render_backend::AttachmentInformation { + texture_view: self.render_system.get_texture(self.frame_handle, attachment.texture).texture_view.unwrap(), + format: attachment.format, + layout: crate::render_backend::Layouts::RenderTarget, + clear: attachment.clear, + resource_use: crate::render_backend::Layouts::RenderTarget, + load: attachment.load, + store: attachment.store, + }); + } + + self.render_system.render_backend.start_render_pass(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, extent, &attachment_information); + + self.in_render_pass = true; + } + + /// Ends a render pass on the GPU. + pub fn end_render_pass(&mut self) { + self.render_system.render_backend.end_render_pass(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer); + self.in_render_pass = false; + } + + /// Binds a shader to the GPU. + pub fn bind_shader(&self, shader_handle: ShaderHandle) { + self.render_system.render_backend.bind_shader(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &self.render_system.shaders[shader_handle.0 as usize].shader); + } + + /// Binds a pipeline to the GPU. + pub fn bind_pipeline(&mut self, pipeline_handle: &PipelineHandle) { + self.render_system.render_backend.bind_pipeline(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &self.render_system.pipelines[pipeline_handle.0 as usize].pipeline); + } + + /// Writes to the push constant register. + pub fn write_to_push_constant(&mut self, pipeline_layout_handle: &PipelineLayoutHandle, offset: u32, data: &[u8]) { + self.render_system.render_backend.write_to_push_constant(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &self.render_system.pipeline_layouts[pipeline_layout_handle.0 as usize].pipeline_layout, offset, data); + } + + /// Draws a render system mesh. + pub fn draw_mesh(&mut self, mesh_handle: &MeshHandle) { + let mesh = &self.render_system.meshes[mesh_handle.0 as usize]; + + self.render_system.render_backend.bind_vertex_buffer(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &mesh.vertex_buffer.buffer); + self.render_system.render_backend.bind_index_buffer(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &mesh.index_buffer.buffer); + + self.render_system.render_backend.draw_indexed(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, mesh.index_count, 1, 0, 0, 0); + } + + /// Performs a transition on a series of textures. + /// A transition is a change in layout, stage and access. + /// The `keep_old` parameter determines whether the texture's contents should be kept or discarded. + /// The `layout` parameter determines the new layout of the texture. + /// The `stage` parameter determines the new stage of the texture. + /// The `access` parameter determines the new access of the texture. + /// The resource states are automatically tracked. + pub fn transition_textures(&mut self, transitions: &[(TextureHandle, bool, crate::render_backend::Layouts, crate::render_backend::Stages, crate::render_backend::AccessPolicies)]) { + let mut barriers = Vec::new(); + + for (texture_handle, keep_old, layout, stage, access) in transitions { + barriers.push(crate::render_backend::BarrierDescriptor { + barrier: crate::render_backend::Barrier::Texture(self.render_system.get_texture(self.frame_handle, *texture_handle).texture), + source: if *keep_old { self.get_texture_state(*texture_handle) } else { None }, + destination: self.upsert_texture_state(*texture_handle, crate::render_backend::TransitionState { layout: *layout, stage: *stage, access: *access, }), + }); + } + + self.render_system.render_backend.execute_barriers(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &barriers); + } + + /// Copies texture data from a CPU accessible buffer to a GPU accessible texture. + pub fn write_texture_data(&mut self, texture_handle: TextureHandle, data: &[RGBAu8]) { + let source_texture_res = self.render_system.textures.iter().enumerate().find(|(_, texture)| if let Some(parent) = texture.parent { parent == texture_handle && texture.role == "CPU_WRITE" } else { false }).unwrap(); + + let source_texture = &self.render_system.textures[source_texture_res.0 as usize]; + let destination_texture = &self.render_system.textures[texture_handle.0 as usize]; + + let allocation = &self.render_system.allocations[source_texture.allocation_handle.0 as usize]; + + let pointer = self.render_system.render_backend.get_allocation_pointer(&allocation.allocation); + + let subresource_layout = self.render_system.render_backend.get_image_subresource_layout(&source_texture.texture, 0); + + if pointer.is_null() { + for i in data.len()..source_texture.extent.width as usize * source_texture.extent.height as usize * source_texture.extent.depth as usize { + unsafe { + std::ptr::write(pointer.offset(i as isize), if i % 4 == 0 { 255 } else { 0 }); + } + } + } else { + let pointer = unsafe { pointer.offset(subresource_layout.offset as isize) }; + + for i in 0..source_texture.extent.height { + let pointer = unsafe { pointer.offset(subresource_layout.row_pitch as isize * i as isize) }; + + unsafe { + std::ptr::copy_nonoverlapping((data.as_ptr().add(i as usize * source_texture.extent.width as usize)) as *mut u8, pointer, source_texture.extent.width as usize * 4); + } + } + } + + let source_texture_handle = TextureHandle(source_texture_res.0 as u32); + let destination_texture_handle = texture_handle; + + self.transition_textures(&[ + (source_texture_handle, false, crate::render_backend::Layouts::Transfer, crate::render_backend::Stages::TRANSFER, crate::render_backend::AccessPolicies::READ), // Source texture + (destination_texture_handle, false, crate::render_backend::Layouts::Transfer, crate::render_backend::Stages::TRANSFER, crate::render_backend::AccessPolicies::WRITE), // Destination texture + ]); + + let texture_copy = crate::render_backend::TextureCopy { + source: source_texture.texture, + destination: destination_texture.texture, + extent: source_texture.extent, + }; + + self.render_system.render_backend.copy_textures(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &[texture_copy]); + + self.transition_textures(&[ + (texture_handle, true, crate::render_backend::Layouts::Texture, crate::render_backend::Stages::FRAGMENT, crate::render_backend::AccessPolicies::READ), // Destination texture + ]); + } + + /// Performs a series of texture copies. + pub fn copy_textures(&mut self, copies: &[(TextureHandle, crate::render_backend::Layouts, crate::render_backend::Stages, crate::render_backend::AccessPolicies, TextureHandle, crate::render_backend::Layouts, crate::render_backend::Stages, crate::render_backend::AccessPolicies)]) { + let mut transitions = Vec::new(); + + for (f, fl, fs, fap, t, tl, ts, tap) in copies { + transitions.push((*f, true, *fl, *fs, *fap)); + transitions.push((*t, false, *tl, *ts, *tap)); + } + + self.transition_textures(&transitions); + + let mut texture_copies = Vec::new(); + + for (f, _, _, _, t, _, _, _) in copies { + texture_copies.push(crate::render_backend::TextureCopy { + source: self.render_system.get_texture(self.frame_handle, *f).texture, + destination: self.render_system.get_texture(self.frame_handle, *t).texture, + extent: self.render_system.get_texture(self.frame_handle, *f).extent, + }); + } + + self.render_system.render_backend.copy_textures(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &texture_copies); + } + + /// Copies GPU accessible texture data to a CPU accessible buffer. + pub fn synchronize_texture(&mut self, texture_handle: TextureHandle) { + let mut texture_copies = Vec::new(); + + let texture = self.render_system.get_texture(self.frame_handle, texture_handle); + + let copy_dst_texture = self.render_system.textures.iter().enumerate().find(|(_, texture)| texture.parent == Some(texture_handle) && texture.role == "CPU_READ"); + + let source_texture_handle = texture_handle; + let destination_texture_handle = TextureHandle(copy_dst_texture.unwrap().0 as u32); + + let transitions = [ + (source_texture_handle, true, crate::render_backend::Layouts::Transfer, crate::render_backend::Stages::TRANSFER, crate::render_backend::AccessPolicies::READ), + (destination_texture_handle, false, crate::render_backend::Layouts::Transfer, crate::render_backend::Stages::TRANSFER, crate::render_backend::AccessPolicies::WRITE) + ]; + + self.transition_textures(&transitions); + + texture_copies.push(crate::render_backend::TextureCopy { + source: texture.texture, + destination: copy_dst_texture.unwrap().1.texture, + extent: texture.extent, + }); + + self.render_system.render_backend.copy_textures(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &texture_copies); + } + + /// Ends recording on the command buffer. + pub fn end(&mut self) { + if self.in_render_pass { + self.render_system.render_backend.end_render_pass(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer); + } + + if let Some(surface) = &self.render_system.surface { + //barrier: crate::render_backend::Barrier::Texture(self.render_system.textures[surface.textures[self.frame_handle.unwrap().0 as usize].0 as usize].texture), + + let transitions = [ + (surface.textures[self.frame_handle.unwrap().0 as usize], true, crate::render_backend::Layouts::Present, crate::render_backend::Stages::TRANSFER, crate::render_backend::AccessPolicies::READ), + ]; + + self.transition_textures(&transitions); + } + + self.render_system.render_backend.end_command_buffer_recording(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer); + } + + /// Binds a decriptor set on the GPU. + pub fn bind_descriptor_set(&self, pipeline_layout: PipelineLayoutHandle, arg: u32, descriptor_set_handle: &DescriptorSetHandle) { + self.render_system.render_backend.bind_descriptor_set(&self.render_system.command_buffers[self.command_buffer.0 as usize].command_buffer, &self.render_system.pipeline_layouts[pipeline_layout.0 as usize].pipeline_layout, &self.render_system.descriptor_sets[descriptor_set_handle.0 as usize].descriptor_set, arg); + } +} + +pub struct AllocationHandle(u64); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct FrameHandle(u32); + +struct Frame {} + +struct Surface { + surface: crate::render_backend::Surface, + swapchain: crate::render_backend::Swapchain, + textures: Vec, +} + +pub struct DescriptorSetLayout { + descriptor_set_layout: render_backend::DescriptorSetLayout, +} + +pub struct DescriptorSet { + descriptor_set: render_backend::DescriptorSet, +} + +pub enum Descriptor { + Buffer(BufferHandle), + Texture(TextureHandle), +} + +pub struct DescriptorWrite { + descriptor_set: DescriptorSetHandle, + binding: u32, + array_element: u32, + descriptor: Descriptor, +} + +pub struct DescriptorSetLayoutBinding { + pub binding: u32, + pub descriptor_type: render_backend::DescriptorType, + pub descriptor_count: u32, + pub stage_flags: render_backend::Stages, + pub immutable_samplers: Option>, +} + +/// The [`RenderSystem`] implements easy to use rendering functionality. +/// It is a wrapper around the [`render_backend::RenderBackend`]. +/// It is responsible for creating and managing resources. +/// It also provides a [`CommandBufferRecording`] struct that can be used to record commands. +pub struct RenderSystem { + render_backend: Box, + debugger: crate::render_debugger::RenderDebugger, + allocations: Vec, + buffers: Vec, + textures: Vec, + samplers: Vec, + descriptor_set_layouts: Vec, + pipeline_layouts: Vec, + descriptor_sets: Vec, + shaders: Vec, + pipelines: Vec, + command_buffers: Vec, + meshes: Vec, + surface: Option, + synchronizers: Vec, + frames: Vec, +} + +impl RenderSystem { + /// Creates a new [`RenderSystem`]. + pub fn new() -> RenderSystem { + let render_backend = Box::new(crate::vulkan_render_backend::VulkanRenderBackend::new()); + + let render_system = RenderSystem { + render_backend, + debugger: render_debugger::RenderDebugger::new(), + allocations: Vec::new(), + buffers: Vec::new(), + textures: Vec::new(), + samplers: Vec::new(), + descriptor_set_layouts: Vec::new(), + pipeline_layouts: Vec::new(), + descriptor_sets: Vec::new(), + shaders: Vec::new(), + pipelines: Vec::new(), + command_buffers: Vec::new(), + meshes: Vec::new(), + surface: None, + synchronizers: Vec::new(), + frames: Vec::new(), + }; + + render_system + } + + pub fn has_errors(&self) -> bool { + self.render_backend.get_log_count() > 0 + } + + /// Creates a new frame + /// A frame let's the render system know how many queued frames it can have + pub fn create_frame(&mut self) -> FrameHandle { + FrameHandle(insert_return_length(&mut self.frames, Frame {}) as u32) + } + + /// Creates a new allocation from a managed allocator for the underlying GPU allocations. + pub fn create_allocation(&mut self, size: u64, _resource_uses: render_backend::Uses, resource_device_accesses: DeviceAccesses) -> AllocationHandle { + let allocation = self.render_backend.allocate_memory(size, resource_device_accesses); + + let allocation_handle = AllocationHandle(self.allocations.len() as u64); + + self.allocations.push(Allocation { + allocation, + }); + + allocation_handle + } + + pub fn add_mesh_from_vertices_and_indices(&mut self, vertices: &[u8], indices: &[u8], vertex_layout: &[VertexElement]) -> MeshHandle { + //self.render_backend.add_mesh_from_vertices_and_indices(vertices, indices); + + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + + std::hash::Hash::hash_slice(&vertex_layout, &mut hasher); + + let vertex_layout_hash = hasher.finish(); + + let vertex_buffer_size = vertices.len() as u64; + let vertex_buffer_offset = 0; + let vertex_buffer_creation_result = self.render_backend.create_buffer(vertex_buffer_size, render_backend::Uses::Vertex); + let index_buffer_size = indices.len() as u64; + let index_buffer_offset = vertices.len() as u64 + 15 & !15; + let index_buffer_creation_result = self.render_backend.create_buffer(index_buffer_size, render_backend::Uses::Index); + + let allocation_handle = self.create_allocation(vertex_buffer_creation_result.size + index_buffer_creation_result.size + 64, render_backend::Uses::Vertex | render_backend::Uses::Index, DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead); + + let allocation = &self.allocations[allocation_handle.0 as usize]; + + self.render_backend.bind_buffer_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: vertex_buffer_offset, size: vertex_buffer_size }, &vertex_buffer_creation_result); + self.render_backend.bind_buffer_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: index_buffer_offset, size: index_buffer_size }, &index_buffer_creation_result); + + unsafe { + let vertex_buffer_pointer = self.render_backend.get_allocation_pointer(&allocation.allocation).offset(vertex_buffer_offset as isize); + std::ptr::copy_nonoverlapping(vertices.as_ptr(), vertex_buffer_pointer, vertex_buffer_size as usize); + let index_buffer_pointer = self.render_backend.get_allocation_pointer(&allocation.allocation).offset(index_buffer_offset as isize); + std::ptr::copy_nonoverlapping(indices.as_ptr(), index_buffer_pointer, index_buffer_size as usize); + } + + let mesh_handle = MeshHandle(self.meshes.len() as u32); + + self.meshes.push(Mesh { + vertex_buffer: Buffer { + frame_handle: None, + next: None, + buffer: vertex_buffer_creation_result.resource, + size: vertex_buffer_creation_result.size, + pointer: std::ptr::null_mut(), + }, + index_buffer: Buffer { + frame_handle: None, + next: None, + buffer: index_buffer_creation_result.resource, + size: index_buffer_creation_result.size, + pointer: std::ptr::null_mut(), + }, + vertex_layout_hash, + index_count: indices.len() as u32 / 4, + }); + + mesh_handle + } + + /// Creates a shader. + pub fn add_shader(&mut self, _shader_source_type: ShaderSourceType, shader: &[u8]) -> ShaderHandle { + let compiler = shaderc::Compiler::new().unwrap(); + let mut options = shaderc::CompileOptions::new().unwrap(); + + options.set_optimization_level(shaderc::OptimizationLevel::Performance); + options.set_target_env(shaderc::TargetEnv::Vulkan, shaderc::EnvVersion::Vulkan1_2 as u32); + options.set_generate_debug_info(); + options.set_target_spirv(shaderc::SpirvVersion::V1_5); + options.set_invert_y(true); + + let shader_text = std::str::from_utf8(shader).unwrap(); + + let binary = compiler.compile_into_spirv(shader_text, shaderc::ShaderKind::InferFromSource, "shader_name", "main", Some(&options)); + + let shader_handle = ShaderHandle(self.shaders.len() as u32); + + let shader_stage: String = shader_text.find("#pragma shader_stage(").map(|index| shader_text[index + 21..].split(')').next().unwrap().to_string()).unwrap_or(String::from("")); + + let shader_stage = match shader_stage.as_str() { + "vertex" => { + crate::render_backend::ShaderTypes::Vertex + }, + "fragment" => { + crate::render_backend::ShaderTypes::Fragment + }, + _ => { + crate::render_backend::ShaderTypes::Vertex + }, + }; + + match binary { + Ok(binary) => { + self.shaders.push(Shader { + shader: self.render_backend.create_shader(shader_stage, binary.as_binary_u8()) + }); + + shader_handle + }, + Err(error) => { + println!("Error compiling shader: {}", error); + + shader_handle + } + } + } + + pub fn create_descriptor_set_layout(&mut self, bindings: &[DescriptorSetLayoutBinding]) -> DescriptorSetLayoutHandle { + let bindings = bindings.iter().map(|binding| crate::render_backend::DescriptorSetLayoutBinding { + binding: binding.binding, + descriptor_type: binding.descriptor_type, + descriptor_count: binding.descriptor_count, + stage_flags: binding.stage_flags, + immutable_samplers: binding.immutable_samplers.as_ref().map(|immutable_samplers| immutable_samplers.iter().map(|sampler_handle| self.samplers[sampler_handle.0 as usize].sampler).collect::>()), + }).collect::>(); + + let descriptor_set_layout = self.render_backend.create_descriptor_set_layout(&bindings); + + let descriptor_set_layout_handle = DescriptorSetLayoutHandle(self.descriptor_set_layouts.len() as u32); + + self.descriptor_set_layouts.push(DescriptorSetLayout { + descriptor_set_layout, + }); + + descriptor_set_layout_handle + } + + pub fn create_descriptor_set(&mut self, descriptor_set_layout_handle: &DescriptorSetLayoutHandle, bindings: &[DescriptorSetLayoutBinding]) -> DescriptorSetHandle { + let bindings = bindings.iter().map(|binding| crate::render_backend::DescriptorSetLayoutBinding { + binding: binding.binding, + descriptor_type: binding.descriptor_type, + descriptor_count: binding.descriptor_count, + stage_flags: binding.stage_flags, + immutable_samplers: binding.immutable_samplers.as_ref().map(|immutable_samplers| immutable_samplers.iter().map(|sampler_handle| self.samplers[sampler_handle.0 as usize].sampler).collect::>()), + }).collect::>(); + + let descriptor_set_layout = &self.descriptor_set_layouts[descriptor_set_layout_handle.0 as usize]; + + let descriptor_set = self.render_backend.create_descriptor_set(&descriptor_set_layout.descriptor_set_layout, &bindings); + + let descriptor_set_handle = DescriptorSetHandle(self.descriptor_sets.len() as u32); + + self.descriptor_sets.push(DescriptorSet { + descriptor_set, + }); + + descriptor_set_handle + } + + pub fn write(&self, descriptor_set_writes: &[DescriptorWrite]) { + let descriptor_set_writes = descriptor_set_writes.iter().map(|descriptor_write| crate::render_backend::DescriptorSetWrite { + descriptor_set: self.descriptor_sets[descriptor_write.descriptor_set.0 as usize].descriptor_set, + binding: descriptor_write.binding, + array_element: descriptor_write.array_element, + descriptor_type: match descriptor_write.descriptor { + Descriptor::Buffer(_) => crate::render_backend::DescriptorType::UniformBuffer, + Descriptor::Texture(_) => crate::render_backend::DescriptorType::SampledImage, + }, + descriptor_info: match descriptor_write.descriptor { + Descriptor::Buffer(buffer_handle) => crate::render_backend::DescriptorInfo::Buffer{ buffer: self.buffers[buffer_handle.0 as usize].buffer, offset: 0, range: 64 }, + Descriptor::Texture(texture_handle) => crate::render_backend::DescriptorInfo::Texture{ texture: self.textures[texture_handle.0 as usize].texture_view.unwrap(), format: render_backend::TextureFormats::RGBAu8, layout: render_backend::Layouts::Texture, }, + }, + }).collect::>(); + + self.render_backend.write_descriptors(&descriptor_set_writes); + } + + pub fn create_pipeline_layout(&mut self, descriptor_set_layout_handles: &[DescriptorSetLayoutHandle]) -> PipelineLayoutHandle { + let pipeline_layout = self.render_backend.create_pipeline_layout(&descriptor_set_layout_handles.iter().map(|descriptor_set_layout_handle| self.descriptor_set_layouts[descriptor_set_layout_handle.0 as usize].descriptor_set_layout).collect::>()); + PipelineLayoutHandle(insert_return_length(&mut self.pipeline_layouts, PipelineLayout{ pipeline_layout }) as u32) + } + + pub fn create_pipeline(&mut self, pipeline_layout_handle: PipelineLayoutHandle, shader_handles: &[ShaderHandle]) -> PipelineHandle { + let shaders = shader_handles.iter().map(|shader_handle| self.shaders[shader_handle.0 as usize].shader).collect::>(); + + let pipeline_layout = &self.pipeline_layouts[pipeline_layout_handle.0 as usize]; + + let pipeline = self.render_backend.create_pipeline(&pipeline_layout.pipeline_layout, shaders.as_slice()); + + let pipeline_handle = PipelineHandle(self.pipelines.len() as u32); + + self.pipelines.push(Pipeline { + pipeline, + }); + + pipeline_handle + } + + pub fn create_command_buffer(&mut self) -> CommandBufferHandle { + let command_buffer_handle = CommandBufferHandle(self.command_buffers.len() as u32); + + let mut previous_command_buffer_handle: Option = None; + + for i in 0..self.frames.len() { + let command_buffer_handle = CommandBufferHandle(self.command_buffers.len() as u32); + + self.command_buffers.push(CommandBuffer { + frame_handle: Some(FrameHandle(i as u32)), + next: None, + command_buffer: self.render_backend.create_command_buffer(), + }); + + if let Some(previous_command_buffer_handle) = previous_command_buffer_handle { + self.command_buffers[previous_command_buffer_handle.0 as usize].next = Some(command_buffer_handle); + } + + previous_command_buffer_handle = Some(command_buffer_handle); + } + + command_buffer_handle + } + + pub fn create_command_buffer_recording(&self, frame_handle: Option, command_buffer_handle: CommandBufferHandle) -> CommandBufferRecording { + let recording = CommandBufferRecording::new(self, self.get_command_buffer_handle(frame_handle, command_buffer_handle), frame_handle); + recording.begin(); + recording + } + + /// Creates a new buffer.\ + /// If the access includes [`DeviceAccesses::CpuWrite`] and [`DeviceAccesses::GpuRead`] then multiple buffers will be created, one for each frame.\ + /// Staging buffers MAY be created if there's is not sufficient CPU writable, fast GPU readable memory.\ + /// + /// # Arguments + /// + /// * `size` - The size of the buffer in bytes. + /// * `resource_uses` - The uses of the buffer. + /// * `device_accesses` - The accesses of the buffer. + /// + /// # Returns + /// + /// The handle of the buffer. + /// + /// # Example + /// + /// ```rust + /// let buffer_handle = render_system.create_buffer(1024, render_system::render_backend::Uses::Vertex, render_system::DeviceAccesses::CpuWrite | render_system::DeviceAccesses::GpuRead); + /// ``` + pub fn create_buffer(&mut self, size: usize, resource_uses: render_backend::Uses, device_accesses: DeviceAccesses) -> BufferHandle { + let buffer_handle = BufferHandle(self.buffers.len() as u32); + + let mut previous_buffer_handle: Option = None; + + if device_accesses.contains(DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead) { + for i in 0..self.frames.len() { + let buffer_handle = BufferHandle(self.buffers.len() as u32); + + let buffer_creation_result = self.render_backend.create_buffer(size as u64, resource_uses); + + let allocation_handle = self.create_allocation(buffer_creation_result.size, resource_uses, device_accesses); + + let allocation = &self.allocations[allocation_handle.0 as usize]; + + self.render_backend.bind_buffer_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: 0, size: size as u64 }, &buffer_creation_result); + + let pointer = self.render_backend.get_allocation_pointer(&allocation.allocation); + + self.buffers.push(Buffer { + frame_handle: Some(FrameHandle(i as u32)), + next: None, + buffer: buffer_creation_result.resource, + size: buffer_creation_result.size, + pointer, + }); + + if let Some(previous_buffer_handle) = previous_buffer_handle { + self.buffers[previous_buffer_handle.0 as usize].next = Some(buffer_handle); + } + + previous_buffer_handle = Some(buffer_handle); + } + } + + buffer_handle + } + + pub fn get_buffer_pointer(&mut self, frame_handle: Option, buffer_handle: BufferHandle) -> *mut u8 { + let buffer_handle = self.get_buffer_handle(frame_handle, buffer_handle); + let buffer = &mut self.buffers[buffer_handle.0 as usize]; + buffer.pointer + } + + pub fn get_buffer_slice(&mut self, frame_handle: Option, buffer_handle: BufferHandle) -> &[u8] { + let buffer_handle = self.get_buffer_handle(frame_handle, buffer_handle); + let buffer = &mut self.buffers[buffer_handle.0 as usize]; + unsafe { + std::slice::from_raw_parts(buffer.pointer, buffer.size as usize) + } + } + + pub fn create_texture(&mut self, extent: crate::Extent, format: crate::render_backend::TextureFormats, resource_uses: render_backend::Uses, device_accesses: DeviceAccesses) -> TextureHandle { + let size = extent.width as u64 * extent.height as u64 * extent.depth as u64 * 4; + + dbg!(device_accesses); + + // CPU readeble render target + if device_accesses == DeviceAccesses::CpuRead | DeviceAccesses::GpuWrite { + let texture_creation_result = self.render_backend.create_texture(extent, format, render_backend::Uses::TransferDestination, DeviceAccesses::CpuRead, crate::render_backend::AccessPolicies::READ, 1); + + let allocation_handle = self.create_allocation(texture_creation_result.size, resource_uses, DeviceAccesses::CpuRead); + + let allocation = &self.allocations[allocation_handle.0 as usize]; + + self.render_backend.bind_texture_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: 0, size: size }, &texture_creation_result); + + //let texture_view = self.render_backend.create_texture_view(&texture_creation_result.resource, format, 1); + + let proxy_texture_handle = TextureHandle(self.textures.len() as u32); + + self.textures.push(Texture { + frame_handle: Some(FrameHandle(0)), + next: None, + parent: None, + texture: texture_creation_result.resource, + texture_view: None, + allocation_handle, + extent, + role: String::from("CPU_READ"), + }); + + let texture_creation_result = self.render_backend.create_texture(extent, format, resource_uses | render_backend::Uses::TransferSource, DeviceAccesses::GpuWrite, crate::render_backend::AccessPolicies::WRITE, 1); + + let allocation_handle = self.create_allocation(texture_creation_result.size, resource_uses, DeviceAccesses::GpuWrite); + + let allocation = &self.allocations[allocation_handle.0 as usize]; + + self.render_backend.bind_texture_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: 0, size: size }, &texture_creation_result); + + let texture_view = self.render_backend.create_texture_view(&texture_creation_result.resource, format, 1); + + let texture_handle = self.create_texture_internal(Texture { + frame_handle: Some(FrameHandle(0)), + next: None, + parent: None, + texture: texture_creation_result.resource, + texture_view: Some(texture_view), + allocation_handle, + extent, + role: String::from("GPU_WRITE"), + }); + + self.textures[proxy_texture_handle.0 as usize].parent = Some(texture_handle); + + texture_handle + } else if device_accesses == DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead { + let texture_creation_result = self.render_backend.create_texture(extent, format, resource_uses | render_backend::Uses::TransferSource, DeviceAccesses::CpuWrite, crate::render_backend::AccessPolicies::WRITE, 1); + + let allocation_handle = self.create_allocation(texture_creation_result.size, resource_uses, DeviceAccesses::CpuWrite); + + let allocation = &self.allocations[allocation_handle.0 as usize]; + + self.render_backend.bind_texture_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: 0, size: size }, &texture_creation_result); + + let texture_view = self.render_backend.create_texture_view(&texture_creation_result.resource, format, 1); + + let proxy_texture_handle = TextureHandle(self.textures.len() as u32); + + self.textures.push(Texture { + frame_handle: Some(FrameHandle(0)), + next: None, + parent: None, + texture: texture_creation_result.resource, + texture_view: Some(texture_view), + allocation_handle, + extent, + role: String::from("CPU_WRITE"), + }); + + let texture_creation_result = self.render_backend.create_texture(extent, format, resource_uses | render_backend::Uses::TransferDestination, DeviceAccesses::GpuRead, crate::render_backend::AccessPolicies::READ, 1); + + let allocation_handle = self.create_allocation(texture_creation_result.size, resource_uses, DeviceAccesses::GpuRead); + + let allocation = &self.allocations[allocation_handle.0 as usize]; + + self.render_backend.bind_texture_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: 0, size: size }, &texture_creation_result); + + let texture_view = self.render_backend.create_texture_view(&texture_creation_result.resource, format, 1); + + let texture_handle = self.create_texture_internal(Texture { + frame_handle: Some(FrameHandle(0)), + next: None, + parent: None, + texture: texture_creation_result.resource, + texture_view: Some(texture_view), + allocation_handle, + extent, + role: String::from("GPU_READ"), + }); + + self.textures[proxy_texture_handle.0 as usize].parent = Some(texture_handle); + + texture_handle + } else { + let texture_handle = TextureHandle(self.textures.len() as u32); + + let mut previous_texture_handle: Option = None; + + for i in 0..self.frames.len() { + let texture_creation_result = self.render_backend.create_texture(extent, format, render_backend::Uses::RenderTarget | render_backend::Uses::TransferSource, DeviceAccesses::GpuWrite, crate::render_backend::AccessPolicies::WRITE, 1); + + let allocation_handle = self.create_allocation(texture_creation_result.size, render_backend::Uses::RenderTarget, DeviceAccesses::GpuWrite); + + let allocation = &self.allocations[allocation_handle.0 as usize]; + + self.render_backend.bind_texture_memory(crate::render_backend::Memory{ allocation: &allocation.allocation, offset: 0, size: size }, &texture_creation_result); + + let texture_view = self.render_backend.create_texture_view(&texture_creation_result.resource, format, 1); + + let texture_handle = self.create_texture_internal(Texture { + frame_handle: Some(FrameHandle(i as u32)), + next: None, + parent: None, + texture: texture_creation_result.resource, + texture_view: Some(texture_view), + allocation_handle, + extent, + role: String::from(""), + }); + + if let Some(previous_texture_handle) = previous_texture_handle { + self.textures[previous_texture_handle.0 as usize].next = Some(texture_handle); + } + + previous_texture_handle = Some(texture_handle); + } + + texture_handle + } + } + + pub fn create_sampler(&mut self) -> SamplerHandle { + let sampler_handle = SamplerHandle(self.samplers.len() as u32); + + self.samplers.push(Sampler { + sampler: self.render_backend.create_sampler(), + }); + + sampler_handle + } + + fn create_texture_internal(&mut self, texture: Texture) -> TextureHandle { + let texture_handle = TextureHandle(self.textures.len() as u32); + self.textures.push(texture); + texture_handle + } + + pub fn bind_to_window(&mut self, window_os_handles: window_system::WindowOsHandles) -> SurfaceHandle { + let surface = self.render_backend.create_surface(window_os_handles); + + let properties = self.render_backend.get_surface_properties(&surface); + + let extent = properties.extent; + + let swapchain = self.render_backend.create_swapchain(&surface, extent, std::cmp::max(self.frames.len() as u32, 2)); + + let images = self.render_backend.get_swapchain_images(&swapchain); + + let mut textures = Vec::new(); + + let mut previous_texture_handle: Option = None; + + for (i, image) in images.iter().enumerate() { + let texture_view = self.render_backend.create_texture_view(&image, crate::render_backend::TextureFormats::BGRAu8, 1); + + let texture_handle = self.create_texture_internal(Texture { + frame_handle: Some(FrameHandle(i as u32)), + next: previous_texture_handle, + parent: None, + texture: *image, + texture_view: Some(texture_view), + allocation_handle: AllocationHandle(0xFFFFFFFFFFFFFFFF), + extent: extent, + role: String::from("SURFACE"), + }); + + if let Some(previous_texture_handle) = previous_texture_handle { + self.textures[previous_texture_handle.0 as usize].next = Some(texture_handle); + } + + textures.push(texture_handle); + + previous_texture_handle = Some(texture_handle); + } + + self.surface = Some( + Surface { + surface, + swapchain, + textures, + } + ); + + SurfaceHandle(0) + } + + pub fn get_texture_data(&self, texture_handle: TextureHandle) -> &[T] { + let texture = self.textures.iter().find(|texture| texture.parent.map_or(false, |x| texture_handle == x)).unwrap(); // Get the proxy texture + let allocation = &self.allocations[texture.allocation_handle.0 as usize]; + let slice = unsafe { std::slice::from_raw_parts::<'static, T>(self.render_backend.get_allocation_pointer(&allocation.allocation) as *mut T, (texture.extent.width*texture.extent.height*texture.extent.depth) as usize) }; + + slice + } + + /// Creates a synchronization primitive (implemented as a semaphore/fence/event).\ + /// Multiple underlying synchronization primitives are created, one for each frame + pub fn create_synchronizer(&mut self, signaled: bool) -> SynchronizerHandle { + let synchronizer_handle = SynchronizerHandle(self.synchronizers.len() as u32); + + let mut previous_synchronizer_handle: Option = None; + + for i in 0..self.frames.len() { + let synchronizer_handle = SynchronizerHandle(self.synchronizers.len() as u32); + + self.synchronizers.push(Synchronizer { + frame_handle: Some(FrameHandle(i as u32)), + next: None, + synchronizer: self.render_backend.create_synchronizer(signaled), + }); + + if let Some(previous_synchronizer_handle) = previous_synchronizer_handle { + self.synchronizers[previous_synchronizer_handle.0 as usize].next = Some(synchronizer_handle); + } + + previous_synchronizer_handle = Some(synchronizer_handle); + } + + synchronizer_handle + } + + /// Acquires an image from the swapchain as to have it ready for presentation. + /// + /// # Arguments + /// + /// * `frame_handle` - The frame to acquire the image for. If `None` is passed, the image will be acquired for the next frame. + /// * `synchronizer_handle` - The synchronizer to wait for before acquiring the image. If `None` is passed, the image will be acquired immediately. + /// + /// # Panics + /// + /// Panics if . + pub fn acquire_swapchain_image(&mut self, frame_handle: Option, synchronizer_handle: SynchronizerHandle) -> u32 { + let synchronizer = self.get_synchronizer(frame_handle, synchronizer_handle); + let (index, swapchain_state) = self.render_backend.acquire_swapchain_image(&self.surface.as_ref().unwrap().swapchain, &synchronizer.synchronizer); + + if swapchain_state == render_backend::SwapchainStates::Suboptimal || swapchain_state == render_backend::SwapchainStates::Invalid { + panic!("Swapchain out of date"); + } + + index + } + + pub fn get_swapchain_texture_handle(&self, frame_handle: Option) -> TextureHandle { + let surface = self.surface.as_ref().unwrap(); + surface.textures[frame_handle.unwrap().0 as usize] + } + + pub fn execute(&self, frame_handle: Option, command_buffer_recording: CommandBufferRecording, wait_for_synchronizer_handle: Option, signal_synchronizer_handle: SynchronizerHandle) { + let command_buffer = self.get_command_buffer(frame_handle, command_buffer_recording.command_buffer); + + let wait_for_synchronizer = if let Some(wait_for_synchronizer) = wait_for_synchronizer_handle { + Some(&self.get_synchronizer(frame_handle, wait_for_synchronizer).synchronizer) + } else { + None + }; + + let signal_synchronizer = self.get_synchronizer(frame_handle, signal_synchronizer_handle); + + self.render_backend.execute(&command_buffer.command_buffer, wait_for_synchronizer, &signal_synchronizer.synchronizer); + } + + pub fn present(&self, frame_handle: Option, image_index: u32, synchronizer_handle: SynchronizerHandle) { + let synchronizer = &self.get_synchronizer(frame_handle, synchronizer_handle); + self.render_backend.present(&self.surface.as_ref().unwrap().swapchain, &synchronizer.synchronizer, image_index); + } + + pub fn wait(&self, frame_handle: Option, synchronizer_handle: SynchronizerHandle) { + let synchronizer = &self.get_synchronizer(frame_handle, synchronizer_handle); + self.render_backend.wait(&synchronizer.synchronizer); + } + + pub fn start_frame_capture(&mut self) { + self.debugger.start_frame_capture(); + } + + pub fn end_frame_capture(&mut self) { + self.debugger.end_frame_capture(); + } + + fn get_command_buffer(&self, frame_handle: Option, resource_handle: CommandBufferHandle) -> &CommandBuffer { + let mut resource = &self.command_buffers[resource_handle.0 as usize]; + + loop { + if resource.frame_handle == frame_handle { break; } + + if let Some(next) = resource.next { + resource = &self.command_buffers[next.0 as usize]; + } else { + panic!("Resource not found"); + } + } + + resource + } + + fn get_command_buffer_handle(&self, frame_handle: Option, resource_handle: CommandBufferHandle) -> CommandBufferHandle { + let mut resource = &self.command_buffers[resource_handle.0 as usize]; + let mut command_buffer_handle = resource_handle; + + loop { + if resource.frame_handle == frame_handle { break; } + + if let Some(next) = resource.next { + resource = &self.command_buffers[next.0 as usize]; + command_buffer_handle = next; + } else { + panic!("Resource not found"); + } + } + + command_buffer_handle + } + + fn get_buffer_handle(&self, frame_handle: Option, resource_handle: BufferHandle) -> BufferHandle { + let mut resource = &self.buffers[resource_handle.0 as usize]; + let mut buffer_handle = resource_handle; + + loop { + if resource.frame_handle == frame_handle { break; } + + if let Some(next) = resource.next { + resource = &self.buffers[next.0 as usize]; + buffer_handle = next; + } else { + panic!("Resource not found"); + } + } + + buffer_handle + } + + fn get_texture(&self, frame_handle: Option, resource_handle: TextureHandle) -> &Texture { + let mut resource = &self.textures[resource_handle.0 as usize]; + + loop { + if resource.frame_handle == frame_handle { break; } + + if let Some(next) = resource.next { + resource = &self.textures[next.0 as usize]; + } else { + panic!("Resource not found"); + } + } + + resource + } + + fn get_synchronizer(&self, frame_handle: Option, resource_handle: SynchronizerHandle) -> &Synchronizer { + let mut resource = &self.synchronizers[resource_handle.0 as usize]; + + loop { + if resource.frame_handle == frame_handle { break; } + + if let Some(next) = resource.next { + resource = &self.synchronizers[next.0 as usize]; + } else { + panic!("Resource not found"); + } + } + + resource + } +} + +// TODO: handle resizing + +impl System for RenderSystem { + fn as_any(&self) -> &dyn std::any::Any { self } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct RGBAu8 { + r: u8, + g: u8, + b: u8, + a: u8, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn render_triangle() { + let mut renderer = RenderSystem::new(); + + let frame_handle = renderer.create_frame(); + + let signal = renderer.create_synchronizer(false); + + let floats: [f32;21] = [ + 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, + 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, + -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0 + ]; + + let mesh = unsafe { renderer.add_mesh_from_vertices_and_indices( + std::slice::from_raw_parts(floats.as_ptr() as *const u8, (3*4 + 4*4) * 3), + std::slice::from_raw_parts([0, 1, 2].as_ptr() as *const u8, 3 * 4), + &[ + crate::render_system::VertexElement{ name: "POSITION".to_string(), format: crate::render_system::DataTypes::Float3, shuffled: true }, + crate::render_system::VertexElement{ name: "COLOR".to_string(), format: crate::render_system::DataTypes::Float4, shuffled: true }, + ] + ) }; + + let vertex_shader_code = " + #version 450 + #pragma shader_stage(vertex) + + layout(location = 0) in vec3 in_position; + layout(location = 1) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + void main() { + out_color = in_color; + gl_Position = vec4(in_position, 1.0); + } + "; + + let fragment_shader_code = " + #version 450 + #pragma shader_stage(fragment) + + layout(location = 0) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + void main() { + out_color = in_color; + } + "; + + let vertex_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, vertex_shader_code.as_bytes()); + let fragment_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, fragment_shader_code.as_bytes()); + + let pipeline_layout = renderer.create_pipeline_layout(&[]); + let pipeline = renderer.create_pipeline(pipeline_layout, &[vertex_shader, fragment_shader]); + + // Use and odd width to make sure there is a middle/center pixel + let extent = crate::Extent { width: 1920, height: 1080, depth: 1 }; + + let texture = renderer.create_texture(extent, crate::render_backend::TextureFormats::RGBAu8, crate::render_backend::Uses::RenderTarget, crate::render_system::DeviceAccesses::CpuRead | crate::render_system::DeviceAccesses::GpuWrite); + + let command_buffer_handle = renderer.create_command_buffer(); + + renderer.start_frame_capture(); + + let mut command_buffer_recording = renderer.create_command_buffer_recording(Some(frame_handle), command_buffer_handle); + + let attachments = [ + crate::render_system::AttachmentInfo { + texture: texture, + format: crate::render_backend::TextureFormats::RGBAu8, + clear: Some(crate::RGBA { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }), + load: false, + store: true, + } + ]; + + command_buffer_recording.start_render_pass(extent, &attachments); + + command_buffer_recording.bind_pipeline(&pipeline); + + command_buffer_recording.draw_mesh(&mesh); + + command_buffer_recording.end_render_pass(); + + command_buffer_recording.synchronize_texture(texture); + + command_buffer_recording.end(); + + renderer.execute(Some(frame_handle), command_buffer_recording, None, signal); + + renderer.end_frame_capture(); + + renderer.wait(Some(frame_handle), signal); // Wait for the render to finish before accessing the texture data + + // assert colored triangle was drawn to texture + let pixels = renderer.get_texture_data::(texture); + + // let mut file = std::fs::File::create("test.png").unwrap(); + + // let mut encoder = png::Encoder::new(&mut file, extent.width, extent.height); + + // encoder.set_color(png::ColorType::Rgba); + // encoder.set_depth(png::BitDepth::Eight); + + // let mut writer = encoder.write_header().unwrap(); + // writer.write_image_data(unsafe { std::slice::from_raw_parts(pixels.as_ptr() as *const u8, pixels.len() * 4) }).unwrap(); + + assert_eq!(pixels.len(), (extent.width * extent.height) as usize); + + let pixel = pixels[0]; // top left + assert_eq!(pixel, RGBAu8 { r: 0, g: 0, b: 0, a: 255 }); + + if extent.width % 2 != 0 { + let pixel = pixels[(extent.width / 2) as usize]; // middle top center + assert_eq!(pixel, RGBAu8 { r: 255, g: 0, b: 0, a: 255 }); + } + + let pixel = pixels[(extent.width - 1) as usize]; // top right + assert_eq!(pixel, RGBAu8 { r: 0, g: 0, b: 0, a: 255 }); + + let pixel = pixels[(extent.width * (extent.height - 1)) as usize]; // bottom left + assert_eq!(pixel, RGBAu8 { r: 0, g: 0, b: 255, a: 255 }); + + let pixel = pixels[(extent.width * extent.height - (extent.width / 2)) as usize]; // middle bottom center + assert_eq!(pixel, RGBAu8 { r: 0, g: 127, b: 127, a: 255 }); + + let pixel = pixels[(extent.width * extent.height - 1) as usize]; // bottom right + assert_eq!(pixel, RGBAu8 { r: 0, g: 255, b: 0, a: 255 }); + + assert!(!renderer.has_errors()) + } + + #[test] + fn present() { + let mut renderer = RenderSystem::new(); + + let mut window_system = window_system::WindowSystem::new(); + + // Use and odd width to make sure there is a middle/center pixel + let extent = crate::Extent { width: 1920, height: 1080, depth: 1 }; + + let window_handle = window_system.create_window("Renderer Test", extent, "test"); + + renderer.bind_to_window(window_system.get_os_handles(window_handle)); + + let frame_handle = renderer.create_frame(); + + let floats: [f32;21] = [ + 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, + 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, + -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0 + ]; + + let mesh = unsafe { renderer.add_mesh_from_vertices_and_indices( + std::slice::from_raw_parts(floats.as_ptr() as *const u8, (3*4 + 4*4) * 3), + std::slice::from_raw_parts([0, 1, 2].as_ptr() as *const u8, 3 * 4), + &[ + crate::render_system::VertexElement{ name: "POSITION".to_string(), format: crate::render_system::DataTypes::Float3, shuffled: true }, + crate::render_system::VertexElement{ name: "COLOR".to_string(), format: crate::render_system::DataTypes::Float4, shuffled: true }, + ] + ) }; + + let vertex_shader_code = " + #version 450 + #pragma shader_stage(vertex) + + layout(location = 0) in vec3 in_position; + layout(location = 1) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + void main() { + out_color = in_color; + gl_Position = vec4(in_position, 1.0); + } + "; + + let fragment_shader_code = " + #version 450 + #pragma shader_stage(fragment) + + layout(location = 0) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + void main() { + out_color = in_color; + } + "; + + let vertex_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, vertex_shader_code.as_bytes()); + let fragment_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, fragment_shader_code.as_bytes()); + + let pipeline_layout = renderer.create_pipeline_layout(&[]); + let pipeline = renderer.create_pipeline(pipeline_layout, &[vertex_shader, fragment_shader]); + + let texture = renderer.create_texture(extent, crate::render_backend::TextureFormats::RGBAu8, crate::render_backend::Uses::RenderTarget, crate::render_system::DeviceAccesses::GpuWrite); + + let command_buffer_handle = renderer.create_command_buffer(); + + let render_finished_synchronizer = renderer.create_synchronizer(false); + let image_ready = renderer.create_synchronizer(false); + + let image_index = renderer.acquire_swapchain_image(Some(frame_handle), image_ready); + + renderer.start_frame_capture(); + + let mut command_buffer_recording = renderer.create_command_buffer_recording(Some(frame_handle), command_buffer_handle); + + let attachments = [ + crate::render_system::AttachmentInfo { + texture: texture, + format: crate::render_backend::TextureFormats::RGBAu8, + clear: Some(crate::RGBA { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }), + load: false, + store: true, + } + ]; + + command_buffer_recording.start_render_pass(extent, &attachments); + + command_buffer_recording.bind_pipeline(&pipeline); + + command_buffer_recording.draw_mesh(&mesh); + + command_buffer_recording.end_render_pass(); + + let swapchain_texture_handle = renderer.get_swapchain_texture_handle(Some(frame_handle)); + + command_buffer_recording.copy_textures(&[ + ( + texture, render_backend::Layouts::Transfer, render_backend::Stages::TRANSFER, render_backend::AccessPolicies::READ, + swapchain_texture_handle, render_backend::Layouts::Transfer, render_backend::Stages::TRANSFER, render_backend::AccessPolicies::WRITE + ) + ]); + + command_buffer_recording.end(); + + renderer.execute(Some(frame_handle), command_buffer_recording, Some(image_ready), render_finished_synchronizer); + + renderer.present(Some(frame_handle), image_index, render_finished_synchronizer); + + renderer.end_frame_capture(); + + renderer.wait(Some(frame_handle), render_finished_synchronizer); + + // TODO: assert rendering results + + assert!(!renderer.has_errors()) + } + + #[test] + fn multiframe_rendering() { + //! Tests that the render system can perform rendering with multiple frames in flight. + //! Having multiple frames in flight means allocating and managing multiple resources under a single handle, one for each frame. + + const FRAMES_IN_FLIGHT: usize = 2; + + let mut renderer = RenderSystem::new(); + + let mut window_system = window_system::WindowSystem::new(); + + // Use and odd width to make sure there is a middle/center pixel + let extent = crate::Extent { width: 1920, height: 1080, depth: 1 }; + + let window_handle = window_system.create_window("Renderer Test", extent, "test"); + + renderer.bind_to_window(window_system.get_os_handles(window_handle)); + + let frames = (0..FRAMES_IN_FLIGHT).map(|_| renderer.create_frame()).collect::>(); + + let floats: [f32;21] = [ + 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, + 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, + -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0 + ]; + + let mesh = unsafe { renderer.add_mesh_from_vertices_and_indices( + std::slice::from_raw_parts(floats.as_ptr() as *const u8, (3*4 + 4*4) * 3), + std::slice::from_raw_parts([0, 1, 2].as_ptr() as *const u8, 3 * 4), + &[ + crate::render_system::VertexElement{ name: "POSITION".to_string(), format: crate::render_system::DataTypes::Float3, shuffled: true }, + crate::render_system::VertexElement{ name: "COLOR".to_string(), format: crate::render_system::DataTypes::Float4, shuffled: true }, + ] + ) }; + + let vertex_shader_code = " + #version 450 + #pragma shader_stage(vertex) + + layout(location = 0) in vec3 in_position; + layout(location = 1) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + void main() { + out_color = in_color; + gl_Position = vec4(in_position, 1.0); + } + "; + + let fragment_shader_code = " + #version 450 + #pragma shader_stage(fragment) + + layout(location = 0) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + void main() { + out_color = in_color; + } + "; + + let vertex_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, vertex_shader_code.as_bytes()); + let fragment_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, fragment_shader_code.as_bytes()); + + let pipeline_layout = renderer.create_pipeline_layout(&[]); + let pipeline = renderer.create_pipeline(pipeline_layout, &[vertex_shader, fragment_shader]); + + // Use and odd width to make sure there is a middle/center pixel + let extent = crate::Extent { width: 1920, height: 1080, depth: 1 }; + + let texture = renderer.create_texture(extent, crate::render_backend::TextureFormats::RGBAu8, crate::render_backend::Uses::RenderTarget, crate::render_system::DeviceAccesses::GpuWrite); + + let command_buffer_handle = renderer.create_command_buffer(); + + let render_finished_synchronizer = renderer.create_synchronizer(true); + let image_ready = renderer.create_synchronizer(false); + + for i in 0..FRAMES_IN_FLIGHT*10 { + renderer.wait(Some(frames[i % FRAMES_IN_FLIGHT]), render_finished_synchronizer); + + let image_index = renderer.acquire_swapchain_image(Some(frames[i % FRAMES_IN_FLIGHT]), image_ready); + + renderer.start_frame_capture(); + + let mut command_buffer_recording = renderer.create_command_buffer_recording(Some(frames[i % FRAMES_IN_FLIGHT]), command_buffer_handle); + + let attachments = [ + crate::render_system::AttachmentInfo { + texture: texture, + format: crate::render_backend::TextureFormats::RGBAu8, + clear: Some(crate::RGBA { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }), + load: false, + store: true, + } + ]; + + command_buffer_recording.start_render_pass(extent, &attachments); + + command_buffer_recording.bind_pipeline(&pipeline); + + command_buffer_recording.draw_mesh(&mesh); + + command_buffer_recording.end_render_pass(); + + let swapchain_texture_handle = renderer.get_swapchain_texture_handle(Some(frames[i % FRAMES_IN_FLIGHT])); + + command_buffer_recording.copy_textures(&[ + ( + texture, render_backend::Layouts::Transfer, render_backend::Stages::TRANSFER, render_backend::AccessPolicies::READ, + swapchain_texture_handle, render_backend::Layouts::Transfer, render_backend::Stages::TRANSFER, render_backend::AccessPolicies::WRITE + ) + ]); + + command_buffer_recording.end(); + + renderer.execute(Some(frames[i % FRAMES_IN_FLIGHT]), command_buffer_recording, Some(image_ready), render_finished_synchronizer); + + renderer.present(Some(frames[i % FRAMES_IN_FLIGHT]), image_index, render_finished_synchronizer); + + renderer.end_frame_capture(); + } + + assert!(!renderer.has_errors()) + } + + // TODO: Test changing frames in flight count during rendering + + #[test] + fn dynamic_data() { + //! Tests that the render system can perform rendering with multiple frames in flight. + //! Having multiple frames in flight means allocating and managing multiple resources under a single handle, one for each frame. + + const FRAMES_IN_FLIGHT: usize = 2; + + let mut renderer = RenderSystem::new(); + + let mut window_system = window_system::WindowSystem::new(); + + // Use and odd width to make sure there is a middle/center pixel + let extent = crate::Extent { width: 1920, height: 1080, depth: 1 }; + + let window_handle = window_system.create_window("Renderer Test", extent, "test"); + + renderer.bind_to_window(window_system.get_os_handles(window_handle)); + + let frames = (0..FRAMES_IN_FLIGHT).map(|_| renderer.create_frame()).collect::>(); + + let floats: [f32;21] = [ + 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, + 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, + -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0 + ]; + + let mesh = unsafe { renderer.add_mesh_from_vertices_and_indices( + std::slice::from_raw_parts(floats.as_ptr() as *const u8, (3*4 + 4*4) * 3), + std::slice::from_raw_parts([0, 1, 2].as_ptr() as *const u8, 3 * 4), + &[ + crate::render_system::VertexElement{ name: "POSITION".to_string(), format: crate::render_system::DataTypes::Float3, shuffled: true }, + crate::render_system::VertexElement{ name: "COLOR".to_string(), format: crate::render_system::DataTypes::Float4, shuffled: true }, + ] + ) }; + + let vertex_shader_code = " + #version 450 + #pragma shader_stage(vertex) + + layout(location = 0) in vec3 in_position; + layout(location = 1) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + layout(row_major) uniform; + + layout(push_constant) uniform PushConstants { + mat4 matrix; + } push_constants; + + void main() { + out_color = in_color; + gl_Position = push_constants.matrix * vec4(in_position, 1.0); + } + "; + + let fragment_shader_code = " + #version 450 + #pragma shader_stage(fragment) + + layout(location = 0) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + void main() { + out_color = in_color; + } + "; + + let vertex_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, vertex_shader_code.as_bytes()); + let fragment_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, fragment_shader_code.as_bytes()); + + let pipeline_layout = renderer.create_pipeline_layout(&[]); + let pipeline = renderer.create_pipeline(pipeline_layout, &[vertex_shader, fragment_shader]); + + // Use and odd width to make sure there is a middle/center pixel + let extent = crate::Extent { width: 1920, height: 1080, depth: 1 }; + + let texture = renderer.create_texture(extent, crate::render_backend::TextureFormats::RGBAu8, crate::render_backend::Uses::RenderTarget, crate::render_system::DeviceAccesses::GpuWrite); + + let buffer = renderer.create_buffer(64, crate::render_backend::Uses::Storage, DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead); + + let command_buffer_handle = renderer.create_command_buffer(); + + let render_finished_synchronizer = renderer.create_synchronizer(true); + let image_ready = renderer.create_synchronizer(false); + + for i in 0..FRAMES_IN_FLIGHT*10 { + renderer.wait(Some(frames[i % FRAMES_IN_FLIGHT]), render_finished_synchronizer); + + //let pointer = renderer.get_buffer_pointer(Some(frames[i % FRAMES_IN_FLIGHT]), buffer); + + //unsafe { std::ptr::copy_nonoverlapping(matrix.as_ptr(), pointer as *mut f32, 16); } + + let image_index = renderer.acquire_swapchain_image(Some(frames[i % FRAMES_IN_FLIGHT]), image_ready); + + renderer.start_frame_capture(); + + let mut command_buffer_recording = renderer.create_command_buffer_recording(Some(frames[i % FRAMES_IN_FLIGHT]), command_buffer_handle); + + let attachments = [ + crate::render_system::AttachmentInfo { + texture: texture, + format: crate::render_backend::TextureFormats::RGBAu8, + clear: Some(crate::RGBA { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }), + load: false, + store: true, + } + ]; + + command_buffer_recording.start_render_pass(extent, &attachments); + + command_buffer_recording.bind_pipeline(&pipeline); + + let angle = (i as f32) / 10.0; + + let matrix: [f32; 16] = + [ + angle.cos(), -angle.sin(), 0f32, 0f32, + angle.sin(), angle.cos(), 0f32, 0f32, + 0f32, 0f32, 1f32, 0f32, + 0f32, 0f32, 0f32, 1f32, + ]; + + command_buffer_recording.write_to_push_constant(&pipeline_layout, 0, unsafe { std::slice::from_raw_parts(matrix.as_ptr() as *const u8, 16 * 4) }); + + command_buffer_recording.draw_mesh(&mesh); + + command_buffer_recording.end_render_pass(); + + let swapchain_texture_handle = renderer.get_swapchain_texture_handle(Some(frames[i % FRAMES_IN_FLIGHT])); + + command_buffer_recording.copy_textures(&[ + ( + texture, render_backend::Layouts::Transfer, render_backend::Stages::TRANSFER, render_backend::AccessPolicies::READ, + swapchain_texture_handle, render_backend::Layouts::Transfer, render_backend::Stages::TRANSFER, render_backend::AccessPolicies::WRITE + ) + ]); + + command_buffer_recording.end(); + + renderer.execute(Some(frames[i % FRAMES_IN_FLIGHT]), command_buffer_recording, Some(image_ready), render_finished_synchronizer); + + renderer.present(Some(frames[i % FRAMES_IN_FLIGHT]), image_index, render_finished_synchronizer); + + renderer.end_frame_capture(); + } + + assert!(!renderer.has_errors()) + } + + #[test] + fn descriptor_sets() { + let mut renderer = RenderSystem::new(); + + let frame_handle = renderer.create_frame(); + + let signal = renderer.create_synchronizer(false); + + let floats: [f32;21] = [ + 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, + 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, + -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0 + ]; + + let mesh = unsafe { renderer.add_mesh_from_vertices_and_indices( + std::slice::from_raw_parts(floats.as_ptr() as *const u8, (3*4 + 4*4) * 3), + std::slice::from_raw_parts([0, 1, 2].as_ptr() as *const u8, 3 * 4), + &[ + crate::render_system::VertexElement{ name: "POSITION".to_string(), format: crate::render_system::DataTypes::Float3, shuffled: true }, + crate::render_system::VertexElement{ name: "COLOR".to_string(), format: crate::render_system::DataTypes::Float4, shuffled: true }, + ] + ) }; + + let vertex_shader_code = " + #version 450 core + #pragma shader_stage(vertex) + + layout(location = 0) in vec3 in_position; + layout(location = 1) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + layout(set=0, binding=1) uniform UniformBufferObject { + mat4 matrix; + } ubo; + + void main() { + out_color = in_color; + gl_Position = vec4(in_position, 1.0); + } + "; + + let fragment_shader_code = " + #version 450 core + #pragma shader_stage(fragment) + + layout(location = 0) in vec4 in_color; + + layout(location = 0) out vec4 out_color; + + layout(set=0,binding=0) uniform sampler smpl; + layout(set=0,binding=2) uniform texture2D tex; + + void main() { + out_color = texture(sampler2D(tex, smpl), vec2(0, 0)); + } + "; + + let vertex_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, vertex_shader_code.as_bytes()); + let fragment_shader = renderer.add_shader(crate::render_system::ShaderSourceType::GLSL, fragment_shader_code.as_bytes()); + + let buffer = renderer.create_buffer(64, render_backend::Uses::Uniform, DeviceAccesses::CpuWrite | DeviceAccesses::GpuRead); + + let sampled_texture = renderer.create_texture(crate::Extent { width: 2, height: 2, depth: 1 }, crate::render_backend::TextureFormats::RGBAu8, crate::render_backend::Uses::Texture, crate::render_system::DeviceAccesses::CpuWrite | crate::render_system::DeviceAccesses::GpuRead); + + let pixels = vec![ + RGBAu8 { r: 255, g: 0, b: 0, a: 255 }, + RGBAu8 { r: 0, g: 255, b: 0, a: 255 }, + RGBAu8 { r: 0, g: 0, b: 255, a: 255 }, + RGBAu8 { r: 255, g: 255, b: 0, a: 255 }, + ]; + + let sampler = renderer.create_sampler(); + + let bindings = [ + DescriptorSetLayoutBinding { + descriptor_count: 1, + descriptor_type: render_backend::DescriptorType::Sampler, + binding: 0, + stage_flags: render_backend::Stages::FRAGMENT, + immutable_samplers: Some(vec![sampler]), + }, + DescriptorSetLayoutBinding { + descriptor_count: 1, + descriptor_type: render_backend::DescriptorType::UniformBuffer, + binding: 1, + stage_flags: render_backend::Stages::VERTEX, + immutable_samplers: None, + }, + DescriptorSetLayoutBinding { + descriptor_count: 1, + descriptor_type: render_backend::DescriptorType::SampledImage, + binding: 2, + stage_flags: render_backend::Stages::FRAGMENT, + immutable_samplers: None, + }, + ]; + + let descriptor_set_layout_handle = renderer.create_descriptor_set_layout(&bindings); + + let descriptor_set = renderer.create_descriptor_set(&descriptor_set_layout_handle, &bindings); + + renderer.write(&[ + DescriptorWrite { descriptor_set: descriptor_set, binding: 1, array_element: 0, descriptor: Descriptor::Buffer(buffer) }, + DescriptorWrite { descriptor_set: descriptor_set, binding: 2, array_element: 0, descriptor: Descriptor::Texture(sampled_texture) }, + ]); + + let pipeline_layout = renderer.create_pipeline_layout(&[descriptor_set_layout_handle]); + let pipeline = renderer.create_pipeline(pipeline_layout, &[vertex_shader, fragment_shader]); + + // Use and odd width to make sure there is a middle/center pixel + let extent = crate::Extent { width: 1920, height: 1080, depth: 1 }; + + let render_target = renderer.create_texture(extent, crate::render_backend::TextureFormats::RGBAu8, crate::render_backend::Uses::RenderTarget, crate::render_system::DeviceAccesses::CpuRead | crate::render_system::DeviceAccesses::GpuWrite); + + let command_buffer_handle = renderer.create_command_buffer(); + + renderer.start_frame_capture(); + + let mut command_buffer_recording = renderer.create_command_buffer_recording(Some(frame_handle), command_buffer_handle); + + command_buffer_recording.write_texture_data(sampled_texture, &pixels); + + let attachments = [ + crate::render_system::AttachmentInfo { + texture: render_target, + format: crate::render_backend::TextureFormats::RGBAu8, + clear: Some(crate::RGBA { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }), + load: false, + store: true, + } + ]; + + command_buffer_recording.start_render_pass(extent, &attachments); + + command_buffer_recording.bind_pipeline(&pipeline); + + command_buffer_recording.bind_descriptor_set(pipeline_layout, 0, &descriptor_set); + + command_buffer_recording.draw_mesh(&mesh); + + command_buffer_recording.end_render_pass(); + + command_buffer_recording.synchronize_texture(render_target); + + command_buffer_recording.end(); + + renderer.execute(Some(frame_handle), command_buffer_recording, None, signal); + + renderer.end_frame_capture(); + + renderer.wait(Some(frame_handle), signal); // Wait for the render to finish before accessing the texture data + + // assert colored triangle was drawn to texture + let pixels = renderer.get_texture_data::(render_target); + + // TODO: assert rendering results + + assert!(!renderer.has_errors()) + } +} \ No newline at end of file diff --git a/src/resource_manager.rs b/src/resource_manager.rs new file mode 100644 index 00000000..f6c444a3 --- /dev/null +++ b/src/resource_manager.rs @@ -0,0 +1,751 @@ +//! Resource manager module. +//! Handles loading assets or resources from different origins (network, local, etc.). +//! It also handles caching of resources. + +use std::{io::prelude::*, f32::consts::E}; + +use polodb_core::bson::{Document, bson, doc}; + +#[derive(Debug)] +struct Texture { + pub extent: crate::Extent, +} + +#[derive(Debug, PartialEq)] +enum VertexSemantics { + Position, + Normal, + Tangent, + BiTangent, + Uv, + Color, +} + +#[derive(Debug, PartialEq)] +enum IntegralTypes { + U8, + I8, + U16, + I16, + U32, + I32, + F16, + F32, + F64, +} + +// https://www.yosoygames.com.ar/wp/2018/03/vertex-formats-part-1-compression/ + +#[derive(Debug)] +struct VertexComponent { + pub semantic: VertexSemantics, + pub format: String, + pub channel: u32, +} + +#[derive(Debug)] +struct Mesh { + pub bounding_box: [[f32; 3]; 2], + pub vertex_components: Vec, + pub index_type: IntegralTypes, + pub vertex_count: u32, + pub index_count: u32, +} + +#[derive(Debug)] +enum Resource { + Texture(Texture), + Mesh(Mesh), +} + +use cgmath::{Vector3, Matrix3, Quaternion}; + +fn qtangent(normal: Vector3, tangent: Vector3, bi_tangent: Vector3) -> Quaternion { + let tbn: Matrix3 = Matrix3::from_cols(normal, tangent, bi_tangent); + + let mut qTangent = Quaternion::from(tbn); + //qTangent.normalise(); + + //Make sure QTangent is always positive + if qTangent.s < 0f32 { + qTangent = qTangent.conjugate(); + } + + //Bias = 1 / [2^(bits-1) - 1] + const bias: f32 = 1.0f32 / 32767.0f32; + + //Because '-0' sign information is lost when using integers, + //we need to apply a "bias"; while making sure the Quatenion + //stays normalized. + // ** Also our shaders assume qTangent.w is never 0. ** + if qTangent.s < bias { + let normFactor = f32::sqrt(1f32 - bias * bias); + qTangent.s = bias; + qTangent.v.x *= normFactor; + qTangent.v.y *= normFactor; + qTangent.v.z *= normFactor; + } + + //If it's reflected, then make sure .w is negative. + let naturalBinormal = tangent.cross(normal); + + if cgmath::dot(naturalBinormal, bi_tangent/* check if should be binormal */) <= 0f32 { + qTangent = -qTangent; + } + + qTangent +} + +/// Resource manager. +/// Handles loading assets or resources from different origins (network, local, etc.). +/// It also handles caching of resources. +/// +/// When in a debug build it will lazily load resources from source and cache them. +struct ResourceManager { + db: polodb_core::Database, + collection: polodb_core::Collection, +} + +fn extension_to_file_type(extension: &str) -> &str { + match extension { + "png" => "texture", + "gltf" => "mesh", + _ => "" + } +} + +impl From for LoadResults { + fn from(error: polodb_core::Error) -> Self { + match error { + _ => LoadResults::LoadFailed + } + } +} + +enum LoadResults { + ResourceNotFound, + LoadFailed, + CacheFileNotFound { + document: polodb_core::bson::Document, + }, + UnsuportedResourceType, +} + +fn extent_from_json(field: &polodb_core::bson::Bson) -> Option { + match field { + polodb_core::bson::Bson::Array(array) => { + let mut extent = crate::Extent { + width: 1, + height: 1, + depth: 1, + }; + + for (index, field) in array.iter().enumerate() { + match index { + 0 => extent.width = field.as_i32().unwrap() as u32, + 1 => extent.height = field.as_i32().unwrap() as u32, + 2 => extent.depth = field.as_i32().unwrap() as u32, + _ => panic!("Invalid extent field"), + } + } + + return Some(extent); + }, + _ => return None, + } +} + +fn vec3f_from_json(field: &polodb_core::bson::Bson) -> Option<[f32; 3]> { + match field { + polodb_core::bson::Bson::Array(array) => { + if let Some(polodb_core::bson::Bson::Double(x)) = array.get(0) { + if let Some(polodb_core::bson::Bson::Double(y)) = array.get(1) { + if let Some(polodb_core::bson::Bson::Double(z)) = array.get(2) { + return Some([*x as f32, *y as f32, *z as f32]); + } else { + return None; + } + } else { + return None; + } + } else { + return None; + } + }, + _ => return None, + } +} + +impl ResourceManager { + /// Creates a new resource manager. + pub fn new() -> Self { + let db_res = polodb_core::Database::open_file("assets/resources.db"); + + let db = match db_res { + Ok(db) => db, + Err(_) => { + // Delete file and try again + std::fs::remove_file("assets/resources.db").unwrap(); + + println!("\x1B[WARNING]Database file was corrupted, deleting and trying again."); + + let db_res = polodb_core::Database::open_file("assets/resources.db"); + + match db_res { + Ok(db) => db, + Err(_) => match polodb_core::Database::open_memory() { // If we can't create a file database, create a memory database. This way we can still run the application. + Ok(db) => { + println!("\x1B[WARNING]Could not create database file, using memory database instead."); + db + }, + Err(_) => panic!("Could not create database"), + } + } + } + }; + + let collection = db.collection::("resources"); + + ResourceManager { + db, + collection, + } + } + + /// Tries to read a resource from the cache.\ + /// If the resource is not in the cache, it will return an error. + /// If the resource is in the cache, it will return the resource and the bytes associated to it.\ + /// If the resource is in cache but it's data cannot be parsed, it will return an error. (This is useful if the data layout changed and you want to trigger a reload from source). + fn load_from_cache(&mut self, path: &str) -> Result<(Resource, Vec), LoadResults> { + let result = self.collection.find_one(doc!{ "id": path })?; + + if let Some(resource) = result { + let native_db_resource_id = if let Some(polodb_core::bson::Bson::ObjectId(id)) = resource.get("_id") { + id + } else { + return Err(LoadResults::LoadFailed); + }; + + let native_db_resource_id = native_db_resource_id.to_string(); + + let mut file = match std::fs::File::open("assets/".to_string() + native_db_resource_id.as_str()) { + Ok(it) => it, + Err(reason) => { + match reason { // TODO: handle specific errors + _ => return Err(LoadResults::CacheFileNotFound { document: resource }), + } + } + }; + + let mut bytes = Vec::new(); + + let res = file.read_to_end(&mut bytes); + + if res.is_err() { return Err(LoadResults::LoadFailed); } + + match resource.get("type").unwrap().as_str().unwrap() { + "texture" => { + let texture_object = if let Some(polodb_core::bson::Bson::Document(texture_object)) = resource.get("texture") { + texture_object + } else { + return Err(LoadResults::LoadFailed); + }; + + let _ = texture_object.get("compression").unwrap().as_str().unwrap(); + + if let Some(extent) = extent_from_json(&texture_object.get("extent").unwrap()) { + return Ok((Resource::Texture(Texture { extent }), bytes)) + } else { + return Err(LoadResults::LoadFailed); + } + }, + "mesh" => { + let bounding_box = if let Some(polodb_core::bson::Bson::Document(bbox)) = resource.get("bounding_box"){ + let min = if let Some(v) = bbox.get("min") { + vec3f_from_json(v) + } else { + return Err(LoadResults::LoadFailed); + }; + + let max = if let Some(v) = bbox.get("max") { + vec3f_from_json(v) + } else { + return Err(LoadResults::LoadFailed); + }; + + [min.unwrap(), max.unwrap()] + } else { + return Err(LoadResults::LoadFailed); + }; + + let vertex_components = if let Some(vertex_components_document) = resource.get("vertex_components") { + let mut vertex_components = Vec::new(); + for vertex_component in vertex_components_document.as_array().unwrap() { + let vertex_component = vertex_component.as_document().unwrap(); + vertex_components.push(VertexComponent { + semantic: match vertex_component.get("semantic").unwrap().as_str().unwrap() { + "Position" => VertexSemantics::Position, + "Normal" => VertexSemantics::Normal, + "Tangent" => VertexSemantics::Tangent, + "BiTangent" => VertexSemantics::BiTangent, + "UV" => VertexSemantics::Uv, + "Color" => VertexSemantics::Color, + _ => return Err(LoadResults::LoadFailed), + }, + format: vertex_component.get("format").unwrap().as_str().unwrap().to_string(), + channel: vertex_component.get("channel").unwrap().as_i32().unwrap() as u32, + }); + } + vertex_components + } else { + return Err(LoadResults::LoadFailed); + }; + + let vertex_count = if let Some(polodb_core::bson::Bson::Int32(vertex_count)) = resource.get("vertex_count") { + *vertex_count as u32 + } else { + return Err(LoadResults::LoadFailed); + }; + + let index_count = if let Some(polodb_core::bson::Bson::Int32(index_count)) = resource.get("index_count") { + *index_count as u32 + } else { + return Err(LoadResults::LoadFailed); + }; + + let index_type = if let Some(polodb_core::bson::Bson::String(index_type)) = resource.get("index_type") { + match index_type.as_str() { + "U8" => IntegralTypes::U8, + "U16" => IntegralTypes::U16, + "U32" => IntegralTypes::U32, + _ => return Err(LoadResults::LoadFailed), + } + } else { + return Err(LoadResults::LoadFailed); + }; + + return Ok((Resource::Mesh(Mesh { bounding_box, vertex_components, vertex_count, index_count, index_type }), bytes)) + }, + _ => { + return Err(LoadResults::UnsuportedResourceType); + } + } + } + + return Err(LoadResults::ResourceNotFound); + } + + /// Tries to load a resource from source.\ + /// If the resource cannot be found (non existent file, unreacheble network address, fails to parse, etc.) it will return None.\ + fn load_from_source(&mut self, path: &str) -> Option<(Resource, Vec)> { + let resource_origin = if path.starts_with("http://") || path.starts_with("https://") { + "network" + } else { + "local" + }; + + // Bytes to be stored associated to resource + let mut bytes; + let resource_type; + let format; + + match resource_origin { + "network" => { + let request = ureq::get(path).call(); + + if let Err(_) = request { return None; } + + let request = request.unwrap(); + + let content_type = request.header("content-type").unwrap(); + + match content_type { + "image/png" => { + let mut data = request.into_reader(); + bytes = Vec::with_capacity(4096 * 1024 * 4); + let res = data.read_to_end(&mut bytes); + + if let Err(_) = res { return None; } + + resource_type = "texture"; + format = "png"; + }, + _ => { + // Could not resolve how to get raw resource, return empty bytes + return None; + } + } + + }, + "local" => { + let mut file = std::fs::File::open(path).unwrap(); + let extension = &path[(path.rfind(".").unwrap() + 1)..]; + resource_type = extension_to_file_type(extension); + format = extension; + bytes = Vec::with_capacity(file.metadata().unwrap().len() as usize); + let res = file.read_to_end(&mut bytes); + + if let Err(_) = res { + return None; + } + }, + _ => { + // Could not resolve how to get raw resource, return empty bytes + return None; + } + } + + let resource: Resource; + + match format { + "png" => { + let mut decoder = png::Decoder::new(bytes.as_slice()); + decoder.set_transformations(png::Transformations::EXPAND); + let mut reader = decoder.read_info().unwrap(); + let mut buffer = vec![0; reader.output_buffer_size()]; + let info = reader.next_frame(&mut buffer).unwrap(); + + let extent = crate::Extent { width: info.width, height: info.height, depth: 1, }; + + resource = Resource::Texture(Texture { extent }); + + let mut buf: Vec = Vec::with_capacity(extent.width as usize * extent.height as usize * 4); + + // convert rgb to rgba + for x in 0..extent.width { + for y in 0..extent.height { + let index = ((x + y * extent.width) * 3) as usize; + buf.push(buffer[index]); + buf.push(buffer[index + 1]); + buf.push(buffer[index + 2]); + buf.push(255); + } + } + + bytes = buf; + }, + "gltf" => { + let (gltf, buffers, _) = gltf::import_slice(bytes.as_slice()).unwrap(); + + let mut buf: Vec = Vec::with_capacity(4096 * 1024 * 3); + + // 'mesh_loop: for mesh in gltf.meshes() { + // for primitive in mesh.primitives() { + + let primitive = gltf.meshes().next().unwrap().primitives().next().unwrap(); + + resource = { + let mut vertex_components = Vec::new(); + let index_type; + let bounding_box: [[f32; 3]; 2]; + let vertex_count = primitive.attributes().next().unwrap().1.count() as u32; + let index_count = primitive.indices().unwrap().count() as u32; + + let bounds = primitive.bounding_box(); + + bounding_box = [ + [bounds.min[0], bounds.min[1], bounds.min[2],], + [bounds.max[0], bounds.max[1], bounds.max[2],], + ]; + + let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()])); + + if let Some(positions) = reader.read_positions() { + positions.for_each(|position| position.iter().for_each(|m| m.to_le_bytes().iter().for_each(|byte| buf.push(*byte)))); + vertex_components.push(VertexComponent { semantic: VertexSemantics::Position, format: "vec3f".to_string(), channel: 0 }); + } else { + return None; + } + + if let Some(normals) = reader.read_normals() { + normals.for_each(|normal| normal.iter().for_each(|m| m.to_le_bytes().iter().for_each(|byte| buf.push(*byte)))); + vertex_components.push(VertexComponent { semantic: VertexSemantics::Normal, format: "vec3f".to_string(), channel: 1 }); + } + + if let Some(tangents) = reader.read_tangents() { + tangents.for_each(|tangent| tangent.iter().for_each(|m| m.to_le_bytes().iter().for_each(|byte| buf.push(*byte)))); + vertex_components.push(VertexComponent { semantic: VertexSemantics::Tangent, format: "vec3f".to_string(), channel: 2 }); + } + + if let Some(uv) = reader.read_tex_coords(0) { + uv.into_f32().for_each(|uv| uv.iter().for_each(|m| m.to_le_bytes().iter().for_each(|byte| buf.push(*byte)))); + vertex_components.push(VertexComponent { semantic: VertexSemantics::Uv, format: "vec3f".to_string(), channel: 3 }); + } + + // align buffer to 16 bytes for indices + while buf.len() % 16 != 0 { buf.push(0); } + + if let Some(indices) = reader.read_indices() { + match indices { + gltf::mesh::util::ReadIndices::U8(indices) => { + indices.for_each(|index| index.to_le_bytes().iter().for_each(|byte| buf.push(*byte))); + index_type = IntegralTypes::U8; + }, + gltf::mesh::util::ReadIndices::U16(indices) => { + indices.for_each(|index| index.to_le_bytes().iter().for_each(|byte| buf.push(*byte))); + index_type = IntegralTypes::U16; + }, + gltf::mesh::util::ReadIndices::U32(indices) => { + indices.for_each(|index| index.to_le_bytes().iter().for_each(|byte| buf.push(*byte))); + index_type = IntegralTypes::U32; + }, + } + } else { + return None; + } + + bytes = buf; + + Resource::Mesh(Mesh { bounding_box, vertex_components, index_type, vertex_count, index_count }) + }; + } + _ => { return None; } + } + + let mut document = polodb_core::bson::doc! { + "id": path, + "type": resource_type, + }; + + match resource_type { + "texture" => { + let extent = if let Resource::Texture(texture) = &resource { texture.extent } else { return None; }; + + document.insert("texture", bson!({ "compression": "BC7", "extent": [extent.width, extent.height, extent.depth] })); + + assert_eq!(extent.depth, 1); // TODO: support 3D textures + + let rgba_surface = intel_tex_2::RgbaSurface { + data: bytes.as_slice(), + width: extent.width, + height: extent.height, + stride: extent.width * 4, + }; + + let settings = intel_tex_2::bc7::opaque_ultra_fast_settings(); + + bytes = intel_tex_2::bc7::compress_blocks(&settings, &rgba_surface); + }, + "mesh" => { + let mesh = if let Resource::Mesh(mesh) = &resource { mesh } else { return None; }; + + let bounding_box = bson!({ + "min": [mesh.bounding_box[0][0], mesh.bounding_box[0][1], mesh.bounding_box[0][2]], + "max": [mesh.bounding_box[1][0], mesh.bounding_box[1][1], mesh.bounding_box[1][2]], + }); + + document.insert("bounding_box", bounding_box); + document.insert("vertex_count", mesh.vertex_count); + document.insert("index_count", mesh.index_count); + + let comps = mesh.vertex_components.iter().map( + |vertex_component| { + bson!({ + "semantic": match vertex_component.semantic { + VertexSemantics::Position => "Position", + VertexSemantics::Normal => "Normal", + VertexSemantics::Tangent => "Tangent", + VertexSemantics::BiTangent => "BiTangent", + VertexSemantics::Uv => "UV", + VertexSemantics::Color => "Color", + }, + "format": vertex_component.format.as_str(), + "channel": vertex_component.channel, + }) + } + ).collect::>(); + + document.insert("vertex_components", comps); + + document.insert("index_type", match mesh.index_type { + IntegralTypes::U8 => "U8", + IntegralTypes::U16 => "U16", + IntegralTypes::U32 => "U32", + _ => return None, + }); + } + _ => { return None; } + } + + let insert_result = self.collection.insert_one(document); + + let insert_result = insert_result.unwrap(); + + let resource_id = insert_result.inserted_id.as_object_id().unwrap(); + + let path = "assets/".to_string() + resource_id.to_string().as_str(); + + // Write file with resource contents + let mut file = std::fs::File::create(path).unwrap(); + + file.write_all(bytes.as_slice()).unwrap(); + + return Some((resource, bytes)); + } + + /// Tries to load a resource from cache or source.\ + /// If the resource cannot be found (non existent file, unreacheble network address, fails to parse, etc.) it will return None.\ + /// If the resource is in cache but it's data cannot be parsed, it will return None. + pub fn get(&mut self, path: &str) -> Option<(Resource, Vec)> { + let load_result = self.load_from_cache(path); + + match load_result { + Ok(load_result) => return Some(load_result), + Err(LoadResults::ResourceNotFound) => return self.load_from_source(path), + Err(LoadResults::CacheFileNotFound { document }) => { + println!("\x1B[WARNING]Resource load failed, cache file not found. Could have been deleted, renamed, or moved. Loading from source."); + + let _result = self.collection.delete_many(doc!{ "id": path }); // Delete all documents that point to non existent file + + return self.load_from_source(path) // If load from cache fails, try loading from source. Can happen mostly if resource fields/layout changed or if data was corrupted during debugging. + } + Err(LoadResults::LoadFailed) => { + println!("\x1B[WARNING]Resource load failed, trying to load from source."); + let result = self.collection.find_one(doc!{ "id": path }).unwrap().unwrap(); + let file_deletion_result = std::fs::remove_file(result.get("_id").unwrap().as_object_id().unwrap().to_string()); + + if let Err(_) = file_deletion_result { + println!("\x1B[WARNING]Could not delete resource file! This may leave a dangling file in the resources folder."); + } + + let result = self.collection.delete_many(doc!{ "id": path }); + + if let Ok(a) = result { + if a.deleted_count != 1 { + println!("\x1B[WARNING]Could not delete resource from database! This may leave a dangling file in the resources folder."); + } + } + + return self.load_from_source(path) // If load from cache fails, try loading from source. Can happen mostly if resource fields/layout changed or if data was corrupted during debugging. + } + Err(LoadResults::UnsuportedResourceType) => return None, + } + } +} + + +// TODO: test resource caching + +#[cfg(test)] +mod tests { + /// Tests for the resource manager. + /// It is important to test the load twice as the first time it will be loaded from source and the second time it will be loaded from cache. + + use super::*; + + #[test] + fn load_net_image() { + let mut resource_manager = ResourceManager::new(); + + let resource_result = resource_manager.get("https://camo.githubusercontent.com/dca6cdb597abc9c7ff4a0e066e6c35eb70b187683fbff2208d0440b4ef6c5a30/68747470733a2f2f692e696d6775722e636f6d2f56525261434f702e706e67"); + + assert!(resource_result.is_some()); + + let resource = resource_result.unwrap(); + + assert!(matches!(resource.0, Resource::Texture(_))); + + let texture_info = match &resource.0 { + Resource::Texture(texture) => texture, + _ => panic!("") + }; + + assert_eq!(texture_info.extent, crate::Extent{ width: 4096, height: 1024, depth: 1 }); + + //let bytes = resource_manager.get("https://upload.wikimedia.org/wikipedia/commons/6/6a/PNG_Test.png"); + let resource_result = resource_manager.get("https://camo.githubusercontent.com/dca6cdb597abc9c7ff4a0e066e6c35eb70b187683fbff2208d0440b4ef6c5a30/68747470733a2f2f692e696d6775722e636f6d2f56525261434f702e706e67"); + + assert!(resource_result.is_some()); + + let resource = resource_result.unwrap(); + + assert!(matches!(resource.0, Resource::Texture(_))); + + let texture_info = match &resource.0 { + Resource::Texture(texture) => texture, + _ => panic!("") + }; + + assert_eq!(texture_info.extent, crate::Extent{ width: 4096, height: 1024, depth: 1 }); + } + + #[ignore] + #[test] + fn load_local_image() { + let mut resource_manager = ResourceManager::new(); + + let resource_result = resource_manager.get("resources/test.png"); + + assert!(resource_result.is_some()); + + let resource = resource_result.unwrap(); + + assert!(matches!(resource.0, Resource::Texture(_))); + + let texture_info = match &resource.0 { + Resource::Texture(texture) => texture, + _ => panic!("") + }; + + assert!(texture_info.extent.width == 4096 && texture_info.extent.height == 1024 && texture_info.extent.depth == 1); + } + + #[test] + fn load_local_mesh() { + let mut resource_manager = ResourceManager::new(); + + let resource_result = resource_manager.get("resources/Box.gltf"); + + assert!(resource_result.is_some()); + + let resource = resource_result.unwrap(); + + assert!(matches!(resource.0, Resource::Mesh(_))); + + dbg!(&resource.0); + + let bytes = &resource.1; + + assert_eq!(bytes.len(), (24 /* vertices */ * (3 /* components per position */ * 4 /* float size */ + 3/*normals */ * 4) as usize).next_multiple_of(16) + 6/* cube faces */ * 2 /* triangles per face */ * 3 /* indices per triangle */ * 2 /* bytes per index */); + + if let Resource::Mesh(mesh) = &resource.0 { + assert_eq!(mesh.bounding_box, [[-0.5f32, -0.5f32, -0.5f32], [0.5f32, 0.5f32, 0.5f32]]); + assert_eq!(mesh.vertex_count, 24); + assert_eq!(mesh.index_count, 36); + assert_eq!(mesh.index_type, IntegralTypes::U16); + assert_eq!(mesh.vertex_components.len(), 2); + assert_eq!(mesh.vertex_components[0].semantic, VertexSemantics::Position); + assert_eq!(mesh.vertex_components[0].format, "vec3f"); + assert_eq!(mesh.vertex_components[0].channel, 0); + assert_eq!(mesh.vertex_components[1].semantic, VertexSemantics::Normal); + assert_eq!(mesh.vertex_components[1].format, "vec3f"); + assert_eq!(mesh.vertex_components[1].channel, 1); + } + + let resource_result = resource_manager.get("resources/Box.gltf"); + + assert!(resource_result.is_some()); + + let resource = resource_result.unwrap(); + + assert!(matches!(resource.0, Resource::Mesh(_))); + + let bytes = &resource.1; + + assert_eq!(bytes.len(), (24 /* vertices */ * (3 /* components per position */ * 4 /* float size */ + 3/*normals */ * 4) as usize).next_multiple_of(16) + 6/* cube faces */ * 2 /* triangles per face */ * 3 /* indices per triangle */ * 2 /* bytes per index */); + + if let Resource::Mesh(mesh) = &resource.0 { + assert_eq!(mesh.bounding_box, [[-0.5f32, -0.5f32, -0.5f32], [0.5f32, 0.5f32, 0.5f32]]); + assert_eq!(mesh.vertex_count, 24); + assert_eq!(mesh.index_count, 36); + assert_eq!(mesh.index_type, IntegralTypes::U16); + assert_eq!(mesh.vertex_components.len(), 2); + assert_eq!(mesh.vertex_components[0].semantic, VertexSemantics::Position); + assert_eq!(mesh.vertex_components[0].format, "vec3f"); + assert_eq!(mesh.vertex_components[0].channel, 0); + assert_eq!(mesh.vertex_components[1].semantic, VertexSemantics::Normal); + assert_eq!(mesh.vertex_components[1].format, "vec3f"); + assert_eq!(mesh.vertex_components[1].channel, 1); + } + } +} \ No newline at end of file diff --git a/src/shader_generator.rs b/src/shader_generator.rs new file mode 100644 index 00000000..c44113fc --- /dev/null +++ b/src/shader_generator.rs @@ -0,0 +1,620 @@ +//! The shader_generator module provides utilities to generate shaders. + +use json; + +pub struct ShaderGenerator { + +} + +fn translate_type(value: &str) -> &str { + match value { + "vec3f" => "vec3", + "vec4f" => "vec4", + "mat3f" => "mat3", + "mat4f" => "mat4", + "mat3x4f" => "mat4x3", + "mat4x3f" => "mat3x4", + "mat3x4" => "mat4x3", + "mat4x3" => "mat3x4", + _ => value + } +} + +impl ShaderGenerator { + fn new() -> ShaderGenerator { + ShaderGenerator {} + } + + /// Generates a shader from a source string and an environment\ + /// Environment: + /// glsl: + /// version: expects a string, if this value is not present, the default version is 450 + /// shader: + /// type: expects a string, can be "vertex", "fragment" or "compute" + /// vertex_layout: expects an array of objects, each object must have a "type" and a "name" field + /// input: expects an array of objects, each object must have a "type" and a "name" field + /// output: expects an array of objects, each object must have a "type" and a "name" field + /// local_size: expects an array of 3 numbers + /// descriptor_sets: expects an array of objects, each object must have a "set", "binding" and "value" field + /// set: expects a number + /// binding: expects a number + /// value: expects an object with a "type" and a "name" field + /// push_constants: expects an array of objects, each object must have a "type" and a "name" field + /// structs: expects an array of objects, each object must have a "name" and a "members" field + /// name: expects a string + /// members: expects an array of objects, each object must have a "type" and a "name" field + /// + /// Result: + /// Returns a string with the generated shader + /// Generated shaders will always look like + /// #version + /// #shader type + /// #extensions + /// memory layout declarations + /// struct declarations + /// descritor set declarations + /// push constant declarations + /// in blocks + /// out blocks + /// function declarations + /// "main decorators" + /// main function + /// + pub fn generate_shader(&self, base_shader: &str, environment: json::JsonValue) -> String { + let mut shader_string = String::new(); + + // version + + let glsl_version = &environment["glsl"]["version"]; + + if let json::JsonValue::String(glsl_version) = glsl_version { + shader_string.push_str("#version "); + shader_string.push_str(&glsl_version); // TODO: Get only first number + shader_string.push_str(" core\n"); + } else { + shader_string.push_str("#version 450 core\n"); + } + + // shader type + + let shader_type = &environment["shader"]["type"]; + + let shader_type = shader_type.as_str().unwrap_or(""); + + match shader_type { + "vertex" => shader_string.push_str("#pragma shader_stage(vertex)\n"), + "fragment" => shader_string.push_str("#pragma shader_stage(fragment)\n"), + "compute" => shader_string.push_str("#pragma shader_stage(compute)\n"), + _ => shader_string.push_str("#define BE_UNKNOWN_SHADER_TYPE\n") + } + + // extensions + + shader_string.push_str("#extension GL_EXT_shader_16bit_storage : enable\n"); + shader_string.push_str("#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable\n"); + shader_string.push_str("#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable\n"); + shader_string.push_str("#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable\n"); + shader_string.push_str("#extension GL_EXT_nonuniform_qualifier : enable\n"); + shader_string.push_str("#extension GL_EXT_scalar_block_layout : enable\n"); + shader_string.push_str("#extension GL_EXT_buffer_reference : enable\n"); + shader_string.push_str("#extension GL_EXT_buffer_reference2 : enable\n"); + shader_string.push_str("#extension GL_EXT_shader_image_load_formatted : enable\n"); + + match shader_type { + "compute" => { + shader_string.push_str("#extension GL_KHR_shader_subgroup_basic : enable\n"); + shader_string.push_str("#extension GL_KHR_shader_subgroup_arithmetic : enable\n"); + shader_string.push_str("#extension GL_KHR_shader_subgroup_ballot : enable\n"); + shader_string.push_str("#extension GL_KHR_shader_subgroup_shuffle : enable\n"); + } + _ => {} + } + + // memory layout declarations + + shader_string.push_str("layout(row_major) uniform; layout(row_major) buffer;\n"); + + // struct declarations + + let structs = &environment["shader"]["structs"]; + + if let json::JsonValue::Array(structs) = structs { + for e in structs { + shader_string.push_str("struct "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str(" {\n"); + + let members = &e["members"]; + + if let json::JsonValue::Array(members) = members { + for e in members { + shader_string.push_str(translate_type(&e["type"].as_str().unwrap())); + shader_string.push_str(" "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str(";\n"); + } + } + + shader_string.push_str("};\n"); + } + + for e in structs { + shader_string.push_str("layout(buffer_reference,scalar,buffer_reference_align=2) "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str("Pointer {\n"); + + let members = &e["members"]; + + if let json::JsonValue::Array(members) = members { + for e in members { + shader_string.push_str(translate_type(&e["type"].as_str().unwrap())); + shader_string.push_str(" "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str(";\n"); + } + } + + shader_string.push_str("};\n"); + } + } + + // descriptor set declarations + + let descriptor_sets = &environment["shader"]["descriptor_sets"]; + + if let json::JsonValue::Array(descriptor_sets) = descriptor_sets { + for e in descriptor_sets { + shader_string.push_str("layout(set="); + shader_string.push_str(&e["set"].to_string()); + shader_string.push_str(", binding="); + shader_string.push_str(&e["binding"].to_string()); + shader_string.push_str(") uniform "); + shader_string.push_str(translate_type(&e["value"]["type"].as_str().unwrap())); + shader_string.push_str(" "); + shader_string.push_str(&e["value"]["name"].as_str().unwrap()); + shader_string.push_str(";\n"); + } + } + + // push constant declarations + + let push_constants = &environment["shader"]["push_constants"]; + + if let json::JsonValue::Array(push_constants) = push_constants { + shader_string.push_str("layout(push_constant) uniform push_constants {\n"); + + for e in push_constants { + shader_string.push_str(translate_type(&e["type"].as_str().unwrap())); + shader_string.push_str(" "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str(";\n"); + } + + shader_string.push_str("} pc;\n"); + } + + // in blocks + + match shader_type { + "vertex" => { + let vertex_layout = &environment["shader"]["vertex_layout"]; + + if let json::JsonValue::Array(vertex_layout) = vertex_layout { + let mut pos = 0; + + for e in vertex_layout { + shader_string.push_str("layout(location="); + shader_string.push_str(&pos.to_string()); + shader_string.push_str(") in "); + shader_string.push_str(translate_type(&e["type"].as_str().unwrap())); + shader_string.push_str(" "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str(";\n"); + + pos += 1; + } + } + } + "fragment" => { + let input = &environment["shader"]["input"]; + + if let json::JsonValue::Array(input) = input { + let mut pos = 0; + + for e in input { + shader_string.push_str("layout(location="); + shader_string.push_str(&pos.to_string()); + shader_string.push_str(") in "); + shader_string.push_str(translate_type(&e["type"].as_str().unwrap())); + shader_string.push_str(" "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str(";\n"); + + pos += 1; + } + } + + let output = &environment["shader"]["output"]; + + if let json::JsonValue::Array(output) = output { + let mut pos = 0; + + for e in output { + shader_string.push_str("layout(location="); + shader_string.push_str(&pos.to_string()); + shader_string.push_str(") out "); + shader_string.push_str(&e["type"].as_str().unwrap()); + shader_string.push_str(" "); + shader_string.push_str(&e["name"].as_str().unwrap()); + shader_string.push_str(";\n"); + + pos += 1; + } + } + } + "compute" => { + let local_size = &environment["shader"]["local_size"]; + + if let json::JsonValue::Array(local_size) = local_size { + shader_string.push_str("layout(local_size_x="); + shader_string.push_str(&local_size[0].to_string()); + shader_string.push_str(", local_size_y="); + shader_string.push_str(&local_size[1].to_string()); + shader_string.push_str(", local_size_z="); + shader_string.push_str(&local_size[2].to_string()); + shader_string.push_str(") in;\n"); + } + } + _ => {} + } + + // main function + + shader_string.push_str(base_shader); + + shader_string + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] +fn test_translate_type() { + assert_eq!(translate_type("vec3f"), "vec3"); + assert_eq!(translate_type("vec4f"), "vec4"); + assert_eq!(translate_type("vec3"), "vec3"); + assert_eq!(translate_type("vec4"), "vec4"); + assert_eq!(translate_type("mat3f"), "mat3"); + assert_eq!(translate_type("mat4f"), "mat4"); + assert_eq!(translate_type("mat3"), "mat3"); + assert_eq!(translate_type("mat4"), "mat4"); + assert_eq!(translate_type("mat3x4f"), "mat4x3"); + assert_eq!(translate_type("mat4x3f"), "mat3x4"); + assert_eq!(translate_type("mat3x4"), "mat4x3"); + assert_eq!(translate_type("mat4x3"), "mat3x4"); +} + +#[test] +fn test_generate_no_shader() { + let shader_generator = ShaderGenerator::new(); +} + +#[test] +fn test_generate_vertex_shader() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + gl_Position = vec4(in_position, 1.0); +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { type: "vertex", vertex_layout:[{ type: "vec3", name: "in_position" }] } }); + + let final_shader = +"#version 450 core +#pragma shader_stage(vertex) +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +layout(row_major) uniform; layout(row_major) buffer; +layout(location=0) in vec3 in_position; +void main() { + gl_Position = vec4(in_position, 1.0); +}"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_generate_fragment_shader() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + out_color = in_color; +} +"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { type: "fragment", input:[{ type:"vec4", name:"in_color" }], output:[{ type:"vec4", name:"out_color" }] } }); + + let final_shader = +"#version 450 core +#pragma shader_stage(fragment) +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +layout(row_major) uniform; layout(row_major) buffer; +layout(location=0) in vec4 in_color; +layout(location=0) out vec4 out_color; +void main() { + out_color = in_color; +} +"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_generate_compute_shader() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + return; +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { type: "compute", local_size: [1, 1, 1] } }); + + let final_shader = +"#version 450 core +#pragma shader_stage(compute) +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +#extension GL_KHR_shader_subgroup_basic : enable +#extension GL_KHR_shader_subgroup_arithmetic : enable +#extension GL_KHR_shader_subgroup_ballot : enable +#extension GL_KHR_shader_subgroup_shuffle : enable +layout(row_major) uniform; layout(row_major) buffer; +layout(local_size_x=1, local_size_y=1, local_size_z=1) in; +void main() { + return; +}"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_generate_shader_no_version() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + return; +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { shader: { type: "compute", local_size: [1, 1, 1] } }); + + let final_shader = +"#version 450 core +#pragma shader_stage(compute) +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +#extension GL_KHR_shader_subgroup_basic : enable +#extension GL_KHR_shader_subgroup_arithmetic : enable +#extension GL_KHR_shader_subgroup_ballot : enable +#extension GL_KHR_shader_subgroup_shuffle : enable +layout(row_major) uniform; layout(row_major) buffer; +layout(local_size_x=1, local_size_y=1, local_size_z=1) in; +void main() { + return; +}"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_generate_shader_no_shader_type() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + return; +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { local_size: [1, 1, 1] } }); + + let final_shader = +"#version 450 core +#define BE_UNKNOWN_SHADER_TYPE +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +layout(row_major) uniform; layout(row_major) buffer; +void main() { + return; +}"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_push_constant() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + return; +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { type: "vertex", vertex_layout:[{ type: "vec3", name: "in_position" }], push_constants: [{ type: "mat4", name: "model_matrix" }] } }); + + let final_shader = +"#version 450 core +#pragma shader_stage(vertex) +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +layout(row_major) uniform; layout(row_major) buffer; +layout(push_constant) uniform push_constants { +mat4 model_matrix; +} pc; +layout(location=0) in vec3 in_position; +void main() { + return; +}"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_descriptor_sets() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + return; +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { descriptor_sets:[{ set: 0, binding: 0, value: { type: "sampler2D", name: "texture1" } }, { set: 0, binding: 1, value: { type: "sampler2D", name: "texture2" } }, { set: 1, binding: 0, value: { type: "sampler2D", name: "texture3" } }, { set: 3, binding: 0, value: { type: "sampler2D", name: "texture4" } }] } }); + + let final_shader = +"#version 450 core +#define BE_UNKNOWN_SHADER_TYPE +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +layout(row_major) uniform; layout(row_major) buffer; +layout(set=0, binding=0) uniform sampler2D texture1; +layout(set=0, binding=1) uniform sampler2D texture2; +layout(set=1, binding=0) uniform sampler2D texture3; +layout(set=3, binding=0) uniform sampler2D texture4; +void main() { + return; +}"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_descriptor_sets_and_push_constants() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + return; +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { descriptor_sets:[{ set: 0, binding: 0, value: { type: "sampler2D", name: "texture1" } }, { set: 0, binding: 1, value: { type: "sampler2D", name: "texture2" } }, { set: 1, binding: 0, value: { type: "sampler2D", name: "texture3" } }, { set: 3, binding: 0, value: { type: "sampler2D", name: "texture4" } }], push_constants: [{ type: "mat4", name: "model_matrix" }] } }); + + let final_shader = +"#version 450 core +#define BE_UNKNOWN_SHADER_TYPE +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +layout(row_major) uniform; layout(row_major) buffer; +layout(set=0, binding=0) uniform sampler2D texture1; +layout(set=0, binding=1) uniform sampler2D texture2; +layout(set=1, binding=0) uniform sampler2D texture3; +layout(set=3, binding=0) uniform sampler2D texture4; +layout(push_constant) uniform push_constants { +mat4 model_matrix; +} pc; +void main() { + return; +}"; + + assert_eq!(shader, final_shader); +} + +#[test] +fn test_struct_declarations() { + let shader_generator = ShaderGenerator::new(); + + let base_shader = +"void main() { + return; +}"; + + let shader = shader_generator.generate_shader(base_shader, json::object! { glsl: { version: "450" }, shader: { structs: [{ name: "Light", members: [{ type: "vec3", name: "position" }, { type: "vec3", name: "color" }] }] } }); + + let final_shader = +"#version 450 core +#define BE_UNKNOWN_SHADER_TYPE +#extension GL_EXT_shader_16bit_storage : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference : enable +#extension GL_EXT_buffer_reference2 : enable +#extension GL_EXT_shader_image_load_formatted : enable +layout(row_major) uniform; layout(row_major) buffer; +struct Light { +vec3 position; +vec3 color; +}; +layout(buffer_reference,scalar,buffer_reference_align=2) LightPointer { +vec3 position; +vec3 color; +}; +void main() { + return; +}"; + + assert_eq!(shader, final_shader); +} +} \ No newline at end of file diff --git a/src/vulkan_render_backend.rs b/src/vulkan_render_backend.rs new file mode 100644 index 00000000..11d66724 --- /dev/null +++ b/src/vulkan_render_backend.rs @@ -0,0 +1,1310 @@ +//! The Vulkan render backend. + +use ash::{vk, Entry}; + +use crate::render_backend; + +#[derive(Clone, Copy)] +pub struct Surface { + surface: vk::SurfaceKHR, + surface_capabilities: vk::SurfaceCapabilitiesKHR, + surface_format: vk::SurfaceFormatKHR, + surface_present_mode: vk::PresentModeKHR, +} + +#[derive(Clone, Copy)] +pub struct Swapchain { + swapchain: vk::SwapchainKHR, +} + +#[derive(Clone, Copy)] +pub struct DescriptorSetLayout { + descriptor_set_layout: vk::DescriptorSetLayout, +} + +#[derive(Clone, Copy)] +pub struct DescriptorSet { + descriptor_set: vk::DescriptorSet, +} + +#[derive(Clone, Copy)] +pub struct PipelineLayout { + pipeline_layout: vk::PipelineLayout, +} + +#[derive(Clone, Copy)] +pub struct Pipeline { + pipeline: vk::Pipeline, +} + +#[derive(Clone, Copy)] +pub struct CommandBuffer { + command_buffer: vk::CommandBuffer, +} + +#[derive(Clone, Copy)] +pub struct Allocation { + memory: vk::DeviceMemory, +} + +#[derive(Clone, Copy)] +pub struct Buffer { + buffer: vk::Buffer, + device_address: vk::DeviceAddress, +} + +#[derive(Clone, Copy)] +pub struct Synchronizer { + fence: vk::Fence, + semaphore: vk::Semaphore, +} + +#[derive(Clone, Copy)] +pub struct Sampler { + sampler: vk::Sampler, +} + +#[derive(Clone, Copy)] +pub struct Texture { + image: vk::Image, +} + +#[derive(Clone, Copy)] +pub struct TextureView { + image_view: vk::ImageView, +} + +#[derive(Clone, Copy)] +pub struct Shader { + shader_module: vk::ShaderModule, + stage: vk::ShaderStageFlags +} +#[derive(Clone, Copy)] +struct AccelerationStructure { + acceleration_structure: vk::AccelerationStructureKHR, +} + +pub struct VulkanRenderBackend { + entry: ash::Entry, + instance: ash::Instance, + debug_utils: ash::extensions::ext::DebugUtils, + debug_utils_messenger: vk::DebugUtilsMessengerEXT, + physical_device: vk::PhysicalDevice, + device: ash::Device, + queue_family_index: u32, + queue: vk::Queue, + swapchain: ash::extensions::khr::Swapchain, + surface: ash::extensions::khr::Surface, + acceleration_structure: ash::extensions::khr::AccelerationStructure, + ray_tracing_pipeline: ash::extensions::khr::RayTracingPipeline, + dynamic_rendering: ash::extensions::khr::DynamicRendering, +} + +static mut counter: u32 = 0; + +unsafe extern "system" fn vulkan_debug_utils_callback(message_severity: vk::DebugUtilsMessageSeverityFlagsEXT, message_type: vk::DebugUtilsMessageTypeFlagsEXT, p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT, _p_user_data: *mut std::ffi::c_void,) -> vk::Bool32 { + let message = std::ffi::CStr::from_ptr((*p_callback_data).p_message); + let severity = format!("{:?}", message_severity).to_lowercase(); + let ty = format!("{:?}", message_type).to_lowercase(); + println!("[Debug][{}][{}] {:?}", severity, ty, message); + + counter += 1; + + vk::FALSE +} + +fn to_clear_value(clear: crate::RGBA) -> vk::ClearValue { + vk::ClearValue { + color: vk::ClearColorValue { + float32: [clear.r, clear.g, clear.b, clear.a], + }, + } +} + +fn texture_format_and_resource_use_to_image_layout(_texture_format: render_backend::TextureFormats, layout: render_backend::Layouts, access: Option) -> vk::ImageLayout { + match layout { + render_backend::Layouts::Undefined => vk::ImageLayout::UNDEFINED, + render_backend::Layouts::RenderTarget => vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + render_backend::Layouts::Transfer => { + match access { + Some(a) => { + if a.intersects(render_backend::AccessPolicies::READ) { + vk::ImageLayout::TRANSFER_SRC_OPTIMAL + } else if a.intersects(render_backend::AccessPolicies::WRITE) { + vk::ImageLayout::TRANSFER_DST_OPTIMAL + } else { + vk::ImageLayout::UNDEFINED + } + } + None => vk::ImageLayout::UNDEFINED + } + } + render_backend::Layouts::Present => vk::ImageLayout::PRESENT_SRC_KHR, + render_backend::Layouts::Texture => vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, + } +} + +fn to_load_operation(value: bool) -> vk::AttachmentLoadOp { + if value { + vk::AttachmentLoadOp::LOAD + } else { + vk::AttachmentLoadOp::CLEAR + } +} + +fn to_store_operation(value: bool) -> vk::AttachmentStoreOp { + if value { + vk::AttachmentStoreOp::STORE + } else { + vk::AttachmentStoreOp::DONT_CARE + } +} + +fn to_format(format: render_backend::TextureFormats) -> vk::Format { + match format { + crate::render_backend::TextureFormats::RGBAu8 => vk::Format::R8G8B8A8_UNORM, + crate::render_backend::TextureFormats::RGBAu16 => vk::Format::R16G16B16A16_SFLOAT, + crate::render_backend::TextureFormats::RGBAu32 => vk::Format::R32G32B32A32_SFLOAT, + crate::render_backend::TextureFormats::RGBAf16 => vk::Format::R16G16B16A16_SFLOAT, + crate::render_backend::TextureFormats::RGBAf32 => vk::Format::R32G32B32A32_SFLOAT, + crate::render_backend::TextureFormats::RGBu10u10u11 => vk::Format::R16G16_S10_5_NV, + crate::render_backend::TextureFormats::BGRAu8 => vk::Format::B8G8R8A8_SRGB, + crate::render_backend::TextureFormats::Depth32 => vk::Format::D32_SFLOAT, + } +} + +fn to_shader_stage_flags(shader_type: crate::render_backend::ShaderTypes) -> vk::ShaderStageFlags { + match shader_type { + crate::render_backend::ShaderTypes::Vertex => vk::ShaderStageFlags::VERTEX, + crate::render_backend::ShaderTypes::Fragment => vk::ShaderStageFlags::FRAGMENT, + crate::render_backend::ShaderTypes::Compute => vk::ShaderStageFlags::COMPUTE, + } +} + +fn to_pipeline_stage_flags(stages: crate::render_backend::Stages) -> vk::PipelineStageFlags2 { + let mut pipeline_stage_flags = vk::PipelineStageFlags2::NONE; + + if stages.contains(crate::render_backend::Stages::VERTEX) { + pipeline_stage_flags |= vk::PipelineStageFlags2::VERTEX_SHADER + } + + if stages.contains(crate::render_backend::Stages::FRAGMENT) { + pipeline_stage_flags |= vk::PipelineStageFlags2::FRAGMENT_SHADER + } + + if stages.contains(crate::render_backend::Stages::COMPUTE) { + pipeline_stage_flags |= vk::PipelineStageFlags2::COMPUTE_SHADER + } + + if stages.contains(crate::render_backend::Stages::TRANSFER) { + pipeline_stage_flags |= vk::PipelineStageFlags2::TRANSFER + } + + pipeline_stage_flags +} + +fn to_access_flags(accesses: crate::render_backend::AccessPolicies, stages: crate::render_backend::Stages) -> vk::AccessFlags2 { + let mut access_flags = vk::AccessFlags2::empty(); + + if accesses.contains(crate::render_backend::AccessPolicies::READ) { + if stages.intersects(crate::render_backend::Stages::TRANSFER) { + access_flags |= vk::AccessFlags2::TRANSFER_READ + } + } + + if accesses.contains(crate::render_backend::AccessPolicies::WRITE) { + if stages.intersects(crate::render_backend::Stages::TRANSFER) { + access_flags |= vk::AccessFlags2::TRANSFER_WRITE + } + } + + access_flags +} + +impl Into for render_backend::Stages { + fn into(self) -> vk::ShaderStageFlags { + let mut shader_stage_flags = vk::ShaderStageFlags::default(); + + if self.intersects(render_backend::Stages::VERTEX) { + shader_stage_flags |= vk::ShaderStageFlags::VERTEX + } + + if self.intersects(render_backend::Stages::FRAGMENT) { + shader_stage_flags |= vk::ShaderStageFlags::FRAGMENT + } + + if self.intersects(render_backend::Stages::COMPUTE) { + shader_stage_flags |= vk::ShaderStageFlags::COMPUTE + } + + shader_stage_flags + } +} + +impl VulkanRenderBackend { + pub fn new() -> VulkanRenderBackend { + let entry: ash::Entry = Entry::linked(); + + let application_info = vk::ApplicationInfo::default() + .api_version(vk::make_api_version(0, 1, 3, 0)); + + let layer_names = [ + #[cfg(debug_assertions)] + std::ffi::CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap().as_ptr(), + /*std::ffi::CStr::from_bytes_with_nul(b"VK_LAYER_LUNARG_api_dump\0").unwrap().as_ptr(),*/ + ]; + + let extension_names = [ + #[cfg(debug_assertions)] + ash::extensions::ext::DebugUtils::NAME.as_ptr(), + ash::extensions::khr::Surface::NAME.as_ptr(), + ash::extensions::khr::XcbSurface::NAME.as_ptr(), + ]; + + let instance_create_info = vk::InstanceCreateInfo::default() + .application_info(&application_info) + .enabled_layer_names(&layer_names) + .enabled_extension_names(&extension_names) + /* .build() */; + + + let instance = unsafe { entry.create_instance(&instance_create_info, None).expect("No instance") }; + + let debug_utils = ash::extensions::ext::DebugUtils::new(&entry, &instance); + + let debug_utils_create_info = vk::DebugUtilsMessengerCreateInfoEXT::default() + .message_severity( + vk::DebugUtilsMessageSeverityFlagsEXT::WARNING + | vk::DebugUtilsMessageSeverityFlagsEXT::ERROR, + ) + .message_type( + vk::DebugUtilsMessageTypeFlagsEXT::GENERAL + | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION + | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE, + ) + .pfn_user_callback(Some(vulkan_debug_utils_callback)); + + let debug_utils_messenger = unsafe { debug_utils.create_debug_utils_messenger(&debug_utils_create_info, None).expect("Debug Utils Callback") }; + + let physical_devices = unsafe { instance.enumerate_physical_devices().expect("No physical devices.") }; + + let physical_device; + + { + let best_physical_device = crate::render_system::select_by_score(physical_devices.as_slice(), |physical_device| { + let properties = unsafe { instance.get_physical_device_properties(*physical_device) }; + + let mut device_score = 0 as i64; + + device_score += match properties.device_type { + vk::PhysicalDeviceType::DISCRETE_GPU => 1000, + _ => 0, + }; + + device_score += properties.limits.max_image_dimension2_d as i64; + + device_score + }); + + physical_device = *best_physical_device.expect("No physical devices."); + } + + let queue_family_properties = unsafe { instance.get_physical_device_queue_family_properties(physical_device) }; + + let queue_family_index = queue_family_properties + .iter() + .enumerate() + .find_map(|(index, ref info)| { + let supports_graphics = info.queue_flags.contains(vk::QueueFlags::GRAPHICS); + let supports_compute = info.queue_flags.contains(vk::QueueFlags::COMPUTE); + let supports_transfer = info.queue_flags.contains(vk::QueueFlags::TRANSFER); + + if supports_graphics && supports_compute && supports_transfer { + Some(index as u32) + } else { + None + } + }) + .expect("No queue family index found."); + + let device_extension_names = [ + ash::extensions::khr::Swapchain::NAME.as_ptr(), + ash::extensions::khr::DynamicRendering::NAME.as_ptr(), + ]; + + let queue_create_infos = [vk::DeviceQueueCreateInfo::default() + .queue_family_index(queue_family_index) + .queue_priorities(&[1.0]) + /* .build() */]; + + let mut buffer_device_address_features = vk::PhysicalDeviceBufferDeviceAddressFeatures::default().buffer_device_address(true); + let mut dynamic_rendering_features = vk::PhysicalDeviceDynamicRenderingFeatures::default().dynamic_rendering(true); + let mut synchronization2_features = vk::PhysicalDeviceSynchronization2FeaturesKHR::default().synchronization2(true); + + let enabled_physical_device_features = vk::PhysicalDeviceFeatures::default(); + + let device_create_info = vk::DeviceCreateInfo::default() + .push_next(&mut buffer_device_address_features/* .build() */) + .push_next(&mut dynamic_rendering_features/* .build() */) + .push_next(&mut synchronization2_features/* .build() */) + .queue_create_infos(&queue_create_infos) + .enabled_extension_names(&device_extension_names) + .enabled_features(&enabled_physical_device_features/* .build() */) + /* .build() */; + + let device: ash::Device = unsafe { instance.create_device(physical_device, &device_create_info, None).expect("No device") }; + + let queue = unsafe { device.get_device_queue(queue_family_index, 0) }; + + let acceleration_structure = ash::extensions::khr::AccelerationStructure::new(&instance, &device); + let ray_tracing_pipeline = ash::extensions::khr::RayTracingPipeline::new(&instance, &device); + let dynamic_rendering = ash::extensions::khr::DynamicRendering::new(&instance, &device); + + let swapchain = ash::extensions::khr::Swapchain::new(&instance, &device); + let surface = ash::extensions::khr::Surface::new(&entry, &instance); + + VulkanRenderBackend { + entry, + instance, + debug_utils, + debug_utils_messenger, + physical_device, + device, + queue_family_index, + queue, + swapchain, + surface, + acceleration_structure, + ray_tracing_pipeline, + dynamic_rendering, + } + } +} + +impl render_backend::RenderBackend for VulkanRenderBackend { + fn get_log_count(&self) -> u32 { + unsafe { counter } + } + + fn create_descriptor_set_layout(&self, bindings: &[render_backend::DescriptorSetLayoutBinding]) -> render_backend::DescriptorSetLayout { + let mut ll = Vec::new(); + + let descriptor_set_layout_bindings = bindings + .iter() + .map(|binding| { + let b = vk::DescriptorSetLayoutBinding::default() + .binding(binding.binding) + .descriptor_type(match binding.descriptor_type { + render_backend::DescriptorType::UniformBuffer => vk::DescriptorType::UNIFORM_BUFFER, + render_backend::DescriptorType::StorageBuffer => vk::DescriptorType::STORAGE_BUFFER, + render_backend::DescriptorType::SampledImage => vk::DescriptorType::SAMPLED_IMAGE, + render_backend::DescriptorType::StorageImage => vk::DescriptorType::STORAGE_IMAGE, + render_backend::DescriptorType::Sampler => vk::DescriptorType::SAMPLER, + }) + .descriptor_count(binding.descriptor_count) + .stage_flags(binding.stage_flags.into()); + + if let Some(immutable_samplers) = &binding.immutable_samplers { + let l = immutable_samplers.iter().map(|sampler| sampler.vulkan_sampler.sampler).collect::>(); + let b = b.immutable_samplers(unsafe { std::slice::from_raw_parts(l.as_ptr(), l.len()) }); // WARNING: Don't how else to return a slice of l which gets stored in an outer scope, which should be safe since l is not dropped. + ll.push(l); + b + } else { + b + } + }) + .collect::>(); + + let descriptor_set_layout_create_info = vk::DescriptorSetLayoutCreateInfo::default() + .bindings(&descriptor_set_layout_bindings) + /* .build() */; + + let descriptor_set_layout = unsafe { self.device.create_descriptor_set_layout(&descriptor_set_layout_create_info, None).expect("No descriptor set layout") }; + + render_backend::DescriptorSetLayout { + vulkan_descriptor_set_layout: DescriptorSetLayout { + descriptor_set_layout, + }, + } + } + + fn create_descriptor_set(&self, descriptor_set_layout: &render_backend::DescriptorSetLayout, bindings: &[render_backend::DescriptorSetLayoutBinding]) -> render_backend::DescriptorSet { + let pool_sizes = bindings + .iter() + .map(|binding| { + vk::DescriptorPoolSize::default() + .ty(match binding.descriptor_type { + render_backend::DescriptorType::UniformBuffer => vk::DescriptorType::UNIFORM_BUFFER, + render_backend::DescriptorType::StorageBuffer => vk::DescriptorType::STORAGE_BUFFER, + render_backend::DescriptorType::SampledImage => vk::DescriptorType::SAMPLED_IMAGE, + render_backend::DescriptorType::StorageImage => vk::DescriptorType::STORAGE_IMAGE, + render_backend::DescriptorType::Sampler => vk::DescriptorType::SAMPLER, + }) + .descriptor_count(binding.descriptor_count) + /* .build() */ + }) + .collect::>(); + + let descriptor_pool_create_info = vk::DescriptorPoolCreateInfo::default() + .max_sets(3) + .pool_sizes(&pool_sizes); + + let descriptor_pool = unsafe { self.device.create_descriptor_pool(&descriptor_pool_create_info, None).expect("No descriptor pool") }; + + let descriptor_set_layouts = [unsafe { descriptor_set_layout.vulkan_descriptor_set_layout.descriptor_set_layout }]; + + let descriptor_set_allocate_info = vk::DescriptorSetAllocateInfo::default() + .descriptor_pool(descriptor_pool) + .set_layouts(&descriptor_set_layouts) + /* .build() */; + + let descriptor_set = unsafe { self.device.allocate_descriptor_sets(&descriptor_set_allocate_info).expect("No descriptor set") }; + + render_backend::DescriptorSet { + vulkan_descriptor_set: DescriptorSet { + descriptor_set: descriptor_set[0], + }, + } + } + + fn write_descriptors(&self, descriptor_set_writes: &[render_backend::DescriptorSetWrite]) { + for descriptor_set_write in descriptor_set_writes { + let mut buffers: Vec = Vec::new(); + let mut images: Vec = Vec::new(); + + let descriptor_type = match descriptor_set_write.descriptor_type { + render_backend::DescriptorType::UniformBuffer => vk::DescriptorType::UNIFORM_BUFFER, + render_backend::DescriptorType::StorageBuffer => vk::DescriptorType::STORAGE_BUFFER, + render_backend::DescriptorType::SampledImage => vk::DescriptorType::SAMPLED_IMAGE, + render_backend::DescriptorType::StorageImage => vk::DescriptorType::STORAGE_IMAGE, + render_backend::DescriptorType::Sampler => vk::DescriptorType::SAMPLER, + }; + + let write_info = vk::WriteDescriptorSet::default() + .dst_set(unsafe { descriptor_set_write.descriptor_set.vulkan_descriptor_set.descriptor_set }) + .dst_binding(descriptor_set_write.binding) + .dst_array_element(descriptor_set_write.array_element) + .descriptor_type(descriptor_type) + ; + + let write_info = match descriptor_set_write.descriptor_info { + render_backend::DescriptorInfo::Buffer { buffer, offset, range } => { + let a = vk::DescriptorBufferInfo::default() + .buffer(unsafe { buffer.vulkan_buffer.buffer }) + .offset(offset) + .range(range); + buffers.push(a); + write_info.buffer_info(&buffers) + }, + render_backend::DescriptorInfo::Texture { texture, format, layout } => { + let a = vk::DescriptorImageInfo::default() + .image_layout(texture_format_and_resource_use_to_image_layout(format, layout, None)) + .image_view(unsafe { texture.vulkan_texture_view.image_view }); + images.push(a); + write_info.image_info(&images) + }, + _ => panic!("Invalid descriptor info"), + }; + + unsafe { self.device.update_descriptor_sets(&[write_info], &[]) }; + } + + } + + fn create_command_buffer(&self) -> crate::render_backend::CommandBuffer { + let command_pool_create_info = vk::CommandPoolCreateInfo::default() + .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER) + .queue_family_index(self.queue_family_index) + /* .build() */; + + let command_pool = unsafe { self.device.create_command_pool(&command_pool_create_info, None).expect("No command pool") }; + + let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::default() + .command_pool(command_pool) + .level(vk::CommandBufferLevel::PRIMARY) + .command_buffer_count(1) + /* .build() */; + + let command_buffer = unsafe { self.device.allocate_command_buffers(&command_buffer_allocate_info).expect("No command buffer") }; + + crate::render_backend::CommandBuffer { + vulkan_command_buffer: CommandBuffer { + command_buffer: command_buffer[0], + }, + } + } + + fn create_pipeline_layout(&self, descriptor_set_layouts: &[crate::render_backend::DescriptorSetLayout]) -> crate::render_backend::PipelineLayout { + let push_constant_ranges = [vk::PushConstantRange::default().size(64).offset(0).stage_flags(vk::ShaderStageFlags::VERTEX)]; + let set_layouts = descriptor_set_layouts.iter().map(|set_layout| unsafe { set_layout.vulkan_descriptor_set_layout.descriptor_set_layout }).collect::>(); + + let pipeline_layout_create_info = vk::PipelineLayoutCreateInfo::default() + .set_layouts(&set_layouts) + .push_constant_ranges(&push_constant_ranges) + /* .build() */; + + let pipeline_layout = unsafe { self.device.create_pipeline_layout(&pipeline_layout_create_info, None).expect("No pipeline layout") }; + + crate::render_backend::PipelineLayout { + vulkan_pipeline_layout: PipelineLayout { + pipeline_layout, + }, + } + } + + fn create_shader(&self, stage: crate::render_backend::ShaderTypes, shader: &[u8]) -> crate::render_backend::Shader { + let shader_module_create_info = vk::ShaderModuleCreateInfo::default() + .code(unsafe { shader.align_to::().1 }) + /* .build() */; + + let shader_module = unsafe { self.device.create_shader_module(&shader_module_create_info, None).expect("No shader module") }; + + crate::render_backend::Shader { + vulkan_shader: Shader { + shader_module, + stage: to_shader_stage_flags(stage), + }, + } + } + + fn create_pipeline(&self, pipeline_layout: &render_backend::PipelineLayout, shaders: &[render_backend::Shader]) -> crate::render_backend::Pipeline { + let stages = shaders + .iter() + .map(|shader| { + vk::PipelineShaderStageCreateInfo::default() + .stage(unsafe { shader.vulkan_shader.stage }) + .module(unsafe { shader.vulkan_shader.shader_module }) + .name(std::ffi::CStr::from_bytes_with_nul(b"main\0").unwrap()) + /* .build() */ + }) + .collect::>(); + + let viewports = [vk::Viewport::default() + .x(0.0) + .y(9.0) + .width(16.0) + .height(-9.0) + .min_depth(0.0) + .max_depth(1.0) + /* .build() */]; + + let scissors = [vk::Rect2D::default() + .offset(vk::Offset2D { x: 0, y: 0 }) + .extent(vk::Extent2D { width: 16, height: 9 }) + /* .build() */]; + + let viewport_state = vk::PipelineViewportStateCreateInfo::default() + .viewports(&viewports) + .scissors(&scissors) + /* .build() */; + + let mut rendering_info = vk::PipelineRenderingCreateInfo::default() + .color_attachment_formats(&[vk::Format::R8G8B8A8_UNORM]) + .depth_attachment_format(vk::Format::UNDEFINED) + /* .build() */; + + let dynamic_state = vk::PipelineDynamicStateCreateInfo::default() + .dynamic_states(&[vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR]) + /* .build() */; + + let attachments = [ + vk::PipelineColorBlendAttachmentState::default() + .color_write_mask(vk::ColorComponentFlags::RGBA) + .blend_enable(false) + .src_color_blend_factor(vk::BlendFactor::ONE) + .dst_color_blend_factor(vk::BlendFactor::ZERO) + .color_blend_op(vk::BlendOp::ADD) + .src_alpha_blend_factor(vk::BlendFactor::ONE) + .dst_alpha_blend_factor(vk::BlendFactor::ZERO) + .alpha_blend_op(vk::BlendOp::ADD) + /* .build() */, + ]; + + let color_blend_state = &vk::PipelineColorBlendStateCreateInfo::default() + .logic_op_enable(false) + .logic_op(vk::LogicOp::COPY) + .attachments(&attachments) + .blend_constants([0.0, 0.0, 0.0, 0.0]) + /* .build() */; + + let multisample_state = vk::PipelineMultisampleStateCreateInfo::default() + .sample_shading_enable(false) + .rasterization_samples(vk::SampleCountFlags::TYPE_1) + .min_sample_shading(1.0) + .alpha_to_coverage_enable(false) + .alpha_to_one_enable(false) + /* .build() */; + + let depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo::default() + .depth_test_enable(false) + .depth_write_enable(false) + .depth_compare_op(vk::CompareOp::ALWAYS) + .depth_bounds_test_enable(false) + .stencil_test_enable(false) + .front(vk::StencilOpState::default()/* .build() */) + .back(vk::StencilOpState::default()/* .build() */) + /* .build() */; + + let input_assembly_state = vk::PipelineInputAssemblyStateCreateInfo::default() + .topology(vk::PrimitiveTopology::TRIANGLE_LIST) + .primitive_restart_enable(false) + /* .build() */; + + let vertex_input_attribute_descriptions = [ + vk::VertexInputAttributeDescription::default() + .binding(0) + .location(0) + .format(vk::Format::R32G32B32_SFLOAT) + .offset(0) + /* .build() */, + vk::VertexInputAttributeDescription::default() + .binding(0) + .location(1) + .format(vk::Format::R32G32B32A32_SFLOAT) + .offset(12) + /* .build() */, + ]; + + let vertex_binding_descriptions = [ + vk::VertexInputBindingDescription::default() + .binding(0) + .stride(28) + .input_rate(vk::VertexInputRate::VERTEX) + /* .build() */, + ]; + + let vertex_input_state = vk::PipelineVertexInputStateCreateInfo::default() + .vertex_attribute_descriptions(&vertex_input_attribute_descriptions) + .vertex_binding_descriptions(&vertex_binding_descriptions) + /* .build() */; + + let rasterization_state = vk::PipelineRasterizationStateCreateInfo::default() + .depth_clamp_enable(false) + .rasterizer_discard_enable(false) + .polygon_mode(vk::PolygonMode::FILL) + .cull_mode(vk::CullModeFlags::NONE) + .front_face(vk::FrontFace::CLOCKWISE) + .depth_bias_enable(false) + .depth_bias_constant_factor(0.0) + .depth_bias_clamp(0.0) + .depth_bias_slope_factor(0.0) + .line_width(1.0); + + let mut pipeline_create_infos = [vk::GraphicsPipelineCreateInfo::default() + .push_next(&mut rendering_info) + .layout(unsafe { pipeline_layout.vulkan_pipeline_layout.pipeline_layout }) + .render_pass(vk::RenderPass::null()) // We use a null render pass because of VK_KHR_dynamic_rendering + .color_blend_state(&color_blend_state) + .depth_stencil_state(&depth_stencil_state) + .dynamic_state(&dynamic_state) + .input_assembly_state(&input_assembly_state) + .vertex_input_state(&vertex_input_state) + .rasterization_state(&rasterization_state) + .viewport_state(&viewport_state) + .multisample_state(&multisample_state) + .stages(&stages) + /* .build() */ + ]; + + pipeline_create_infos[0].p_viewport_state = &viewport_state; + + let pipeline = unsafe { self.device.create_graphics_pipelines(vk::PipelineCache::null(), &pipeline_create_infos, None).expect("No pipeline") }; + + crate::render_backend::Pipeline { + vulkan_pipeline: Pipeline { + pipeline: pipeline[0], + }, + } + } + + fn allocate_memory(&self, size: u64, device_accesses: crate::render_system::DeviceAccesses) -> crate::render_backend::Allocation { + // get memory types + let memory_properties = unsafe { self.instance.get_physical_device_memory_properties(self.physical_device) }; + + let memory_type_index = memory_properties + .memory_types + .iter() + .enumerate() + .find_map(|(index, memory_type)| { + let mut memory_property_flags = vk::MemoryPropertyFlags::empty(); + + memory_property_flags |= if device_accesses.contains(crate::render_system::DeviceAccesses::CpuRead) { vk::MemoryPropertyFlags::HOST_VISIBLE } else { vk::MemoryPropertyFlags::empty() }; + memory_property_flags |= if device_accesses.contains(crate::render_system::DeviceAccesses::CpuWrite) { vk::MemoryPropertyFlags::HOST_COHERENT } else { vk::MemoryPropertyFlags::empty() }; + memory_property_flags |= if device_accesses.contains(crate::render_system::DeviceAccesses::GpuRead) { vk::MemoryPropertyFlags::DEVICE_LOCAL } else { vk::MemoryPropertyFlags::empty() }; + memory_property_flags |= if device_accesses.contains(crate::render_system::DeviceAccesses::GpuWrite) { vk::MemoryPropertyFlags::DEVICE_LOCAL } else { vk::MemoryPropertyFlags::empty() }; + + let memory_type = memory_type.property_flags.contains(memory_property_flags); + + if memory_type { + Some(index as u32) + } else { + None + } + }) + .expect("No memory type index found."); + + let mut memory_allocate_flags_info = vk::MemoryAllocateFlagsInfo::default().flags(vk::MemoryAllocateFlags::DEVICE_ADDRESS); + + let memory_allocate_info = vk::MemoryAllocateInfo::default() + .allocation_size(size) + .memory_type_index(memory_type_index) + .push_next(&mut memory_allocate_flags_info) + /* .build() */; + + let memory = unsafe { self.device.allocate_memory(&memory_allocate_info, None).expect("No memory") }; + + let mut mapped_memory = std::ptr::null_mut(); + + if device_accesses.intersects(crate::render_system::DeviceAccesses::CpuRead | crate::render_system::DeviceAccesses::CpuWrite) { + mapped_memory = unsafe { self.device.map_memory(memory, 0, size, vk::MemoryMapFlags::empty()).expect("No mapped memory") as *mut u8 }; + } + + crate::render_backend::Allocation { + vulkan_allocation: Allocation{ + memory, + }, + pointer: mapped_memory, + } + } + + fn get_allocation_pointer(&self, allocation: &crate::render_backend::Allocation) -> *mut u8 { + allocation.pointer + } + + fn create_buffer(&self, size: u64, resource_uses: render_backend::Uses) -> crate::render_backend::MemoryBackedResourceCreationResult { + let buffer_create_info = vk::BufferCreateInfo::default() + .size(size) + .sharing_mode(vk::SharingMode::EXCLUSIVE) + .usage( + if resource_uses.contains(render_backend::Uses::Vertex) { vk::BufferUsageFlags::VERTEX_BUFFER } else { vk::BufferUsageFlags::empty() } + | + if resource_uses.contains(render_backend::Uses::Index) { vk::BufferUsageFlags::INDEX_BUFFER } else { vk::BufferUsageFlags::empty() } + | + if resource_uses.contains(render_backend::Uses::Uniform) { vk::BufferUsageFlags::UNIFORM_BUFFER } else { vk::BufferUsageFlags::empty() } + | + vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS /*We allways use this feature so include constantly*/ + ) + /* .build() */; + + let buffer = unsafe { self.device.create_buffer(&buffer_create_info, None).expect("No buffer") }; + + let memory_requirements = unsafe { self.device.get_buffer_memory_requirements(buffer) }; + + crate::render_backend::MemoryBackedResourceCreationResult{ + resource: crate::render_backend::Buffer { + vulkan_buffer: Buffer { + buffer, + device_address: 0, + }, + }, + size: memory_requirements.size + } + } + + fn create_texture(&self, extent: crate::Extent, format: crate::render_backend::TextureFormats, resource_uses: render_backend::Uses, device_accesses: crate::render_system::DeviceAccesses, _access_policies: crate::render_backend::AccessPolicies, mip_levels: u32) -> crate::render_backend::MemoryBackedResourceCreationResult { + let image_type_from_extent = |extent: crate::Extent| { + if extent.depth > 1 { + vk::ImageType::TYPE_3D + } else if extent.height > 1 { + vk::ImageType::TYPE_2D + } else { + vk::ImageType::TYPE_1D + } + }; + + let image_create_info = vk::ImageCreateInfo::default() + .image_type(image_type_from_extent(extent)) + .format(to_format(format)) + .extent(vk::Extent3D{ + width: extent.width, + height: extent.height, + depth: 1, + }) + .mip_levels(mip_levels) + .array_layers(1) + .samples(vk::SampleCountFlags::TYPE_1) + .tiling(if !device_accesses.intersects(crate::render_system::DeviceAccesses::CpuRead | crate::render_system::DeviceAccesses::CpuWrite) { vk::ImageTiling::OPTIMAL } else { vk::ImageTiling::LINEAR }) + .usage( + if resource_uses.intersects(render_backend::Uses::Texture) { vk::ImageUsageFlags::SAMPLED } else { vk::ImageUsageFlags::empty() } + | + if resource_uses.intersects(render_backend::Uses::RenderTarget) { vk::ImageUsageFlags::COLOR_ATTACHMENT } else { vk::ImageUsageFlags::empty() } + | + if resource_uses.intersects(render_backend::Uses::DepthStencil) { vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT } else { vk::ImageUsageFlags::empty() } + | + if resource_uses.intersects(render_backend::Uses::TransferSource) { vk::ImageUsageFlags::TRANSFER_SRC } else { vk::ImageUsageFlags::empty() } + | + if resource_uses.intersects(render_backend::Uses::TransferDestination) { vk::ImageUsageFlags::TRANSFER_DST } else { vk::ImageUsageFlags::empty() } + ) + .sharing_mode(vk::SharingMode::EXCLUSIVE) + .initial_layout(vk::ImageLayout::UNDEFINED) + /* .build() */; + + let image = unsafe { self.device.create_image(&image_create_info, None).expect("No image") }; + + let memory_requirements = unsafe { self.device.get_image_memory_requirements(image) }; + + crate::render_backend::MemoryBackedResourceCreationResult { + resource: crate::render_backend::Texture { + vulkan_texture: Texture{ + image, + }, + }, + size: memory_requirements.size + } + } + + fn create_sampler(&self) -> render_backend::Sampler { + let sampler_create_info = vk::SamplerCreateInfo::default() + .mag_filter(vk::Filter::NEAREST) + .min_filter(vk::Filter::NEAREST) + .mipmap_mode(vk::SamplerMipmapMode::NEAREST) + .address_mode_u(vk::SamplerAddressMode::REPEAT) + .address_mode_v(vk::SamplerAddressMode::REPEAT) + .address_mode_w(vk::SamplerAddressMode::REPEAT) + .anisotropy_enable(false) + .max_anisotropy(1.0) + .compare_enable(false) + .compare_op(vk::CompareOp::ALWAYS) + .min_lod(0.0) + .max_lod(0.0) + .mip_lod_bias(0.0) + .unnormalized_coordinates(false) + /* .build() */; + + let sampler = unsafe { self.device.create_sampler(&sampler_create_info, None).expect("No sampler") }; + + render_backend::Sampler { + vulkan_sampler: Sampler { + sampler, + }, + } + } + + fn get_image_subresource_layout(&self, texture: &render_backend::Texture, mip_level: u32) -> render_backend::ImageSubresourceLayout { + let image_subresource = vk::ImageSubresource { + aspect_mask: vk::ImageAspectFlags::COLOR, + mip_level, + array_layer: 0, + }; + + let image_subresource_layout = unsafe { self.device.get_image_subresource_layout(texture.vulkan_texture.image, image_subresource) }; + + render_backend::ImageSubresourceLayout { + offset: image_subresource_layout.offset, + size: image_subresource_layout.size, + row_pitch: image_subresource_layout.row_pitch, + array_pitch: image_subresource_layout.array_pitch, + depth_pitch: image_subresource_layout.depth_pitch, + } + } + + fn bind_buffer_memory(&self, memory: crate::render_backend::Memory, resource_creation_info: &crate::render_backend::MemoryBackedResourceCreationResult) { + unsafe { self.device.bind_buffer_memory(resource_creation_info.resource.vulkan_buffer.buffer, memory.allocation.vulkan_allocation.memory, memory.offset).expect("No buffer memory binding") }; + } + + fn bind_texture_memory(&self, memory: crate::render_backend::Memory, resource_creation_info: &crate::render_backend::MemoryBackedResourceCreationResult) { + unsafe { self.device.bind_image_memory(resource_creation_info.resource.vulkan_texture.image, memory.allocation.vulkan_allocation.memory, memory.offset).expect("No image memory binding") }; + //let image_view = unsafe { self.device.create_image_view(&image_view_create_info, None).expect("No image view") }; + //resource_creation_info.resource.vulkan_texture.image_view = image_view; + } + + fn create_synchronizer(&self, signaled: bool) -> crate::render_backend::Synchronizer { + let fence_create_info = vk::FenceCreateInfo::default() + .flags(vk::FenceCreateFlags::empty() | if signaled { vk::FenceCreateFlags::SIGNALED } else { vk::FenceCreateFlags::empty() }) + /* .build() */; + + let fence = unsafe { self.device.create_fence(&fence_create_info, None).expect("No fence") }; + + let semaphore_create_info = vk::SemaphoreCreateInfo::default() + /* .build() */; + + let semaphore = unsafe { self.device.create_semaphore(&semaphore_create_info, None).expect("No semaphore") }; + + crate::render_backend::Synchronizer { + vulkan_synchronizer: Synchronizer { + fence, + semaphore, + }, + } + } + + fn create_texture_view(&self, texture: &crate::render_backend::Texture, format: render_backend::TextureFormats, _mip_levels: u32) -> crate::render_backend::TextureView { + let image_view_create_info = vk::ImageViewCreateInfo::default() + .image(unsafe { texture.vulkan_texture.image }) + .view_type( + vk::ImageViewType::TYPE_2D + ) + .format(to_format(format)) + .components(vk::ComponentMapping { + r: vk::ComponentSwizzle::IDENTITY, + g: vk::ComponentSwizzle::IDENTITY, + b: vk::ComponentSwizzle::IDENTITY, + a: vk::ComponentSwizzle::IDENTITY, + }) + .subresource_range(vk::ImageSubresourceRange { + aspect_mask: vk::ImageAspectFlags::COLOR, + base_mip_level: 0, + level_count: 1, + base_array_layer: 0, + layer_count: 1, + }) + /* .build() */; + + let image_view = unsafe { self.device.create_image_view(&image_view_create_info, None).expect("No image view") }; + + crate::render_backend::TextureView { + vulkan_texture_view: TextureView { + image_view, + }, + } + } + + fn get_surface_properties(&self, surface: &crate::render_backend::Surface) -> crate::render_backend::SurfaceProperties { + let surface_capabilities = unsafe { self.surface.get_physical_device_surface_capabilities(self.physical_device, surface.vulkan_surface.surface).expect("No surface capabilities") }; + + crate::render_backend::SurfaceProperties { + extent: crate::Extent { + width: surface_capabilities.current_extent.width, + height: surface_capabilities.current_extent.height, + depth: 1, + }, + } + } + + fn create_surface(&self, window_os_handles: crate::window_system::WindowOsHandles) -> crate::render_backend::Surface { + let xcb_surface_create_info = vk::XcbSurfaceCreateInfoKHR::default() + .connection(window_os_handles.xcb_connection) + .window(window_os_handles.xcb_window); + + let xcb_surface = ash::extensions::khr::XcbSurface::new(&self.entry, &self.instance); + + let surface = unsafe { xcb_surface.create_xcb_surface(&xcb_surface_create_info, None).expect("No surface") }; + + let surface_capabilities = unsafe { self.surface.get_physical_device_surface_capabilities(self.physical_device, surface).expect("No surface capabilities") }; + + let surface_format = unsafe { self.surface.get_physical_device_surface_formats(self.physical_device, surface).expect("No surface formats") }; + + let surface_format: vk::SurfaceFormatKHR = surface_format + .iter() + .find(|format| { + format.format == vk::Format::B8G8R8A8_SRGB && format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR + }) + .expect("No surface format").to_owned(); + + let surface_present_modes = unsafe { self.surface.get_physical_device_surface_present_modes(self.physical_device, surface).expect("No surface present modes") }; + + let surface_present_mode: vk::PresentModeKHR = surface_present_modes + .iter() + .find(|present_mode| { + **present_mode == vk::PresentModeKHR::FIFO + }) + .expect("No surface present mode").to_owned(); + + let _surface_resolution = surface_capabilities.current_extent; + + crate::render_backend::Surface { + vulkan_surface: Surface { + surface, + surface_capabilities, + surface_format, + surface_present_mode, + }, + } + } + + fn create_swapchain(&self, surface: &crate::render_backend::Surface, _extent: crate::Extent, buffer_count: u32) -> crate::render_backend::Swapchain { + let surface_capabilities = unsafe { self.surface.get_physical_device_surface_capabilities(self.physical_device, surface.vulkan_surface.surface).expect("No surface capabilities") }; + + let swapchain_create_info = vk::SwapchainCreateInfoKHR::default() + .surface(unsafe { surface.vulkan_surface.surface }) + .min_image_count(buffer_count) + .image_color_space(vk::ColorSpaceKHR::SRGB_NONLINEAR) + .image_format(vk::Format::B8G8R8A8_SRGB) + .image_extent(surface_capabilities.current_extent) + .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT | vk::ImageUsageFlags::TRANSFER_DST) + .image_sharing_mode(vk::SharingMode::EXCLUSIVE) + .pre_transform(surface_capabilities.current_transform) + .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE) + .present_mode(unsafe { surface.vulkan_surface.surface_present_mode }) + .image_array_layers(1) + .clipped(true); + + let swapchain_loader = ash::extensions::khr::Swapchain::new(&self.instance, &self.device); + + let swapchain = unsafe { swapchain_loader.create_swapchain(&swapchain_create_info, None).expect("No swapchain") }; + + crate::render_backend::Swapchain { + vulkan_swapchain: Swapchain { + swapchain, + }, + } + } + + fn get_swapchain_images(&self, swapchain: &crate::render_backend::Swapchain) -> Vec { + let swapchain_images = unsafe { self.swapchain.get_swapchain_images(unsafe { swapchain.vulkan_swapchain.swapchain }).expect("No swapchain images") }; + + swapchain_images.iter().map(|a| crate::render_backend::Texture { + vulkan_texture: Texture { + image: *a, + }, + }).collect::>() + } + + fn begin_command_buffer_recording(&self, command_buffer: &crate::render_backend::CommandBuffer) { + let command_buffer_begin_info = vk::CommandBufferBeginInfo::default() + .flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT) + /* .build() */; + + unsafe { self.device.begin_command_buffer(command_buffer.vulkan_command_buffer.command_buffer, &command_buffer_begin_info).expect("No command buffer begin") }; + } + + fn end_command_buffer_recording(&self, command_buffer: &crate::render_backend::CommandBuffer) { + unsafe { self.device.end_command_buffer(command_buffer.vulkan_command_buffer.command_buffer).expect("No command buffer end") }; + } + + fn start_render_pass(&self, command_buffer: &crate::render_backend::CommandBuffer, extent: crate::Extent, attachments: &[crate::render_backend::AttachmentInformation]) { + let render_area = vk::Rect2D::default() + .offset(vk::Offset2D::default().x(0).y(0)/* .build() */) + .extent(vk::Extent2D::default().width(extent.width).height(extent.height)/* .build() */) + /* .build() */; + + let color_attchments = attachments.iter().map(|attachment| { + vk::RenderingAttachmentInfo::default() + .image_view(unsafe { attachment.texture_view.vulkan_texture_view.image_view }) + .image_layout(texture_format_and_resource_use_to_image_layout(attachment.format, attachment.resource_use, None)) + .load_op(to_load_operation(attachment.load)) + .store_op(to_store_operation(attachment.store)) + .clear_value(to_clear_value(attachment.clear.expect("No clear value"))) + /* .build() */ + }).collect::>(); + + let depth_attachment = attachments.iter().find(|attachment| attachment.format == render_backend::TextureFormats::Depth32).map(|attachment| { + vk::RenderingAttachmentInfo::default() + .image_view(unsafe { attachment.texture_view.vulkan_texture_view.image_view }) + .image_layout(texture_format_and_resource_use_to_image_layout(attachment.format, attachment.resource_use, None)) + .load_op(to_load_operation(attachment.load)) + .store_op(to_store_operation(attachment.store)) + .clear_value(to_clear_value(attachment.clear.expect("No clear value"))) + /* .build() */ + }).or(Some(vk::RenderingAttachmentInfo::default())).unwrap(); + + let rendering_info = vk::RenderingInfoKHR::default() + .color_attachments(color_attchments.as_slice()) + .depth_attachment(&depth_attachment) + .render_area(render_area) + .layer_count(1) + /* .build() */; + + let viewports = [ + vk::Viewport { + x: 0.0, + y: extent.height as f32, + width: extent.width as f32, + height: -(extent.height as f32), + min_depth: 0.0, + max_depth: 1.0, + } + ]; + + unsafe { self.dynamic_rendering.cmd_begin_rendering(command_buffer.vulkan_command_buffer.command_buffer, &rendering_info); } + unsafe { self.device.cmd_set_viewport(command_buffer.vulkan_command_buffer.command_buffer, 0, &viewports); } + unsafe { self.device.cmd_set_scissor(command_buffer.vulkan_command_buffer.command_buffer, 0, &[render_area]); } + } + + fn end_render_pass(&self, command_buffer: &crate::render_backend::CommandBuffer) { + unsafe { self.dynamic_rendering.cmd_end_rendering(command_buffer.vulkan_command_buffer.command_buffer); } + } + + fn bind_shader(&self, _command_buffer: &crate::render_backend::CommandBuffer, _shader: &crate::render_backend::Shader) { + panic!("Not implemented") + } + + fn bind_pipeline(&self, command_buffer: &crate::render_backend::CommandBuffer, pipeline: &crate::render_backend::Pipeline) { + unsafe { self.device.cmd_bind_pipeline(command_buffer.vulkan_command_buffer.command_buffer, vk::PipelineBindPoint::GRAPHICS, pipeline.vulkan_pipeline.pipeline); } + } + + fn write_to_push_constant(&self, command_buffer: &render_backend::CommandBuffer, pipeline_layout: &render_backend::PipelineLayout, offset: u32, data: &[u8]) { + unsafe { self.device.cmd_push_constants(command_buffer.vulkan_command_buffer.command_buffer, pipeline_layout.vulkan_pipeline_layout.pipeline_layout, vk::ShaderStageFlags::VERTEX, offset, data); } + } + + fn bind_descriptor_set(&self, command_buffer: &render_backend::CommandBuffer, pipeline_layout: &render_backend::PipelineLayout, descriptor_set: &render_backend::DescriptorSet, index: u32) { + unsafe { self.device.cmd_bind_descriptor_sets(command_buffer.vulkan_command_buffer.command_buffer, vk::PipelineBindPoint::GRAPHICS, pipeline_layout.vulkan_pipeline_layout.pipeline_layout, index, &[descriptor_set.vulkan_descriptor_set.descriptor_set], &[]); } + } + + fn bind_vertex_buffer(&self, command_buffer: &crate::render_backend::CommandBuffer, buffer: &crate::render_backend::Buffer) { + unsafe { self.device.cmd_bind_vertex_buffers(command_buffer.vulkan_command_buffer.command_buffer, 0, &[buffer.vulkan_buffer.buffer], &[0 as u64]); } + } + + fn bind_index_buffer(&self, command_buffer: &crate::render_backend::CommandBuffer, buffer: &crate::render_backend::Buffer) { + unsafe { self.device.cmd_bind_index_buffer(command_buffer.vulkan_command_buffer.command_buffer, buffer.vulkan_buffer.buffer, 0, vk::IndexType::UINT32); } + } + + fn draw_indexed(&self, command_buffer: &crate::render_backend::CommandBuffer, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32) { + unsafe { self.device.cmd_draw_indexed(command_buffer.vulkan_command_buffer.command_buffer, index_count, instance_count, first_index, vertex_offset, first_instance); } + } + + fn execute_barriers(&self, command_buffer: &crate::render_backend::CommandBuffer, barriers: &[crate::render_backend::BarrierDescriptor]) { + let mut image_memory_barriers = Vec::new(); + + for barrier in barriers { + match barrier.barrier { + // crate::render_backend::Barrier::BufferBarrier(buffer_barrier) => { + // let buffer_memory_barrier = vk::BufferMemoryBarrier2KHR::default() + // .src_stage_mask(to_pipeline_stage_flags(buffer_barrier.source_stage)) + // .dst_stage_mask(to_pipeline_stage_flags(buffer_barrier.destination_stage)) + // .src_access_mask(to_access_flags(buffer_barrier.source_access)) + // .dst_access_mask(to_access_flags(buffer_barrier.destination_access)) + // .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED) + // .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED) + // .buffer(unsafe { buffer_barrier.buffer.vulkan_buffer.buffer }) + // .offset(0) + // .size(vk::WHOLE_SIZE) + // /* .build() */; + + // unsafe { self.device.cmd_pipeline_barrier2(command_buffer.vulkan_command_buffer.command_buffer, &vk::DependencyInfo::default().buffer_memory_barriers(&[buffer_memory_barrier])) }; + // }, + crate::render_backend::Barrier::Texture(texture_barrier) => { + let image_memory_barrier = if let Some(source) = barrier.source { + vk::ImageMemoryBarrier2KHR::default() + .old_layout(texture_format_and_resource_use_to_image_layout(crate::render_backend::TextureFormats::RGBAu8, source.layout, Some(source.access))) + .src_stage_mask(to_pipeline_stage_flags(source.stage)) + .src_access_mask(to_access_flags(source.access, source.stage)) + } else { + vk::ImageMemoryBarrier2KHR::default() + .old_layout(vk::ImageLayout::UNDEFINED) + .src_stage_mask(vk::PipelineStageFlags2::empty()) + .src_access_mask(vk::AccessFlags2KHR::empty()) + } + .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED) + .new_layout(texture_format_and_resource_use_to_image_layout(crate::render_backend::TextureFormats::RGBAu8, barrier.destination.layout, Some(barrier.destination.access))) + .dst_stage_mask(to_pipeline_stage_flags(barrier.destination.stage)) + .dst_access_mask(to_access_flags(barrier.destination.access, barrier.destination.stage)) + .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED) + .image(unsafe { texture_barrier.vulkan_texture.image }) + .subresource_range(vk::ImageSubresourceRange { + aspect_mask: vk::ImageAspectFlags::COLOR, + base_mip_level: 0, + level_count: vk::REMAINING_MIP_LEVELS, + base_array_layer: 0, + layer_count: vk::REMAINING_ARRAY_LAYERS, + }) + /* .build() */; + + image_memory_barriers.push(image_memory_barrier); + }, + } + } + + let dependency_info = vk::DependencyInfo::default() + .image_memory_barriers(&image_memory_barriers) + .dependency_flags(vk::DependencyFlags::BY_REGION) + /* .build() */; + + unsafe { self.device.cmd_pipeline_barrier2(command_buffer.vulkan_command_buffer.command_buffer, &dependency_info) }; + } + + fn copy_textures(&self, command_buffer: &crate::render_backend::CommandBuffer, copies: &[crate::render_backend::TextureCopy]) { + let regions = copies.iter().map(|copy| { + vk::ImageCopy2::default() + .src_subresource(vk::ImageSubresourceLayers::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .mip_level(0) + .base_array_layer(0) + .layer_count(1) + /* .build() */ + ) + .src_offset(vk::Offset3D::default().x(0).y(0).z(0)/* .build() */) + .dst_subresource(vk::ImageSubresourceLayers::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .mip_level(0) + .base_array_layer(0) + .layer_count(1) + /* .build() */ + ) + .dst_offset(vk::Offset3D::default().x(0).y(0).z(0)/* .build() */) + .extent(vk::Extent3D::default().width(copy.extent.width).height(copy.extent.height).depth(1)/* .build() */) + /* .build() */ + }).collect::>(); + + for copy in copies { + let copy_image_info = vk::CopyImageInfo2::default() + .src_image(unsafe { copy.source.vulkan_texture.image }) + .src_image_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL) + .dst_image(unsafe { copy.destination.vulkan_texture.image }) + .dst_image_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL) + .regions(®ions) + /* .build() */; + + unsafe { self.device.cmd_copy_image2(command_buffer.vulkan_command_buffer.command_buffer, ©_image_info); } + } + } + + fn execute(&self, command_buffer: &crate::render_backend::CommandBuffer, wait_for: Option<&crate::render_backend::Synchronizer>, signal: &crate::render_backend::Synchronizer) { + let command_buffers = [unsafe { command_buffer.vulkan_command_buffer.command_buffer }]; + + let command_buffer_infos = [ + vk::CommandBufferSubmitInfo::default() + .command_buffer( + command_buffers[0] + ) + /* .build() */ + ]; + + let wait_semaphores = if let Some(wait_for) = wait_for { + vec![ + vk::SemaphoreSubmitInfo::default() + .semaphore(unsafe { wait_for.vulkan_synchronizer.semaphore }) + .stage_mask(vk::PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT) + /* .build() */ + ] + } else { + vec![] + }; + + let signal_semaphores = [ + vk::SemaphoreSubmitInfo::default() + .semaphore(unsafe { signal.vulkan_synchronizer.semaphore }) + /* .build() */ + ]; + + let submit_info = vk::SubmitInfo2::default() + .command_buffer_infos(&command_buffer_infos) + .wait_semaphore_infos(&wait_semaphores) + .signal_semaphore_infos(&signal_semaphores) + /* .build() */; + + unsafe { self.device.queue_submit2(self.queue, &[submit_info], signal.vulkan_synchronizer.fence); } + } + + fn acquire_swapchain_image(&self, swapchain: &crate::render_backend::Swapchain, image_available: &crate::render_backend::Synchronizer) -> (u32, render_backend::SwapchainStates) { + let acquisition_result = unsafe { self.swapchain.acquire_next_image(swapchain.vulkan_swapchain.swapchain, u64::MAX, image_available.vulkan_synchronizer.semaphore, vk::Fence::null()) }; + + if let Ok((index, state)) = acquisition_result { + if !state { + (index, render_backend::SwapchainStates::Ok) + } else { + (index, render_backend::SwapchainStates::Suboptimal) + } + } else { + (0, render_backend::SwapchainStates::Invalid) + } + } + + fn present(&self, swapchain: &crate::render_backend::Swapchain, wait_for: &crate::render_backend::Synchronizer, image_index: u32) { + let swapchains = [unsafe { swapchain.vulkan_swapchain.swapchain }]; + let wait_semaphores = [unsafe { wait_for.vulkan_synchronizer.semaphore }]; + let image_indices = [image_index]; + + let present_info = vk::PresentInfoKHR::default() + .swapchains(&swapchains) + .wait_semaphores(&wait_semaphores) + .image_indices(&image_indices); + + unsafe { self.swapchain.queue_present(self.queue, &present_info); } + } + + fn wait(&self, synchronizer: &crate::render_backend::Synchronizer) { + unsafe { self.device.wait_for_fences(&[synchronizer.vulkan_synchronizer.fence], true, u64::MAX).expect("No fence wait"); } + unsafe { self.device.reset_fences(&[synchronizer.vulkan_synchronizer.fence]).expect("No fence reset"); } + } +} \ No newline at end of file diff --git a/src/window_system.rs b/src/window_system.rs new file mode 100644 index 00000000..fd4c5638 --- /dev/null +++ b/src/window_system.rs @@ -0,0 +1,607 @@ +//! The window system module implements logic to handle creation and management of OS windows. + +use std::ffi::c_void; + +use xcb::{Xid, x}; + +use crate::{Extent, orchestrator::System}; + +#[derive(Debug, Clone, Copy)] +enum Keys { + A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + + Num0, + Num1, + Num2, + Num3, + Num4, + Num5, + Num6, + Num7, + Num8, + Num9, + + NumPad0, + NumPad1, + NumPad2, + NumPad3, + NumPad4, + NumPad5, + NumPad6, + NumPad7, + NumPad8, + NumPad9, + + NumPadAdd, + NumPadSubtract, + NumPadMultiply, + NumPadDivide, + NumPadDecimal, + NumPadEnter, + + Backspace, + Tab, + Enter, + ShiftLeft, + ShiftRight, + ControlLeft, + ControlRight, + AltLeft, + AltRight, + Menu, + Space, + Insert, + Delete, + Home, + End, + PageUp, + PageDown, + ArrowUp, + ArrowDown, + ArrowLeft, + ArrowRight, + + Escape, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + + NumLock, + ScrollLock, + CapsLock, + PrintScreen, + Pause, + Help, + SysReq, + Compose, + AltGr, + Stop, + Again, + Undo, + Cut, + Copy, + Paste, + Find, + Mute, + VolumeUp, + VolumeDown, + NumPadComma, + NumPadEquals, + NumPadParenLeft, + NumPadParenRight, + NumPadBackspace, + NumPadMemoryStore, + NumPadMemoryRecall, + NumPadMemoryClear, +} + +#[derive(Debug, Clone, Copy)] +enum MouseKeys { + Left, + Middle, + Right, + ScrollUp, + ScrollDown, +} + +#[derive(Debug, Clone, Copy)] +enum WindowEvents { + Resize, + Minimize, + Maximize, + Close, + Key { + pressed: bool, + key: Keys, + }, + Button { + pressed: bool, + button: MouseKeys, + } +} + +impl TryFrom for Keys { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0x26 => Ok(Keys::A), 0x38 => Ok(Keys::B), 0x36 => Ok(Keys::C), 0x28 => Ok(Keys::D), 0x1a => Ok(Keys::E), 0x29 => Ok(Keys::F), + 0x2a => Ok(Keys::G), 0x2b => Ok(Keys::H), 0x1f => Ok(Keys::I), 0x2c => Ok(Keys::J), 0x2d => Ok(Keys::K), 0x2e => Ok(Keys::L), + 0x3a => Ok(Keys::M), 0x39 => Ok(Keys::N), 0x20 => Ok(Keys::O), 0x21 => Ok(Keys::P), 24 => Ok(Keys::Q), 0x1b => Ok(Keys::R), + 0x27 => Ok(Keys::S), 28 => Ok(Keys::T), 30 => Ok(Keys::U), 0x37 => Ok(Keys::V), 25 => Ok(Keys::W), 0x35 => Ok(Keys::X), + 0x1d => Ok(Keys::Y), 0x34 => Ok(Keys::Z), + + 90 => Ok(Keys::NumPad0), 87 => Ok(Keys::NumPad1), 88 => Ok(Keys::NumPad2), 89 => Ok(Keys::NumPad3), 0x53 => Ok(Keys::NumPad4), + 0x54 => Ok(Keys::NumPad5), 0x55 => Ok(Keys::NumPad6), 79 => Ok(Keys::NumPad7), 80 => Ok(Keys::NumPad8), 81 => Ok(Keys::NumPad9), + + 113 => Ok(Keys::ArrowLeft), 116 => Ok(Keys::ArrowDown), 114 => Ok(Keys::ArrowRight), 111 => Ok(Keys::ArrowUp), + + 9 => Ok(Keys::Escape), 23 => Ok(Keys::Tab), 50 => Ok(Keys::ShiftLeft), 37 => Ok(Keys::ControlLeft), 64 => Ok(Keys::AltLeft), + 65 => Ok(Keys::Space), 108 => Ok(Keys::AltGr), 105 => Ok(Keys::ControlRight), 62 => Ok(Keys::ShiftRight), 36 => Ok(Keys::Enter), + 22 => Ok(Keys::Backspace), + + _ => Err(()), + } + } +} + +impl TryFrom for MouseKeys { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 1 => Ok(MouseKeys::Left), + 2 => Ok(MouseKeys::Middle), + 3 => Ok(MouseKeys::Right), + 4 => Ok(MouseKeys::ScrollUp), + 5 => Ok(MouseKeys::ScrollDown), + _ => Err(()), + } + } +} + +struct Window { + connection: xcb::Connection, + window: xcb::x::Window, + wm_del_window: xcb::x::Atom, +} + +struct WindowIterator<'a> { + connection: &'a xcb::Connection, + wm_del_window: xcb::x::Atom, +} + +impl Iterator for WindowIterator<'_> { + type Item = WindowEvents; + + fn next(&mut self) -> Option { + let connection = &self.connection; + + loop { + let event = connection.poll_for_event(); + + let event = if let Ok(event) = event { + event + } else { + return None; + }; + + let event = if let Some(event) = event { + event + } else { + return None; + }; + + let ev = match event { + xcb::Event::X(x::Event::KeyPress(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + Some(WindowEvents::Key { pressed: true, key }) + } else { + None + } + }, + xcb::Event::X(x::Event::KeyRelease(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + println!("release {:?}", key); + Some(WindowEvents::Key { pressed: false, key }) + } else { + None + } + }, + xcb::Event::X(x::Event::ButtonPress(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + Some(WindowEvents::Button { pressed: true, button: key }) + } else { + None + } + }, + xcb::Event::X(x::Event::ButtonRelease(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + Some(WindowEvents::Button { pressed: false, button: key }) + } else { + None + } + }, + xcb::Event::X(x::Event::ClientMessage(ev)) => { + // We have received a message from the server + if let x::ClientMessageData::Data32([atom, ..]) = ev.data() { + if atom == self.wm_del_window.resource_id() { + let event = WindowEvents::Close; + println!("Window event: {:?}", event); + Some(event) + } else { + None + } + } else { + None + } + }, + _ => { None } + }; + + if let Some(ev) = ev { + return Some(ev); + } else { + continue; + } + } + } +} + +impl Window { + pub fn new_with_params(name: &str, extent: Extent, id_name: &str) -> Option { + let (connection, screen_index) = xcb::Connection::connect(None).unwrap(); + + let setup = connection.get_setup(); + let screen = setup.roots().nth(screen_index as usize).unwrap(); + + let window: xcb::x::Window = connection.generate_id(); + + // We can now create a window. For this we pass a `Request` + // object to the `send_request_checked` method. The method + // returns a cookie that will be used to check for success. + let cookie = connection.send_request_checked(&xcb::x::CreateWindow { + depth: xcb::x::COPY_FROM_PARENT as u8, + wid: window, + parent: screen.root(), + x: 0, + y: 0, + width: extent.width as u16, height: extent.height as u16, + border_width: 0, + class: xcb::x::WindowClass::InputOutput, + visual: screen.root_visual(), + // this list must be in same order than `Cw` enum order + value_list: &[ + xcb::x::Cw::BackPixel(screen.black_pixel()), + xcb::x::Cw::EventMask(xcb::x::EventMask::EXPOSURE | xcb::x::EventMask::BUTTON_PRESS | xcb::x::EventMask::BUTTON_RELEASE | xcb::x::EventMask::POINTER_MOTION | xcb::x::EventMask::ENTER_WINDOW | xcb::x::EventMask::LEAVE_WINDOW | xcb::x::EventMask::KEY_PRESS | xcb::x::EventMask::KEY_RELEASE | xcb::x::EventMask::RESIZE_REDIRECT | xcb::x::EventMask::STRUCTURE_NOTIFY), + ], + }); + + if let Err(_) = connection.check_request(cookie) { + return None; + } + + // Let's change the window title + let cookie = connection.send_request_checked(&xcb::x::ChangeProperty { + mode: xcb::x::PropMode::Replace, + window, + property: xcb::x::ATOM_WM_NAME, + r#type: xcb::x::ATOM_STRING, + data: name.as_bytes(), + }); + + if let Err(_) = connection.check_request(cookie) { + return None; + } + + // We need a few atoms for our application. + // We send a few requests in a row and wait for the replies after. + let (wm_protocols, wm_del_window, _wm_state, _wm_state_maxv, _wm_state_maxh) = { + let cookies = ( + connection.send_request(&xcb::x::InternAtom { + only_if_exists: true, + name: b"WM_PROTOCOLS", + }), + connection.send_request(&xcb::x::InternAtom { + only_if_exists: true, + name: b"WM_DELETE_WINDOW", + }), + connection.send_request(&xcb::x::InternAtom { + only_if_exists: true, + name: b"_NET_WM_STATE", + }), + connection.send_request(&xcb::x::InternAtom { + only_if_exists: true, + name: b"_NET_WM_STATE_MAXIMIZED_VERT", + }), + connection.send_request(&xcb::x::InternAtom { + only_if_exists: true, + name: b"_NET_WM_STATE_MAXIMIZED_HORZ", + }), + ); + ( + connection.wait_for_reply(cookies.0).unwrap().atom(), + connection.wait_for_reply(cookies.1).unwrap().atom(), + connection.wait_for_reply(cookies.2).unwrap().atom(), + connection.wait_for_reply(cookies.3).unwrap().atom(), + connection.wait_for_reply(cookies.4).unwrap().atom(), + ) + }; + + // We now activate the window close event by sending the following request. + // If we don't do this we can still close the window by clicking on the "x" button, + // but the event loop is notified through a connection shutdown error. + let cookie = connection.send_request_checked(&xcb::x::ChangeProperty { + mode: xcb::x::PropMode::Replace, + window, + property: wm_protocols, + r#type: xcb::x::ATOM_ATOM, + data: &[wm_del_window], + }); + + if let Err(_) = connection.check_request(cookie) { + return None; + } + + // We now show ("map" in X terminology) the window. + // This time we do not check for success, so we discard the cookie. + connection.send_request(&xcb::x::MapWindow { window, }); + + // Previous request was checked, so a flush is not necessary in this case. + // Otherwise, here is how to perform a connection flush. + let flush_result = connection.flush(); + + if let Err(_) = flush_result { + return None; + } + + Some(Window { + connection, + window, + wm_del_window, + }) + } + + pub fn poll(&self) -> WindowIterator { + WindowIterator { + connection: &self.connection, + wm_del_window: self.wm_del_window, + } + } + + pub fn update(&self) -> Option { + let connection = &self.connection; + + loop { + let event = connection.poll_for_event(); + + let event = if let Ok(event) = event { + event + } else { + return None; + }; + + let event = if let Some(event) = event { + event + } else { + return None; + }; + + let ev = match event { + xcb::Event::X(x::Event::KeyPress(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + Some(WindowEvents::Key { pressed: true, key }) + } else { + None + } + }, + xcb::Event::X(x::Event::KeyRelease(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + println!("release {:?}", key); + Some(WindowEvents::Key { pressed: false, key }) + } else { + None + } + }, + xcb::Event::X(x::Event::ButtonPress(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + Some(WindowEvents::Button { pressed: true, button: key }) + } else { + None + } + }, + xcb::Event::X(x::Event::ButtonRelease(ev)) => { + let key: Result = ev.detail().try_into(); + + if let Ok(key) = key { + Some(WindowEvents::Button { pressed: false, button: key }) + } else { + None + } + }, + xcb::Event::X(x::Event::ClientMessage(ev)) => { + // We have received a message from the server + if let x::ClientMessageData::Data32([atom, ..]) = ev.data() { + if atom == self.wm_del_window.resource_id() { + let event = WindowEvents::Close; + println!("Window event: {:?}", event); + Some(event) + } else { + None + } + } else { + None + } + }, + _ => { None } + }; + + if let Some(ev) = ev { + return Some(ev); + } else { + continue; + } + } + } +} + +pub struct WindowSystem { + windows: Vec, +} + +impl System for WindowSystem { + fn as_any(&self) -> &dyn std::any::Any { self } +} + +pub struct WindowHandle(u64); + +/// The operating system handles for a window. +pub struct WindowOsHandles { + #[cfg(target_os = "linux")] + /// The XCB connection. + pub xcb_connection: *mut c_void, + #[cfg(target_os = "linux")] + /// The XCB window. + pub xcb_window: u32, +} + +impl WindowSystem { + /// Creates a new window system. + pub fn new() -> WindowSystem { + WindowSystem { windows: Vec::new() } + } + + pub fn update(&mut self) -> bool { + for window in &self.windows { + for event in window.poll() { + println!("event {:?}", event); + + match event { + WindowEvents::Close => { + return false; + }, + _ => { return true; } + } + } + } + + return true; + } + + /// Creates a new OS window. + /// + /// # Arguments + /// - `name` - The name of the window. + /// - `extent` - The size of the window. + /// - `id_name` - The name of the window for identification purposes. + pub fn create_window(&mut self, name: &str, extent: Extent, id_name: &str) -> WindowHandle { + let window = Window::new_with_params(name, extent, id_name); + + if let Some(window) = window { + let window_handle = WindowHandle(self.windows.len() as u64); + self.windows.push(window); + window_handle + } else { + panic!("Failed to create window") + } + } + + /// Gets the OS handles for a window. + /// + /// # Arguments + /// - `window_handle` - The handle of the window to get the OS handles for. + /// + /// # Returns + /// The operationg system handles for the window. + pub fn get_os_handles(&self, window_handle: WindowHandle,) -> WindowOsHandles { + if window_handle.0 > self.windows.len() as u64 { return WindowOsHandles{ xcb_connection: std::ptr::null_mut(), xcb_window: 0 }; } + + let window = &self.windows[window_handle.0 as usize]; + + let connection = window.connection.get_raw_conn() as *mut std::ffi::c_void; + + let window = window.window.to_owned().resource_id(); + + return WindowOsHandles{ xcb_connection: connection, xcb_window: window }; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn create_window() { + let mut window_system = WindowSystem::new(); + + let window_handle = window_system.create_window("Main Window", Extent { width: 1920, height: 1080, depth: 1 }, "main_window"); + + let os_handles = window_system.get_os_handles(window_handle); + + assert_ne!(os_handles.xcb_connection, std::ptr::null_mut()); + assert_ne!(os_handles.xcb_window, 0); + } + + #[test] + fn test_window_loop() { + let mut window_system = WindowSystem::new(); + + let window_handle = window_system.create_window("Main Window", Extent { width: 1920, height: 1080, depth: 1 }, "main_window"); + + loop { + if window_system.update() == false { + break; + } + + std::thread::sleep(std::time::Duration::from_millis(16)); + } + } +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index 248056e8..00000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -include(FetchContent) - -FetchContent_Declare(googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.11.0 -) - -FetchContent_MakeAvailable(googletest) -add_library(GTest::GTest INTERFACE IMPORTED) -target_link_libraries(GTest::GTest INTERFACE gtest_main) - -add_executable(TestApplication TestApplication.cpp) - -target_link_libraries(TestApplication PRIVATE GTest::GTest Application) - -add_test(Application_gtests TestApplication) \ No newline at end of file diff --git a/tests/TestApplication.cpp b/tests/TestApplication.cpp deleted file mode 100644 index bc97d175..00000000 --- a/tests/TestApplication.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include - -class TestApplication : public BE::Application { -public: - TestApplication() : BE::Application(u8"Test Application") { - } - - ~TestApplication() {} - - bool initialize() override { - BE::Application::initialize(); - return true; - } - - void shutdown() override { - BE::Application::shutdown(); - } - - virtual GTSL::ShortString<128> GetApplicationName() { - return u8"Test Application"; - } -}; - -int CreateApplication(GTSL::Range arguments) { -//int CreateApplication() { - auto application = TestApplication(); - - int exitCode = -1; - - if (application.base_initialize(arguments)) //call BE::Application initialize, which does basic universal startup - { - if (application.initialize()) //call BE::Application virtual initialize which will call the chain of initialize's - { - } - } - - application.shutdown(); - - return exitCode; //Return and exit. -} \ No newline at end of file