From bb5b48698a1407a117324f2957ba4cca3e21ce4e Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Tue, 5 May 2020 01:51:13 +0200 Subject: [PATCH] Adding nlohmanns json library --- .gitmodules | 3 + .vscode/settings.json | 8 +- CMakeLists.txt | 12 +- CMakeSettings.json | 2 +- cmake/SuperBuild.cmake | 47 +- external/json | 1 + src/Engine/Asset/Asset.cpp | 11 + src/Engine/Asset/Asset.h | 15 + src/Engine/Asset/CMakeLists.txt | 6 + src/Engine/Asset/FileAsset.cpp | 62 ++ src/Engine/Asset/FileAsset.h | 24 + src/Engine/CMakeLists.txt | 5 +- src/Engine/Containers/Array.h | 6 +- src/Engine/EngineTypes.h | 18 +- src/Engine/Graphics/CMakeLists.txt | 1 + src/Engine/Graphics/ForwardPlusRenderPath.cpp | 23 +- src/Engine/Graphics/ForwardPlusRenderPath.h | 7 +- src/Engine/Graphics/Graphics.h | 9 +- src/Engine/Graphics/GraphicsEnums.h | 7 + src/Engine/Graphics/GraphicsInitializer.h | 188 ++++++ src/Engine/Graphics/GraphicsResources.cpp | 63 ++ src/Engine/Graphics/GraphicsResources.h | 267 +++++---- src/Engine/Graphics/Mesh.cpp | 2 +- src/Engine/Graphics/Mesh.h | 3 +- src/Engine/Graphics/RenderCore.cpp | 9 +- src/Engine/Graphics/RenderCore.h | 2 + src/Engine/Graphics/RenderPath.cpp | 6 +- src/Engine/Graphics/RenderPath.h | 3 +- src/Engine/Graphics/SceneRenderPath.cpp | 2 + src/Engine/Graphics/SceneRenderPath.h | 4 + src/Engine/Graphics/SceneView.cpp | 3 +- src/Engine/Graphics/SceneView.h | 3 +- src/Engine/Graphics/View.cpp | 7 +- src/Engine/Graphics/View.h | 4 +- src/Engine/Graphics/Vulkan/CMakeLists.txt | 6 + .../Graphics/Vulkan/VulkanAllocator.cpp | 99 ++-- src/Engine/Graphics/Vulkan/VulkanBuffer.cpp | 28 +- .../Graphics/Vulkan/VulkanCommandBuffer.cpp | 38 +- .../Graphics/Vulkan/VulkanCommandBuffer.h | 12 +- .../Graphics/Vulkan/VulkanDescriptorSets.h | 49 +- .../Graphics/Vulkan/VulkanFramebuffer.cpp | 4 +- .../Graphics/Vulkan/VulkanFramebuffer.h | 1 + src/Engine/Graphics/Vulkan/VulkanGraphics.cpp | 36 +- src/Engine/Graphics/Vulkan/VulkanGraphics.h | 16 +- .../Graphics/Vulkan/VulkanGraphicsEnums.cpp | 163 +++++ .../Graphics/Vulkan/VulkanGraphicsEnums.h | 19 + .../Vulkan/VulkanGraphicsResources.cpp | 43 ++ .../Graphics/Vulkan/VulkanGraphicsResources.h | 35 +- src/Engine/Graphics/Vulkan/VulkanPipeline.cpp | 28 + src/Engine/Graphics/Vulkan/VulkanPipeline.h | 24 + .../Graphics/Vulkan/VulkanPipelineCache.cpp | 240 ++++++++ .../Graphics/Vulkan/VulkanPipelineCache.h | 21 + src/Engine/Graphics/Vulkan/VulkanQueue.cpp | 17 +- .../Graphics/Vulkan/VulkanRenderPass.cpp | 11 +- src/Engine/Graphics/Vulkan/VulkanRenderPass.h | 5 - src/Engine/Graphics/Vulkan/VulkanShader.cpp | 4 + src/Engine/Graphics/Vulkan/VulkanShader.h | 57 ++ src/Engine/Graphics/Vulkan/VulkanTexture.cpp | 13 +- src/Engine/Graphics/Vulkan/VulkanViewport.cpp | 42 +- src/Engine/Graphics/Window.cpp | 7 +- src/Engine/Graphics/Window.h | 3 +- src/Engine/Graphics/WindowManager.cpp | 6 +- src/Engine/Graphics/WindowManager.h | 9 +- src/Engine/Material/CMakeLists.txt | 6 + src/Engine/Material/Material.cpp | 37 ++ src/Engine/Material/Material.h | 44 ++ src/Engine/Material/MaterialInstance.cpp | 32 + src/Engine/Material/MaterialInstance.h | 21 + src/Engine/Math/Math.h | 23 + src/Engine/Math/Transform.cpp | 117 +++- src/Engine/Math/Transform.h | 24 +- src/Engine/Math/Vector.h | 18 +- src/Engine/MinimalEngine.cpp | 2 +- src/Engine/MinimalEngine.h | 556 +++++++++--------- src/Engine/Scene/Actor/Actor.cpp | 35 +- src/Engine/Scene/Actor/Actor.h | 19 +- src/Engine/Scene/Components/Component.cpp | 130 +++- src/Engine/Scene/Components/Component.h | 21 +- .../Scene/Components/PrimitiveComponent.cpp | 23 + .../Scene/Components/PrimitiveComponent.h | 15 +- src/Engine/Scene/Scene.cpp | 61 ++ src/Engine/Scene/Scene.h | 16 +- test.mat | 3 + 83 files changed, 2426 insertions(+), 646 deletions(-) create mode 160000 external/json create mode 100644 src/Engine/Asset/Asset.cpp create mode 100644 src/Engine/Asset/Asset.h create mode 100644 src/Engine/Asset/CMakeLists.txt create mode 100644 src/Engine/Asset/FileAsset.cpp create mode 100644 src/Engine/Asset/FileAsset.h create mode 100644 src/Engine/Graphics/GraphicsInitializer.h create mode 100644 src/Engine/Graphics/Vulkan/VulkanPipeline.cpp create mode 100644 src/Engine/Graphics/Vulkan/VulkanPipeline.h create mode 100644 src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp create mode 100644 src/Engine/Graphics/Vulkan/VulkanPipelineCache.h create mode 100644 src/Engine/Graphics/Vulkan/VulkanShader.cpp create mode 100644 src/Engine/Graphics/Vulkan/VulkanShader.h create mode 100644 src/Engine/Material/CMakeLists.txt create mode 100644 src/Engine/Material/Material.cpp create mode 100644 src/Engine/Material/Material.h create mode 100644 src/Engine/Material/MaterialInstance.cpp create mode 100644 src/Engine/Material/MaterialInstance.h create mode 100644 test.mat diff --git a/.gitmodules b/.gitmodules index ec0e8b9..c9c9f25 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "external/slang"] path = external/slang url = https://github.com/shader-slang/slang.git +[submodule "external/json"] + path = external/json + url = https://github.com/nlohmann/json.git diff --git a/.vscode/settings.json b/.vscode/settings.json index 1670fdc..23a7428 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,6 +14,12 @@ "type_traits": "cpp", "vector": "cpp", "*.rh": "cpp", - "memory": "cpp" + "memory": "cpp", + "*.ipp": "cpp", + "iostream": "cpp", + "initializer_list": "cpp" }, + "C_Cpp.default.browse.limitSymbolsToIncludedHeaders": false, + "C_Cpp.default.intelliSenseMode": "msvc-x64", + "C_Cpp.errorSquiggles": "Disabled", } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f4c992..3cba8ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.15) -set(CMAKE_CXX_STANDARD_REQUIRED 17) +set(CMAKE_CXX_STANDARD_REQUIRED 20) # Handle superbuild first option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON) @@ -11,6 +11,7 @@ set(SLANG_ROOT ${EXTERNAL_ROOT}/slang) set(BOOST_ROOT ${EXTERNAL_ROOT}/boost) set(GLM_ROOT ${EXTERNAL_ROOT}/glm) set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw) +set(JSON_ROOT ${EXTERNAL_ROOT}/json) set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}) set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) @@ -34,9 +35,11 @@ else() project (Seele) endif() -add_subdirectory(${GLFW_ROOT}) find_package(Vulkan REQUIRED) find_package(Boost REQUIRED COMPONENTS serialization) +find_package(Threads) +include(${JSON_IMPORT}) +include(${GLFW_IMPORT}) include_directories(${GLFW_ROOT}/include) include_directories(${GLM_INCLUDE_DIRS}) @@ -52,11 +55,12 @@ if(WIN32) add_compile_definitions(USE_EXTENSIONS) endif() add_executable(SeeleEngine "") -add_subdirectory(src/) +target_link_libraries(SeeleEngine glfw) +target_link_libraries(SeeleEngine nlohmann_json::nlohmann_json) target_link_libraries(SeeleEngine ${Boost_LIBRARIES}) target_link_libraries(SeeleEngine ${Vulkan_LIBRARY}) -target_link_libraries(SeeleEngine glfw ${GLFW_LIBRARIES}) target_link_libraries(SeeleEngine ${SLANG_LIBRARY}) +add_subdirectory(src/) if(MSVC) target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi /W4) diff --git a/CMakeSettings.json b/CMakeSettings.json index 49da498..00a8e6e 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -7,7 +7,7 @@ "inheritEnvironments": [ "msvc_x64_x64" ], "buildRoot": "${projectDir}\\bin\\${name}", "installRoot": "${projectDir}\\install\\${name}", - "cmakeCommandArgs": "", + "cmakeCommandArgs": "-DUSE_SUPERBUILD=TRUE", "buildCommandArgs": "-v", "ctestCommandArgs": "", "variables": [] diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index fb5967e..8faf438 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -18,7 +18,7 @@ ExternalProject_Add(boost SOURCE_DIR ${BOOST_ROOT} UPDATE_COMMAND "" CONFIGURE_COMMAND ./bootstrap.${BOOTSTRAP_EXTENSION} --with-libraries=serialization,test - BUILD_COMMAND ./b2 link=static + BUILD_COMMAND ./b2 link=static -d0 BUILD_IN_SOURCE 1 INSTALL_COMMAND "") @@ -37,23 +37,36 @@ list(APPEND EXTRA_CMAKE_ARGS -DGLM_INCLUDE_DIRS=${GLM_ROOT} ) +#--------------------JSON------------------ +#list(APPEND DEPENDENCIES nlohmann_json) +set(JSON_MultipleHeaders ON CACHE INTERNAL "") +set(JSON_BuildTests OFF CACHE INTERNAL "") +set(JSON_Install OFF CACHE INTERNAL "") + +add_subdirectory(${JSON_ROOT}) +export(TARGETS nlohmann_json + NAMESPACE nlohmann_json:: + FILE ${nlohmann_json_BINARY_DIR}/json_target.cmake) + +list(APPEND EXTRA_CMAKE_ARGS + -DJSON_IMPORT=${nlohmann_json_BINARY_DIR}/json_target.cmake + ) + #--------------GLFW------------------------------ -#list(APPEND DEPENDENCIES glfw) -#set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) -#set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) -#set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) -# -#ExternalProject_Add(glfw -# SOURCE_DIR ${GLFW_ROOT} -# BINARY_DIR ${CMAKE_BINARY_DIR}/lib -# INSTALL_COMMAND "") -# -#list(APPEND EXTRA_CMAKE_ARGS -# -DGLFW_INCLUDE_DIRS=${GLFW_ROOT}/include -# -DGLFW_LIBRARY=${CMAKE_BINARY_DIR}/lib/src/glfw3.lib -# ) -# +list(APPEND DEPENDENCIES glfw) +set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + +add_subdirectory(${GLFW_ROOT}) +export(TARGETS glfw + FILE ${GLFW_BINARY_DIR}/glfw.cmake) + +list(APPEND EXTRA_CMAKE_ARGS + -DGLFW_IMPORT=${GLFW_BINARY_DIR}/glfw.cmake + ) + #--------------SLang------------------------------ list(APPEND DEPENDENCIES slang) string(TOLOWER ${CMAKE_BUILD_TYPE}_${CMAKE_PLATFORM} SLANG_CONFIG) @@ -83,7 +96,7 @@ endif() list(APPEND EXTRA_CMAKE_ARGS - -DSLANG_INCLUDE_DIRS=${EXTERNAL_ROOT} + -DSLANG_INCLUDE_DIRS=${EXTERNAL_ROOT}/slang -DSLANG_LIBRARY=${SLANG_LIB_PATH}) list(APPEND DEPENDENT_BINARIES ${SLANG_ROOT}/${SLANG_BINARY}) diff --git a/external/json b/external/json new file mode 160000 index 0000000..634fa87 --- /dev/null +++ b/external/json @@ -0,0 +1 @@ +Subproject commit 634fa87e5a6a438089954a46ddec948bf6b5e69e diff --git a/src/Engine/Asset/Asset.cpp b/src/Engine/Asset/Asset.cpp new file mode 100644 index 0000000..36a4537 --- /dev/null +++ b/src/Engine/Asset/Asset.cpp @@ -0,0 +1,11 @@ +#include "Asset.h" + +using namespace Seele; + +Asset::Asset() +{ +} + +Asset::~Asset() +{ +} \ No newline at end of file diff --git a/src/Engine/Asset/Asset.h b/src/Engine/Asset/Asset.h new file mode 100644 index 0000000..6139c30 --- /dev/null +++ b/src/Engine/Asset/Asset.h @@ -0,0 +1,15 @@ +#pragma once +#include "MinimalEngine.h" + +namespace Seele +{ +class Asset +{ +public: + Asset(); + virtual ~Asset(); + +private: +}; +DEFINE_REF(Asset); +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Asset/CMakeLists.txt b/src/Engine/Asset/CMakeLists.txt new file mode 100644 index 0000000..b6522dc --- /dev/null +++ b/src/Engine/Asset/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(SeeleEngine + PRIVATE + Asset.h + Asset.cpp + FileAsset.h + FileAsset.cpp) \ No newline at end of file diff --git a/src/Engine/Asset/FileAsset.cpp b/src/Engine/Asset/FileAsset.cpp new file mode 100644 index 0000000..ae0c58c --- /dev/null +++ b/src/Engine/Asset/FileAsset.cpp @@ -0,0 +1,62 @@ +#include "FileAsset.h" + +using namespace Seele; + +FileAsset::FileAsset() + : path("") + , name("") +{ +} + +FileAsset::FileAsset(const std::string &fullPath) + : path(fullPath) +{ + name = fullPath.substr(fullPath.find_last_of('\\')+1); +} + +FileAsset::FileAsset(const std::string &directory, const std::string &name) + : path(directory+name) + , name(name) +{ +} + +FileAsset::~FileAsset() +{ +} + +std::ifstream &FileAsset::getReadStream() +{ + if(inStream.is_open()) + { + return inStream; + } + inStream.open(path); + return inStream; +} + +std::ofstream &FileAsset::getWriteStream() +{ + if(outStream.is_open()) + { + return outStream; + } + outStream.open(path); + return outStream; +} + +void FileAsset::rename(const std::string& newName) +{ + if(inStream.is_open()) + { + inStream.close(); + } + if(outStream.is_open()) + { + outStream.flush(); + outStream.close(); + } + path.replace(path.find_last_of(name), name.size(), newName); + name = newName; + inStream.open(path); + outStream.open(path); +} \ No newline at end of file diff --git a/src/Engine/Asset/FileAsset.h b/src/Engine/Asset/FileAsset.h new file mode 100644 index 0000000..3dc96fe --- /dev/null +++ b/src/Engine/Asset/FileAsset.h @@ -0,0 +1,24 @@ +#pragma once +#include "Asset.h" +#include + +namespace Seele +{ +class FileAsset +{ +public: + FileAsset(); + FileAsset(const std::string& directory, const std::string& name); + FileAsset(const std::string& fullPath); + virtual ~FileAsset(); + std::ifstream& getReadStream(); + std::ofstream& getWriteStream(); + void rename(const std::string& newName); +private: + std::string name; + std::string path; + uint32 byteSize; + std::ifstream inStream; + std::ofstream outStream; +}; +} \ No newline at end of file diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index c04161c..a542c96 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -4,6 +4,9 @@ target_sources(SeeleEngine MinimalEngine.cpp main.cpp) +add_subdirectory(Asset/) +add_subdirectory(Containers/) add_subdirectory(Graphics/) +add_subdirectory(Material/) add_subdirectory(Math/) -add_subdirectory(Containers/) \ No newline at end of file +add_subdirectory(Scene/) \ No newline at end of file diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 1c3073f..9d9e327 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -372,7 +372,11 @@ public: { return N; } - inline T *data() const + inline T *data() + { + return _data; + } + inline const T* data() const { return _data; } diff --git a/src/Engine/EngineTypes.h b/src/Engine/EngineTypes.h index 2392704..18e72fe 100644 --- a/src/Engine/EngineTypes.h +++ b/src/Engine/EngineTypes.h @@ -2,13 +2,13 @@ namespace Seele { - typedef uint64_t uint64; - typedef uint32_t uint32; - typedef uint16_t uint16; - typedef uint8_t uint8; +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; - typedef int64_t int64; - typedef int32_t int32; - typedef int16_t int16; - typedef int8_t int8; -} \ No newline at end of file +typedef int64_t int64; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/CMakeLists.txt b/src/Engine/Graphics/CMakeLists.txt index edfd04d..ae599af 100644 --- a/src/Engine/Graphics/CMakeLists.txt +++ b/src/Engine/Graphics/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(SeeleEngine ForwardPlusRenderPath.cpp GraphicsResources.h GraphicsResources.cpp + GraphicsInitializer.h GraphicsEnums.h Graphics.h Graphics.cpp diff --git a/src/Engine/Graphics/ForwardPlusRenderPath.cpp b/src/Engine/Graphics/ForwardPlusRenderPath.cpp index 020dc1a..39267f0 100644 --- a/src/Engine/Graphics/ForwardPlusRenderPath.cpp +++ b/src/Engine/Graphics/ForwardPlusRenderPath.cpp @@ -1,15 +1,21 @@ #include "ForwardPlusRenderPath.h" +#include "Scene/Scene.h" +#include "Material/MaterialInstance.h" +#include "Material/Material.h" +#include "GraphicsResources.h" using namespace Seele; Seele::ForwardPlusRenderPath::ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport viewport) : SceneRenderPath(graphics, viewport) { - + PMaterial material = new Material("D:\\Private\\Programming\\C++\\Seele\\test.mat"); + material->compile(); } Seele::ForwardPlusRenderPath::~ForwardPlusRenderPath() -{} +{ +} void Seele::ForwardPlusRenderPath::beginFrame() { @@ -17,6 +23,19 @@ void Seele::ForwardPlusRenderPath::beginFrame() void Seele::ForwardPlusRenderPath::render() { + for (auto entry : scene->getMeshBatches()) + { + PMaterial material = entry.key; + Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); + renderCommand->bindPipeline(material->getPipeline()); + for (auto drawState : entry.value.instances) + { + renderCommand->bindVertexBuffer(drawState.vertexBuffer); + renderCommand->bindIndexBuffer(drawState.indexBuffer); + renderCommand->bindDescriptor(drawState.instance->getDescriptor()); + renderCommand->draw(drawState); + } + } } void Seele::ForwardPlusRenderPath::endFrame() diff --git a/src/Engine/Graphics/ForwardPlusRenderPath.h b/src/Engine/Graphics/ForwardPlusRenderPath.h index 7499ca7..13b08bc 100644 --- a/src/Engine/Graphics/ForwardPlusRenderPath.h +++ b/src/Engine/Graphics/ForwardPlusRenderPath.h @@ -6,11 +6,12 @@ namespace Seele class ForwardPlusRenderPath : public SceneRenderPath { public: - ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target); - virtual ~ForwardPlusRenderPath(); + ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target); + virtual ~ForwardPlusRenderPath(); virtual void beginFrame() override; virtual void render() override; virtual void endFrame() override; + private: }; -} \ No newline at end of file +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index e2951a8..41945ba 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -20,12 +20,15 @@ public: virtual void beginRenderPass(PRenderPass renderPass) = 0; virtual void endRenderPass() = 0; + virtual void executeCommands(Array commands) = 0; + virtual PTexture2D createTexture2D(const TextureCreateInfo &createInfo) = 0; virtual PUniformBuffer createUniformBuffer(const BulkResourceData &bulkData) = 0; virtual PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) = 0; - virtual PVertexBuffer createVertexBuffer(const BulkResourceData &bulkData) = 0; - virtual PIndexBuffer createIndexBuffer(const BulkResourceData &bulkData) = 0; - + virtual PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) = 0; + virtual PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) = 0; + virtual PRenderCommand createRenderCommand() = 0; + virtual PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) = 0; protected: friend class Window; }; diff --git a/src/Engine/Graphics/GraphicsEnums.h b/src/Engine/Graphics/GraphicsEnums.h index 07a1749..ef90de1 100644 --- a/src/Engine/Graphics/GraphicsEnums.h +++ b/src/Engine/Graphics/GraphicsEnums.h @@ -1846,5 +1846,12 @@ typedef enum SeStencilFaceFlagBits SE_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } SeStencilFaceFlagBits; typedef SeFlags SeStencilFaceFlags; +enum class QueueType +{ + GRAPHICS = 1, + COMPUTE = 2, + TRANSFER = 3, + DEDICATED_TRANSFER = 4 +}; } // namespace Gfx } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/GraphicsInitializer.h b/src/Engine/Graphics/GraphicsInitializer.h new file mode 100644 index 0000000..e6c2ce5 --- /dev/null +++ b/src/Engine/Graphics/GraphicsInitializer.h @@ -0,0 +1,188 @@ +#include "GraphicsEnums.h" + +namespace Seele +{ + +struct GraphicsInitializer +{ + const char *windowLayoutFile; + const char *applicationName; + const char *engineName; + void *windowHandle; + /** + * layers defines the enabled Vulkan layers used in the instance, + * if ENABLE_VALIDATION is defined, standard validation is already enabled + * not yet implemented + */ + Array layers; + Array instanceExtensions; + Array deviceExtensions; + GraphicsInitializer() + : applicationName("SeeleEngine"), engineName("SeeleEngine"), layers{"VK_LAYER_LUNARG_standard_validation"}, instanceExtensions{}, deviceExtensions{"VK_KHR_swapchain"}, windowHandle(nullptr) + { + } + GraphicsInitializer(const GraphicsInitializer &other) + : applicationName(other.applicationName), engineName(other.engineName), layers(other.layers), instanceExtensions(other.instanceExtensions), deviceExtensions(other.deviceExtensions) + { + } +}; +struct WindowCreateInfo +{ + int32 width; + int32 height; + const char *title; + bool bFullscreen; + Gfx::SeFormat pixelFormat; + void *windowHandle; +}; +struct ViewportCreateInfo +{ + uint32 sizeX; + uint32 sizeY; + uint32 offsetX; + uint32 offsetY; +}; +struct TextureCreateInfo +{ + uint32 width; + uint32 height; + uint32 depth; + bool bArray; + uint32 arrayLayers; + uint32 mipLevels; + uint32 samples; + Gfx::SeFormat format; + Gfx::SeImageUsageFlagBits usage; + Gfx::QueueType queueType; + TextureCreateInfo() + : width(1), height(1), depth(1), bArray(false), arrayLayers(1), mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), queueType(Gfx::QueueType::GRAPHICS), usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT) + { + } +}; +// doesnt own the data, only proxy it +struct BulkResourceData +{ + uint32 size; + uint8 *data; + Gfx::QueueType owner; + BulkResourceData() + : size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS) + { + } +}; +struct VertexBufferCreateInfo +{ + BulkResourceData resourceData; + // bytes per vertex + uint32 vertexSize; + uint32 numVertices; + VertexBufferCreateInfo() + : resourceData(), vertexSize(0), numVertices(0) + { + } +}; +struct IndexBufferCreateInfo +{ + BulkResourceData resourceData; + Gfx::SeIndexType indexType; + IndexBufferCreateInfo() + : resourceData(), indexType(Gfx::SeIndexType::SE_INDEX_TYPE_UINT16) + { + } +}; + +namespace Gfx +{ +struct SePushConstantRange +{ + SeShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; +}; +struct VertexElement +{ + uint32 location; + SeFormat vertexFormat; + uint32 offset; +}; +struct RasterizationState +{ + uint8 depthClampEnable : 1; + uint8 rasterizerDiscardEnable : 1; + uint8 depthBiasEnable : 1; + float depthBoasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; + float lineWidth; + SePolygonMode polygonMode; + SeCullModeFlags cullMode; + SeFrontFace frontFace; +}; +struct MultisampleState +{ + uint32 samples; + float minSampleShading; + uint8 sampleShadingEnable : 1; + uint8 alphaCoverageEnable; + uint8 alphaToOneEnable; +}; +struct DepthStencilState +{ + uint8 depthTestEnable : 1; + uint8 depthWriteEnable : 1; + uint8 depthBoundsTestEnable : 1; + uint8 stencilTestEnable : 1; + SeCompareOp depthCompareOp; + SeStencilOp front; + SeStencilOp back; + float minDepthBounds; + float maxDepthBounds; +}; +struct ColorBlendState +{ + uint8 logicOpEnable : 1; + SeLogicOp logicOp; + uint32 attachmentCount; + struct BlendAttachment + { + uint8 blendEnable; + SeBlendFactor srcColorBlendFactor; + SeBlendFactor dstColorBlendFactor; + SeBlendOp colorBlendOp; + SeBlendFactor srcAlphaBlendFactor; + SeBlendFactor dstAlphaBlendFactor; + SeBlendOp alphaBlendOp; + SeColorComponentFlags colorWriteMask; + } blendAttachments[16]; + float blendConstants[4]; +}; +} // namespace Gfx +DECLARE_NAME_REF(Gfx, VertexDeclaration); +DECLARE_NAME_REF(Gfx, VertexShader); +DECLARE_NAME_REF(Gfx, ControlShader); +DECLARE_NAME_REF(Gfx, EvaluationShader); +DECLARE_NAME_REF(Gfx, GeometryShader); +DECLARE_NAME_REF(Gfx, FragmentShader); +DECLARE_NAME_REF(Gfx, PipelineLayout); +DECLARE_NAME_REF(Gfx, RenderPass); +struct GraphicsPipelineCreateInfo +{ + Gfx::PVertexDeclaration vertexDeclaration; + Gfx::PVertexShader vertexShader; + Gfx::PControlShader controlShader; + Gfx::PEvaluationShader evalShader; + Gfx::PGeometryShader geometryShader; + Gfx::PFragmentShader fragmentShader; + Gfx::PPipelineLayout pipelineLayout; + Gfx::PRenderPass renderPass; + Gfx::SePrimitiveTopology topology; + Gfx::RasterizationState rasterizationState; + Gfx::DepthStencilState depthStencilState; + Gfx::MultisampleState multisampleState; + Gfx::ColorBlendState colorBlend; + GraphicsPipelineCreateInfo() + { + std::memset(this, 0, sizeof(*this)); + } +}; +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/GraphicsResources.cpp b/src/Engine/Graphics/GraphicsResources.cpp index a95860f..dfee69b 100644 --- a/src/Engine/Graphics/GraphicsResources.cpp +++ b/src/Engine/Graphics/GraphicsResources.cpp @@ -1,4 +1,5 @@ #include "GraphicsResources.h" +#include "Material/MaterialInstance.h" using namespace Seele; using namespace Seele::Gfx; @@ -46,6 +47,7 @@ void PipelineLayout::addDescriptorLayout(uint32 setIndex, PDescriptorLayout layo else { descriptorSetLayouts[setIndex] = layout; + layout->setIndex = setIndex; } } @@ -61,6 +63,67 @@ UniformBuffer::UniformBuffer() UniformBuffer::~UniformBuffer() { } +VertexBuffer::VertexBuffer(uint32 numVertices, uint32 vertexSize) + : numVertices(numVertices), vertexSize(vertexSize) +{ +} +VertexBuffer::~VertexBuffer() +{ +} +IndexBuffer::IndexBuffer(uint32 size, Gfx::SeIndexType indexType) + : indexType(indexType) +{ + switch (indexType) + { + case SE_INDEX_TYPE_UINT16: + numIndices = size / 16; + break; + case SE_INDEX_TYPE_UINT32: + numIndices = size / 32; + default: + break; + } +} +IndexBuffer::~IndexBuffer() +{ +} +VertexStream::VertexStream(PVertexBuffer buffer, uint8 instanced) + : buffer(buffer) + , instanced(instanced) +{ +} +VertexStream::~VertexStream() +{ +} +void VertexStream::addVertexElement(VertexElement element) +{ + vertexDescription.add(element); +} +const Array VertexStream::getVertexDescriptions() const +{ + return vertexDescription; +} +Gfx::PVertexBuffer VertexStream::getVertexBuffer() +{ + return buffer; +} + +VertexDeclaration::VertexDeclaration() +{ +} +VertexDeclaration::~VertexDeclaration() +{ +} +uint32 VertexDeclaration::addVertexStream(const VertexStream &element) +{ + uint32 currIndex = vertexStreams.size(); + vertexStreams.add(element); + return currIndex; +} +const Array &VertexDeclaration::getVertexStreams() const +{ + return vertexStreams; +} RenderTargetLayout::RenderTargetLayout() : inputAttachments(), colorAttachments(), depthAttachment() diff --git a/src/Engine/Graphics/GraphicsResources.h b/src/Engine/Graphics/GraphicsResources.h index aef4e2c..9366385 100644 --- a/src/Engine/Graphics/GraphicsResources.h +++ b/src/Engine/Graphics/GraphicsResources.h @@ -1,7 +1,10 @@ #pragma once #include "GraphicsEnums.h" #include "Containers/Array.h" +#include "Containers/List.h" #include "Math/MemCRC.h" +#include "Material/MaterialInstance.h" +#include "GraphicsInitializer.h" #ifdef _DEBUG #define ENABLE_VALIDATION @@ -9,97 +12,35 @@ namespace Seele { -namespace Gfx + +DECLARE_NAME_REF(Gfx, VertexBuffer); +DECLARE_NAME_REF(Gfx, IndexBuffer); +struct DrawInstance { -enum class QueueType -{ - GRAPHICS = 1, - COMPUTE = 2, - TRANSFER = 3, - DEDICATED_TRANSFER = 4 -}; -} // namespace Gfx -struct GraphicsInitializer -{ - const char *windowLayoutFile; - const char *applicationName; - const char *engineName; - void *windowHandle; - /** - * layers defines the enabled Vulkan layers used in the instance, - * if ENABLE_VALIDATION is defined, standard validation is already enabled - * not yet implemented - */ - Array layers; - Array instanceExtensions; - Array deviceExtensions; - GraphicsInitializer() - : applicationName("SeeleEngine"), engineName("SeeleEngine"), layers{"VK_LAYER_LUNARG_standard_validation"}, instanceExtensions{}, deviceExtensions{"VK_KHR_swapchain"}, windowHandle(nullptr) - { - } - GraphicsInitializer(const GraphicsInitializer &other) - : applicationName(other.applicationName), engineName(other.engineName), layers(other.layers), instanceExtensions(other.instanceExtensions), deviceExtensions(other.deviceExtensions) + Matrix4 modelMatrix; + PMaterialInstance instance; + Gfx::PIndexBuffer indexBuffer; + Gfx::PVertexBuffer vertexBuffer; + + uint32 numInstances; + uint32 baseVertexIndex; + uint32 minVertexIndex; + uint32 firstInstance; + DrawInstance() + : instance(nullptr), indexBuffer(nullptr), vertexBuffer(nullptr), modelMatrix(1), numInstances(1), baseVertexIndex(0), minVertexIndex(0), firstInstance(0) { } }; -struct WindowCreateInfo +struct DrawState { - int32 width; - int32 height; - const char *title; - bool bFullscreen; - Gfx::SeFormat pixelFormat; - void *windowHandle; -}; -struct ViewportCreateInfo -{ - uint32 sizeX; - uint32 sizeY; - uint32 offsetX; - uint32 offsetY; - bool bFullscreen; - bool bVsync; -}; -struct TextureCreateInfo -{ - uint32 width; - uint32 height; - uint32 depth; - bool bArray; - uint32 arrayLayers; - uint32 mipLevels; - uint32 samples; - Gfx::SeFormat format; - Gfx::SeImageUsageFlagBits usage; - Gfx::QueueType queueType; - TextureCreateInfo() - : width(1), height(1), depth(1), bArray(false), arrayLayers(1), mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT) + Array instances; + + DrawState() { } }; -//doesnt own the data, only proxy it -struct BulkResourceData -{ - uint32 size; - uint8 *data; - Gfx::QueueType owner; -}; namespace Gfx { -struct SePushConstantRange -{ - SeShaderStageFlags stageFlags; - uint32_t offset; - uint32_t size; -}; -class RenderCommandBase -{ -public: - virtual ~RenderCommandBase() - { - } -}; -DEFINE_REF(RenderCommandBase); class SamplerState { public: @@ -108,6 +49,54 @@ public: } }; DEFINE_REF(SamplerState); + +class VertexShader +{ +public: + VertexShader() {} + virtual ~VertexShader() {} +}; +DEFINE_REF(VertexShader); +class ControlShader +{ +public: + ControlShader() {} + virtual ~ControlShader() {} + uint32 getNumPatches() const { return numPatchPoints; } + +protected: + uint32 numPatchPoints; +}; +DEFINE_REF(ControlShader); +class EvaluationShader +{ +public: + EvaluationShader() {} + virtual ~EvaluationShader() {} +}; +DEFINE_REF(EvaluationShader); +class GeometryShader +{ +public: + GeometryShader() {} + virtual ~GeometryShader() {} +}; +DEFINE_REF(GeometryShader); +class FragmentShader +{ +public: + FragmentShader() {} + virtual ~FragmentShader() {} +}; +DEFINE_REF(FragmentShader); +class ComputeShader +{ +public: + ComputeShader() {} + virtual ~ComputeShader() {} +}; +DEFINE_REF(ComputeShader); + class DescriptorBinding { public: @@ -155,13 +144,18 @@ public: virtual void updateSampler(uint32 binding, PSamplerState samplerState) = 0; virtual void updateTexture(uint32 binding, PTexture texture, PSamplerState samplerState = nullptr) = 0; virtual bool operator<(PDescriptorSet other) = 0; + + virtual uint32 getSetIndex() const = 0; }; DEFINE_REF(DescriptorSet); class DescriptorLayout { public: - DescriptorLayout() {} + DescriptorLayout() + : setIndex(0) + { + } virtual ~DescriptorLayout() {} void operator=(const DescriptorLayout &other) { @@ -172,10 +166,12 @@ public: virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1); virtual PDescriptorSet allocatedDescriptorSet(); const Array &getBindings() const { return descriptorBindings; } + inline uint32 getSetIndex() const { return setIndex; } protected: Array descriptorBindings; PDescriptorAllocator allocator; + uint32 setIndex; friend class PipelineLayout; friend class DescriptorAllocator; }; @@ -195,22 +191,6 @@ protected: Array pushConstants; }; DEFINE_REF(PipelineLayout); -class VertexDeclaration -{ -public: - virtual ~VertexDeclaration() - { - } -}; -DEFINE_REF(VertexDeclaration); -class GraphicsPipeline -{ -public: - virtual ~GraphicsPipeline() - { - } -}; -DEFINE_REF(GraphicsPipeline); class UniformBuffer { public: @@ -221,17 +201,40 @@ DEFINE_REF(UniformBuffer); class VertexBuffer { public: - virtual ~VertexBuffer() + VertexBuffer(uint32 numVertices, uint32 vertexSize); + virtual ~VertexBuffer(); + inline uint32 getNumVertices() { + return numVertices; } + // Size of one vertex in bytes + inline uint32 getVertexSize() + { + return vertexSize; + } + +protected: + uint32 numVertices; + uint32 vertexSize; }; DEFINE_REF(VertexBuffer); class IndexBuffer { public: - virtual ~IndexBuffer() + IndexBuffer(uint32 size, Gfx::SeIndexType index); + virtual ~IndexBuffer(); + inline uint32 getNumIndices() const { + return numIndices; } + inline Gfx::SeIndexType getIndexType() const + { + return indexType; + } + +protected: + Gfx::SeIndexType indexType; + uint32 numIndices; }; DEFINE_REF(IndexBuffer); class StructuredBuffer @@ -242,6 +245,44 @@ public: } }; DEFINE_REF(StructuredBuffer); +class VertexStream +{ +public: + VertexStream() {} + VertexStream(PVertexBuffer buffer, uint8 instanced); + ~VertexStream(); + void addVertexElement(VertexElement element); + const Array getVertexDescriptions() const; + PVertexBuffer getVertexBuffer(); + inline uint8 isInstanced() const { return instanced; } + +private: + PVertexBuffer buffer; + Array vertexDescription; + uint8 instanced; +}; +class VertexDeclaration +{ +public: + VertexDeclaration(); + ~VertexDeclaration(); + uint32 addVertexStream(const VertexStream &vertexStream); + const Array &getVertexStreams() const; + +private: + Array vertexStreams; +}; +DEFINE_REF(VertexDeclaration); +class GraphicsPipeline +{ +public: + GraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) : createInfo(createInfo) {} + virtual ~GraphicsPipeline(){} + const GraphicsPipelineCreateInfo& getCreateInfo() const {return createInfo;} +protected: + GraphicsPipelineCreateInfo createInfo; +}; +DEFINE_REF(GraphicsPipeline); class Texture { public: @@ -259,6 +300,20 @@ public: }; DEFINE_REF(Texture2D); +class RenderCommand +{ +public: + virtual ~RenderCommand() + { + } + virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0; + virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0; + virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) = 0; + virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0; + virtual void draw(DrawInstance data) = 0; +}; +DEFINE_REF(RenderCommand); + class Window { public: @@ -285,6 +340,7 @@ public: virtual ~Viewport(); virtual void resize(uint32 newX, uint32 newY) = 0; virtual void move(uint32 newOffsetX, uint32 newOffsetY) = 0; + protected: uint32 sizeX; uint32 sizeY; @@ -364,12 +420,13 @@ DEFINE_REF(RenderTargetLayout); class RenderPass { public: - virtual ~RenderPass() - { - } -}; -DEFINE_REF(RenderPass); + RenderPass(PRenderTargetLayout layout) : layout(layout) {} + virtual ~RenderPass() {} + inline PRenderTargetLayout getLayout() const { return layout; } +protected: + PRenderTargetLayout layout; +}; DEFINE_REF(RenderPass); } // namespace Gfx } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Mesh.cpp b/src/Engine/Graphics/Mesh.cpp index f99d1ac..49582af 100644 --- a/src/Engine/Graphics/Mesh.cpp +++ b/src/Engine/Graphics/Mesh.cpp @@ -1 +1 @@ -#include "Mesh.h" \ No newline at end of file +#include "Mesh.h" diff --git a/src/Engine/Graphics/Mesh.h b/src/Engine/Graphics/Mesh.h index fd0917a..d94a27c 100644 --- a/src/Engine/Graphics/Mesh.h +++ b/src/Engine/Graphics/Mesh.h @@ -8,8 +8,9 @@ class Mesh public: Mesh(Gfx::PVertexBuffer vertexBuffer, Gfx::PIndexBuffer indexBuffer); ~Mesh(); + private: Gfx::VertexBuffer vertexBuffer; Gfx::IndexBuffer indexBuffer; }; -} \ No newline at end of file +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/RenderCore.cpp b/src/Engine/Graphics/RenderCore.cpp index d792029..42c9866 100644 --- a/src/Engine/Graphics/RenderCore.cpp +++ b/src/Engine/Graphics/RenderCore.cpp @@ -1,4 +1,5 @@ #include "RenderCore.h" +#include "SceneView.h" Seele::RenderCore::RenderCore() { @@ -16,7 +17,13 @@ void Seele::RenderCore::init() mainWindowInfo.width = 1280; mainWindowInfo.height = 720; mainWindowInfo.bFullscreen = false; - windowManager->addWindow(mainWindowInfo); + auto window = windowManager->addWindow(mainWindowInfo); + ViewportCreateInfo sceneViewInfo; + sceneViewInfo.sizeX = 1280; + sceneViewInfo.sizeY = 720; + sceneViewInfo.offsetX = 0; + sceneViewInfo.offsetY = 0; + PSceneView sceneView = new SceneView(windowManager->getGraphics(), window, sceneViewInfo); } void Seele::RenderCore::renderLoop() diff --git a/src/Engine/Graphics/RenderCore.h b/src/Engine/Graphics/RenderCore.h index 0c091b1..45498d4 100644 --- a/src/Engine/Graphics/RenderCore.h +++ b/src/Engine/Graphics/RenderCore.h @@ -1,5 +1,6 @@ #pragma once #include "WindowManager.h" +#include "Scene/Scene.h" namespace Seele { class RenderCore @@ -12,6 +13,7 @@ public: void shutdown(); private: + PScene scene; PWindowManager windowManager; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPath.cpp b/src/Engine/Graphics/RenderPath.cpp index 5bfb80d..7ea627a 100644 --- a/src/Engine/Graphics/RenderPath.cpp +++ b/src/Engine/Graphics/RenderPath.cpp @@ -1,8 +1,8 @@ #include "RenderPath.h" +#include "GraphicsResources.h" Seele::RenderPath::RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target) - : graphics(graphics) - , target(target) + : graphics(graphics), target(target) { } @@ -10,7 +10,7 @@ Seele::RenderPath::~RenderPath() { } -void Seele::RenderPath::applyArea(Rect newArea) +void Seele::RenderPath::applyArea(URect newArea) { target->resize(newArea.size.x, newArea.size.y); target->move(newArea.offset.x, newArea.offset.y); diff --git a/src/Engine/Graphics/RenderPath.h b/src/Engine/Graphics/RenderPath.h index 87b9ff8..b8e337b 100644 --- a/src/Engine/Graphics/RenderPath.h +++ b/src/Engine/Graphics/RenderPath.h @@ -8,10 +8,11 @@ class RenderPath public: RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target); virtual ~RenderPath(); - virtual void applyArea(Rect area); + virtual void applyArea(URect area); virtual void beginFrame() = 0; virtual void render() = 0; virtual void endFrame() = 0; + protected: Gfx::PGraphics graphics; Gfx::PViewport target; diff --git a/src/Engine/Graphics/SceneRenderPath.cpp b/src/Engine/Graphics/SceneRenderPath.cpp index 154dbf6..a3e3f1d 100644 --- a/src/Engine/Graphics/SceneRenderPath.cpp +++ b/src/Engine/Graphics/SceneRenderPath.cpp @@ -1,8 +1,10 @@ #include "SceneRenderPath.h" +#include "Scene/Scene.h" Seele::SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target) : RenderPath(graphics, target) { + scene = new Scene(); } Seele::SceneRenderPath::~SceneRenderPath() diff --git a/src/Engine/Graphics/SceneRenderPath.h b/src/Engine/Graphics/SceneRenderPath.h index 9b0c790..b93cf61 100644 --- a/src/Engine/Graphics/SceneRenderPath.h +++ b/src/Engine/Graphics/SceneRenderPath.h @@ -3,6 +3,7 @@ namespace Seele { +DECLARE_REF(Scene); class SceneRenderPath : public RenderPath { public: @@ -11,5 +12,8 @@ public: virtual void beginFrame() = 0; virtual void render() = 0; virtual void endFrame() = 0; + +protected: + PScene scene; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/SceneView.cpp b/src/Engine/Graphics/SceneView.cpp index 441e3d4..301e80e 100644 --- a/src/Engine/Graphics/SceneView.cpp +++ b/src/Engine/Graphics/SceneView.cpp @@ -1,7 +1,8 @@ #include "SceneView.h" #include "ForwardPlusRenderPath.h" +#include "Window.h" -Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo& createInfo) +Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo) : View(graphics, owner, createInfo) { renderer = new ForwardPlusRenderPath(graphics, viewport); diff --git a/src/Engine/Graphics/SceneView.h b/src/Engine/Graphics/SceneView.h index 59aaf41..57f1c77 100644 --- a/src/Engine/Graphics/SceneView.h +++ b/src/Engine/Graphics/SceneView.h @@ -5,7 +5,8 @@ namespace Seele class SceneView : public View { public: - SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo& createInfo); + SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo); ~SceneView(); }; +DEFINE_REF(SceneView); } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/View.cpp b/src/Engine/Graphics/View.cpp index 8ee559c..491e912 100644 --- a/src/Engine/Graphics/View.cpp +++ b/src/Engine/Graphics/View.cpp @@ -1,9 +1,8 @@ #include "View.h" #include "Window.h" -Seele::View::View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& viewportInfo) - : graphics(graphics) - , owner(owner) +Seele::View::View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &viewportInfo) + : graphics(graphics), owner(window) { viewport = graphics->createViewport(owner->getGfxHandle(), viewportInfo); } @@ -27,7 +26,7 @@ void Seele::View::endFrame() renderer->endFrame(); } -void Seele::View::applyArea(Rect area) +void Seele::View::applyArea(URect area) { renderer->applyArea(area); } diff --git a/src/Engine/Graphics/View.h b/src/Engine/Graphics/View.h index c5429fb..7d21895 100644 --- a/src/Engine/Graphics/View.h +++ b/src/Engine/Graphics/View.h @@ -7,12 +7,12 @@ DECLARE_REF(Window); class View { public: - View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo); + View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo); virtual ~View(); void beginFrame(); void render(); void endFrame(); - void applyArea(Rect area); + void applyArea(URect area); protected: Gfx::PGraphics graphics; diff --git a/src/Engine/Graphics/Vulkan/CMakeLists.txt b/src/Engine/Graphics/Vulkan/CMakeLists.txt index 96d10f3..b7a1784 100644 --- a/src/Engine/Graphics/Vulkan/CMakeLists.txt +++ b/src/Engine/Graphics/Vulkan/CMakeLists.txt @@ -18,6 +18,12 @@ target_sources(SeeleEngine VulkanInitializer.cpp VulkanRenderPass.h VulkanRenderPass.cpp + VulkanPipeline.h + VulkanPipeline.cpp + VulkanPipelineCache.h + VulkanPipelineCache.cpp + VulkanShader.h + VulkanShader.cpp VulkanTexture.cpp VulkanQueue.h VulkanQueue.cpp diff --git a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp index 92102f7..be7b6e0 100644 --- a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp @@ -5,12 +5,8 @@ using namespace Seele::Vulkan; -SubAllocation::SubAllocation(Allocation* owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize) - : owner(owner) - , size(size) - , allocatedOffset(allocatedOffset) - , alignedOffset(alignedOffset) - , allocatedSize(allocatedSize) +SubAllocation::SubAllocation(Allocation *owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize) + : owner(owner), size(size), allocatedOffset(allocatedOffset), alignedOffset(alignedOffset), allocatedSize(allocatedSize) { } @@ -29,9 +25,9 @@ bool SubAllocation::isReadable() const return owner->isReadable(); } -void* SubAllocation::getMappedPointer() +void *SubAllocation::getMappedPointer() { - return (uint8*)owner->getMappedPointer() + alignedOffset; + return (uint8 *)owner->getMappedPointer() + alignedOffset; } void SubAllocation::flushMemory() @@ -44,15 +40,9 @@ void SubAllocation::invalidateMemory() owner->invalidateMemory(); } -Allocation::Allocation(PGraphics graphics, Allocator* allocator, VkDeviceSize size, uint8 memoryTypeIndex, - VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo* dedicatedInfo) - : device(graphics->getDevice()) - , allocator(allocator) - , bytesAllocated(0) - , bytesUsed(0) - , readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - , properties(properties) - , memoryTypeIndex(memoryTypeIndex) +Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize size, uint8 memoryTypeIndex, + VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) + : device(graphics->getDevice()), allocator(allocator), bytesAllocated(0), bytesUsed(0), readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), properties(properties), memoryTypeIndex(memoryTypeIndex) { VkMemoryAllocateInfo allocInfo = init::MemoryAllocateInfo(); @@ -110,8 +100,8 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice { freeAllocation->size -= size; freeAllocation->allocatedSize -= size; - freeAllocation->allocatedOffset += allocatedOffset; - freeAllocation->alignedOffset += allocatedOffset; + freeAllocation->allocatedOffset += size; + freeAllocation->alignedOffset += size; PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size); activeAllocations[allocatedOffset] = subAlloc.getHandle(); freeRanges.erase(allocatedOffset); @@ -123,15 +113,15 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice return nullptr; } -void Allocation::markFree(SubAllocation* allocation) +void Allocation::markFree(SubAllocation *allocation) { VkDeviceSize lowerBound = allocation->allocatedOffset; VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize; PSubAllocation allocHandle; - for(auto freeRange : freeRanges) + for (auto freeRange : freeRanges) { PSubAllocation freeAlloc = freeRange.value; - if(freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound) + if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound) { freeAlloc->allocatedSize += allocation->allocatedSize; allocHandle = freeAlloc; @@ -139,9 +129,9 @@ void Allocation::markFree(SubAllocation* allocation) } } auto foundAlloc = freeRanges.find(upperBound + 1); - if(foundAlloc != freeRanges.end()) + if (foundAlloc != freeRanges.end()) { - if(allocHandle == nullptr) + if (allocHandle == nullptr) { allocHandle->allocatedSize += foundAlloc->value->allocatedSize; freeRanges.erase(foundAlloc->key); @@ -153,7 +143,7 @@ void Allocation::markFree(SubAllocation* allocation) allocHandle->alignedOffset -= allocation->allocatedSize; } } - if(allocHandle == nullptr) + if (allocHandle == nullptr) { allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize); freeRanges[allocation->allocatedOffset] = allocHandle; @@ -170,16 +160,16 @@ Allocator::Allocator(PGraphics graphics) for (size_t i = 0; i < memProperties.memoryHeapCount; ++i) { VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i]; - HeapInfo& heapInfo = heaps[i]; + HeapInfo &heapInfo = heaps[i]; heapInfo.maxSize = memoryHeap.size; } } Allocator::~Allocator() { - for(auto heap : heaps) + for (auto heap : heaps) { - for(auto alloc : heap.allocations) + for (auto alloc : heap.allocations) { assert(alloc->activeAllocations.empty()); assert(alloc->freeRanges.size() == 1); @@ -189,45 +179,45 @@ Allocator::~Allocator() graphics = nullptr; } -PSubAllocation Allocator::allocate(const VkMemoryRequirements2& memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo* dedicatedInfo) +PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) { - const VkMemoryRequirements& requirements = memRequirements2.memoryRequirements; + const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements; uint8 memoryTypeIndex; VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex)); uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex; - - if(memRequirements2.pNext != nullptr) + + if (memRequirements2.pNext != nullptr) { - VkMemoryDedicatedRequirements* dedicatedReq = (VkMemoryDedicatedRequirements*)memRequirements2.pNext; - if(dedicatedReq->prefersDedicatedAllocation) + VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext; + if (dedicatedReq->prefersDedicatedAllocation) { PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo); heaps[heapIndex].allocations.add(newAllocation); return newAllocation->getSuballocation(requirements.size, requirements.alignment); } } - for(auto alloc : heaps[heapIndex].allocations) + for (auto alloc : heaps[heapIndex].allocations) { PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment); - if(suballoc != nullptr) + if (suballoc != nullptr) { return suballoc; } } - + // no suitable allocations found, allocate new block PAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : MemoryBlockSize, memoryTypeIndex, properties, nullptr); heaps[heapIndex].allocations.add(newAllocation); return newAllocation->getSuballocation(requirements.size, requirements.alignment); } -void Allocator::free(Allocation* allocation) +void Allocator::free(Allocation *allocation) { - for(auto heap : heaps) + for (auto heap : heaps) { - for(uint32 i = 0; i < heap.allocations.size(); ++i) + for (uint32 i = 0; i < heap.allocations.size(); ++i) { - if(heap.allocations[i] == allocation) + if (heap.allocations[i] == allocation) { heap.allocations.remove(i, false); return; @@ -236,7 +226,7 @@ void Allocator::free(Allocation* allocation) } } -VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8* typeIndex) +VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex) { for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex) { @@ -250,43 +240,37 @@ VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags proper } typeBits >>= 1; } - + return VK_ERROR_FORMAT_NOT_SUPPORTED; } StagingBuffer::StagingBuffer() { - } StagingBuffer::~StagingBuffer() { - } StagingManager::StagingManager(PGraphics graphics, PAllocator allocator) - : graphics(graphics) - , allocator(allocator) + : graphics(graphics), allocator(allocator) { - } StagingManager::~StagingManager() { - } void StagingManager::clearPending() { - } PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead) { - for(auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it) - { + for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it) + { auto freeBuffer = *it; - if(freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead) + if (freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead) { activeBuffers.add(freeBuffer.getHandle()); freeBuffers.remove(it, false); @@ -311,14 +295,13 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF bufferQuery.buffer = stagingBuffer->buffer; vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs); - memReqs.memoryRequirements.alignment = - (16 > memReqs.memoryRequirements.alignment) ? - 16 : memReqs.memoryRequirements.alignment; + memReqs.memoryRequirements.alignment = + (16 > memReqs.memoryRequirements.alignment) ? 16 : memReqs.memoryRequirements.alignment; - stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_CACHED_BIT : VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), stagingBuffer->buffer); + stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : VK_MEMORY_PROPERTY_HOST_CACHED_BIT), stagingBuffer->buffer); stagingBuffer->bReadable = bCPURead; vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset()); - + activeBuffers.add(stagingBuffer.getHandle()); return stagingBuffer; } diff --git a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp index fa87c57..28e1915 100644 --- a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp @@ -58,9 +58,14 @@ Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::Q Buffer::~Buffer() { + auto fence = getCommands()->getCommands()->getFence(); + auto &deletionQueue = graphics->getDeletionQueue(); + VkDevice device = graphics->getDevice(); + VkBuffer buf[Gfx::numFramesBuffered]; for (uint32 i = 0; i < numBuffers; ++i) { - vkDestroyBuffer(graphics->getDevice(), buffers[i].buffer, nullptr); + buf[i] = buffers[i].buffer; + deletionQueue.addPendingDelete(fence, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); }); buffers[i].allocation = nullptr; } } @@ -221,10 +226,9 @@ void Buffer::unlock() std::memset(®ion, 0, sizeof(VkBufferCopy)); region.size = size; vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - - graphics->getStagingManager()->releaseStagingBuffer(stagingBuffer); } transferOwnership(pending.prevQueue); + graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer); } } @@ -278,13 +282,14 @@ VkAccessFlags StructuredBuffer::getDestAccessMask() return VK_ACCESS_MEMORY_READ_BIT; } -VertexBuffer::VertexBuffer(PGraphics graphics, const BulkResourceData &resourceData) - : Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.owner) +VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData) + : Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner) + , Gfx::VertexBuffer(resourceData.numVertices, resourceData.vertexSize) { - if (resourceData.data != nullptr) + if (resourceData.resourceData.data != nullptr) { void *data = lock(); - std::memcpy(data, resourceData.data, resourceData.size); + std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); unlock(); } } @@ -303,13 +308,14 @@ VkAccessFlags VertexBuffer::getDestAccessMask() return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; } -IndexBuffer::IndexBuffer(PGraphics graphics, const BulkResourceData &resourceData) - : Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.owner) +IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData) + : Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner) + , Gfx::IndexBuffer(resourceData.resourceData.size, resourceData.indexType) { - if (resourceData.data != nullptr) + if (resourceData.resourceData.data != nullptr) { void *data = lock(); - std::memcpy(data, resourceData.data, resourceData.size); + std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); unlock(); } } diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index ea63f6f..59f6812 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -1,9 +1,12 @@ #include "VulkanCommandBuffer.h" #include "VulkanInitializer.h" #include "VulkanGraphics.h" +#include "VulkanPipeline.h" #include "VulkanGraphicsEnums.h" #include "VulkanFramebuffer.h" #include "VulkanRenderPass.h" +#include "VulkanPipeline.h" +#include "VulkanDescriptorSets.h" using namespace Seele; using namespace Seele::Vulkan; @@ -74,7 +77,6 @@ void CmdBuffer::endRenderPass() { vkCmdEndRenderPass(handle); state = State::InsideBegin; - } void CmdBuffer::executeCommands(Array commands) @@ -112,6 +114,11 @@ void CmdBuffer::refreshFence() } } +PFence CmdBuffer::getFence() +{ + return fence; +} + SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool) : CmdBufferBase(graphics, cmdPool) { @@ -145,6 +152,33 @@ void SecondaryCmdBuffer::end() VK_CHECK(vkEndCommandBuffer(handle)); } +void SecondaryCmdBuffer::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline) +{ + pipeline = gfxPipeline.cast(); + pipeline->bind(handle); +} +void SecondaryCmdBuffer::bindDescriptor(Gfx::PDescriptorSet descriptorSet) +{ + VkDescriptorSet setHandle = descriptorSet.cast()->getHandle(); + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr); +} +void SecondaryCmdBuffer::bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) +{ + PVertexBuffer buf = vertexBuffer.cast(); + const VkBuffer bufHandle[1] = {buf->getHandle()}; + const VkDeviceSize offsets[1] = {0}; + vkCmdBindVertexBuffers(handle, 0, 1, bufHandle, offsets); +} +void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) +{ + PIndexBuffer buf = indexBuffer.cast(); + vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, VK_INDEX_TYPE_UINT16); +} +void SecondaryCmdBuffer::draw(DrawInstance data) +{ + vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, data.firstInstance); +} + CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue) : graphics(graphics), queue(queue) { @@ -220,4 +254,4 @@ void CommandBufferManager::waitForCommands(PCmdBuffer cmdBuffer, uint32 timeout) { cmdBuffer->fence->wait(timeout); cmdBuffer->refreshFence(); -} \ No newline at end of file +} diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h index ca52813..2cf22f3 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h @@ -8,7 +8,7 @@ namespace Vulkan { DECLARE_REF(RenderPass); DECLARE_REF(Framebuffer); -class CmdBufferBase : public Gfx::RenderCommandBase +class CmdBufferBase { public: CmdBufferBase(PGraphics graphics, VkCommandPool cmdPool); @@ -41,6 +41,7 @@ public: void executeCommands(Array secondaryCommands); void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore); void refreshFence(); + PFence getFence(); enum State { ReadyBegin, @@ -64,15 +65,22 @@ private: }; DEFINE_REF(CmdBuffer); -class SecondaryCmdBuffer : public CmdBufferBase +DECLARE_REF(GraphicsPipeline); +class SecondaryCmdBuffer : public CmdBufferBase, public Gfx::RenderCommand { public: SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool); virtual ~SecondaryCmdBuffer(); void begin(PCmdBuffer parent); void end(); + virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override; + virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override; + virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) override; + virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override; + virtual void draw(DrawInstance data) override; private: + PGraphicsPipeline pipeline; }; DEFINE_REF(SecondaryCmdBuffer); diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h index 0e1f140..caa419e 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h @@ -23,7 +23,6 @@ private: PGraphics graphics; Array bindings; VkDescriptorSetLayout layoutHandle; - friend class PipelineStateCacheManager; }; DEFINE_REF(DescriptorLayout); class PipelineLayout : public Gfx::PipelineLayout @@ -49,10 +48,33 @@ private: uint32 layoutHash; VkPipelineLayout layoutHandle; PGraphics graphics; - friend class PipelineStateCacheManager; }; DEFINE_REF(PipelineLayout); +class DescriptorAllocator : public Gfx::DescriptorAllocator +{ +public: + DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout); + virtual ~DescriptorAllocator(); + virtual void allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet); + + inline VkDescriptorPool getHandle() const + { + return poolHandle; + } + inline DescriptorLayout getLayout() const + { + return layout; + } + +private: + PGraphics graphics; + int maxSets = 512; + VkDescriptorPool poolHandle; + DescriptorLayout &layout; +}; +DEFINE_REF(DescriptorAllocator); + class DescriptorSet : public Gfx::DescriptorSet { public: @@ -70,6 +92,10 @@ public: { return setHandle; } + virtual uint32 getSetIndex() const + { + return owner->getLayout().getSetIndex(); + } private: virtual void writeChanges(); @@ -83,24 +109,5 @@ private: }; DEFINE_REF(DescriptorSet); -class DescriptorAllocator : public Gfx::DescriptorAllocator -{ -public: - DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout); - virtual ~DescriptorAllocator(); - virtual void allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet); - - inline VkDescriptorPool getHandle() - { - return poolHandle; - } - -private: - PGraphics graphics; - int maxSets = 512; - VkDescriptorPool poolHandle; - DescriptorLayout &layout; -}; -DEFINE_REF(DescriptorAllocator); } // namespace Vulkan } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp index 15a4780..a4e0422 100644 --- a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp @@ -8,9 +8,7 @@ using namespace Seele; using namespace Seele::Vulkan; Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRenderTargetLayout renderTargetLayout) - : graphics(graphics) - , layout(renderTargetLayout) - , renderPass(renderPass) + : graphics(graphics), layout(renderTargetLayout), renderPass(renderPass) { FramebufferDescription description; std::memset(&description, 0, sizeof(FramebufferDescription)); diff --git a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.h b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.h index 837e6d2..35b13f8 100644 --- a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.h +++ b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.h @@ -27,6 +27,7 @@ public: { return hash; } + private: uint32 hash; PGraphics graphics; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp index e502dfe..bb6f5cf 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp @@ -6,6 +6,7 @@ #include "VulkanCommandBuffer.h" #include "VulkanRenderPass.h" #include "VulkanFramebuffer.h" +#include "VulkanPipelineCache.h" #include "Graphics/GraphicsResources.h" #include @@ -42,6 +43,7 @@ void Graphics::init(GraphicsInitializer initInfo) computeCommands = new CommandBufferManager(this, computeQueue); transferCommands = new CommandBufferManager(this, transferQueue); dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue); + pipelineCache = new PipelineCache(this, "pipeline.cache"); } Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo) @@ -67,7 +69,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) uint32 framebufferHash = rp->getFramebufferHash(); PFramebuffer framebuffer; auto found = allocatedFramebuffers.find(framebufferHash); - if(found == allocatedFramebuffers.end()) + if (found == allocatedFramebuffers.end()) { framebuffer = new Framebuffer(this, rp, rp->getLayout()); } @@ -83,6 +85,18 @@ void Graphics::endRenderPass() graphicsCommands->getCommands()->endRenderPass(); } +void Graphics::executeCommands(Array commands) +{ + Array cmdBuffers(commands.size()); + for (uint32 i = 0; i < commands.size(); ++i) + { + PSecondaryCmdBuffer buf = commands[i].cast(); + buf->end(); + cmdBuffers[i] = buf->getHandle(); + } + vkCmdExecuteCommands(graphicsCommands->getCommands()->getHandle(), cmdBuffers.size(), cmdBuffers.data()); +} + Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo) { PTexture2D result = new Texture2D(this, createInfo.width, createInfo.height, createInfo.bArray, @@ -91,28 +105,39 @@ Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo) return result; } -Gfx::PUniformBuffer Graphics::createUniformBuffer(const BulkResourceData &bulkData) +Gfx::PUniformBuffer Graphics::createUniformBuffer(const BulkResourceData &bulkData) { PUniformBuffer uniformBuffer = new UniformBuffer(this, bulkData); return uniformBuffer; } -Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const BulkResourceData &bulkData) +Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const BulkResourceData &bulkData) { PStructuredBuffer structuredBuffer = new StructuredBuffer(this, bulkData); return structuredBuffer; } -Gfx::PVertexBuffer Graphics::createVertexBuffer(const BulkResourceData &bulkData) +Gfx::PVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData) { PVertexBuffer vertexBuffer = new VertexBuffer(this, bulkData); return vertexBuffer; } -Gfx::PIndexBuffer Graphics::createIndexBuffer(const BulkResourceData &bulkData) +Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData) { PIndexBuffer indexBuffer = new IndexBuffer(this, bulkData); return indexBuffer; } +Gfx::PRenderCommand Graphics::createRenderCommand() +{ + PSecondaryCmdBuffer cmdBuffer = graphicsCommands->createSecondaryCmdBuffer(); + cmdBuffer->begin(getGraphicsCommands()->getCommands()); + return cmdBuffer; +} +Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) +{ + PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo); + return pipeline; +} VkInstance Graphics::getInstance() const { @@ -173,6 +198,7 @@ Array Graphics::getRequiredExtensions() } void Graphics::initInstance(GraphicsInitializer initInfo) { + glfwInit(); VkApplicationInfo appInfo = {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = initInfo.applicationName; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.h b/src/Engine/Graphics/Vulkan/VulkanGraphics.h index a2e8da2..43df875 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.h @@ -11,6 +11,8 @@ DECLARE_REF(StagingManager); DECLARE_REF(CommandBufferManager); DECLARE_REF(Queue); DECLARE_REF(Framebuffer); +DECLARE_REF(RenderCommand); +DECLARE_REF(PipelineCache); class Graphics : public Gfx::Graphics { public: @@ -29,6 +31,10 @@ public: { return queueMapping; } + QueueOwnedResourceDeletion &getDeletionQueue() + { + return deletionQueue; + } PAllocator getAllocator(); PStagingManager getStagingManager(); @@ -42,11 +48,15 @@ public: virtual void beginRenderPass(Gfx::PRenderPass renderPass) override; virtual void endRenderPass() override; + virtual void executeCommands(Array commands) override; + virtual Gfx::PTexture2D createTexture2D(const TextureCreateInfo &createInfo) override; virtual Gfx::PUniformBuffer createUniformBuffer(const BulkResourceData &bulkData) override; virtual Gfx::PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) override; - virtual Gfx::PVertexBuffer createVertexBuffer(const BulkResourceData &bulkData) override; - virtual Gfx::PIndexBuffer createIndexBuffer(const BulkResourceData &bulkData) override; + virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override; + virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override; + virtual Gfx::PRenderCommand createRenderCommand() override; + virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override; protected: Array getRequiredExtensions(); @@ -64,6 +74,8 @@ protected: PQueue transferQueue; PQueue dedicatedTransferQueue; QueueFamilyMapping queueMapping; + QueueOwnedResourceDeletion deletionQueue; + PPipelineCache pipelineCache; PCommandBufferManager graphicsCommands; PCommandBufferManager computeCommands; PCommandBufferManager transferCommands; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp index a58375c..2871fe7 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.cpp @@ -1145,3 +1145,166 @@ Gfx::SeAttachmentLoadOp Seele::Vulkan::cast(const VkAttachmentLoadOp &loadOp) return SE_ATTACHMENT_LOAD_OP_MAX_ENUM; } } + +VkIndexType Seele::Vulkan::cast(const Gfx::SeIndexType &indexType) +{ + switch (indexType) + { + case Gfx::SE_INDEX_TYPE_UINT16: + return VK_INDEX_TYPE_UINT16; + case Gfx::SE_INDEX_TYPE_UINT32: + return VK_INDEX_TYPE_UINT32; + default: + return VK_INDEX_TYPE_MAX_ENUM; + } +} +Gfx::SeIndexType Seele::Vulkan::cast(const VkIndexType &indexType) +{ + switch (indexType) + { + case VK_INDEX_TYPE_UINT16: + return Gfx::SE_INDEX_TYPE_UINT16; + case VK_INDEX_TYPE_UINT32: + return Gfx::SE_INDEX_TYPE_UINT32; + default: + return Gfx::SE_INDEX_TYPE_MAX_ENUM; + } +} + +VkPrimitiveTopology Seele::Vulkan::cast(const Gfx::SePrimitiveTopology &topology) +{ + switch (topology) + { + case SE_PRIMITIVE_TOPOLOGY_POINT_LIST: + return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; + case SE_PRIMITIVE_TOPOLOGY_LINE_LIST: + return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; + case SE_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; + case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; + case SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; + case SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY; + case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; + case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; + case SE_PRIMITIVE_TOPOLOGY_PATCH_LIST: + return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; + default: + return VK_PRIMITIVE_TOPOLOGY_MAX_ENUM; + } +} +Gfx::SePrimitiveTopology Seele::Vulkan::cast(const VkPrimitiveTopology &topology) +{ + switch (topology) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return SE_PRIMITIVE_TOPOLOGY_POINT_LIST; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + return SE_PRIMITIVE_TOPOLOGY_LINE_LIST; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return SE_PRIMITIVE_TOPOLOGY_LINE_STRIP; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + return SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; + case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: + return SE_PRIMITIVE_TOPOLOGY_PATCH_LIST; + default: + return SE_PRIMITIVE_TOPOLOGY_MAX_ENUM; + } +} + +VkPolygonMode Seele::Vulkan::cast(const Gfx::SePolygonMode &mode) +{ + switch (mode) + { + case SE_POLYGON_MODE_FILL: + return VK_POLYGON_MODE_FILL; + case SE_POLYGON_MODE_LINE: + return VK_POLYGON_MODE_LINE; + case SE_POLYGON_MODE_POINT: + return VK_POLYGON_MODE_POINT; + default: + return VK_POLYGON_MODE_MAX_ENUM; + } +} +Gfx::SePolygonMode Seele::Vulkan::cast(const VkPolygonMode &mode) +{ + switch (mode) + { + case VK_POLYGON_MODE_FILL: + return SE_POLYGON_MODE_FILL; + case VK_POLYGON_MODE_LINE: + return SE_POLYGON_MODE_LINE; + case VK_POLYGON_MODE_POINT: + return SE_POLYGON_MODE_POINT; + default: + return SE_POLYGON_MODE_MAX_ENUM; + } +} +VkCompareOp Seele::Vulkan::cast(const Gfx::SeCompareOp &op) +{ + switch (op) + { + case SE_COMPARE_OP_NEVER: + return VK_COMPARE_OP_NEVER; + case SE_COMPARE_OP_LESS: + return VK_COMPARE_OP_LESS; + case SE_COMPARE_OP_EQUAL: + return VK_COMPARE_OP_EQUAL; + case SE_COMPARE_OP_LESS_OR_EQUAL: + return VK_COMPARE_OP_LESS_OR_EQUAL; + case SE_COMPARE_OP_GREATER: + return VK_COMPARE_OP_GREATER; + case SE_COMPARE_OP_NOT_EQUAL: + return VK_COMPARE_OP_NOT_EQUAL; + case SE_COMPARE_OP_GREATER_OR_EQUAL: + return VK_COMPARE_OP_GREATER_OR_EQUAL; + case SE_COMPARE_OP_ALWAYS: + return VK_COMPARE_OP_ALWAYS; + default: + return VK_COMPARE_OP_MAX_ENUM; + } +} +Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op) +{ + switch (op) + { + case VK_COMPARE_OP_NEVER: + return SE_COMPARE_OP_NEVER; + case VK_COMPARE_OP_LESS: + return SE_COMPARE_OP_LESS; + case VK_COMPARE_OP_EQUAL: + return SE_COMPARE_OP_EQUAL; + case VK_COMPARE_OP_LESS_OR_EQUAL: + return SE_COMPARE_OP_LESS_OR_EQUAL; + case VK_COMPARE_OP_GREATER: + return SE_COMPARE_OP_GREATER; + case VK_COMPARE_OP_NOT_EQUAL: + return SE_COMPARE_OP_NOT_EQUAL; + case VK_COMPARE_OP_GREATER_OR_EQUAL: + return SE_COMPARE_OP_GREATER_OR_EQUAL; + case VK_COMPARE_OP_ALWAYS: + return SE_COMPARE_OP_ALWAYS; + default: + return SE_COMPARE_OP_MAX_ENUM; + } +} \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h index cf9d98c..56c397c 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h @@ -16,6 +16,17 @@ namespace Seele { namespace Vulkan { + +enum class ShaderType +{ + VERTEX = 0, + CONTROL = 1, + EVALUATION = 2, + GEOMETRY = 3, + FRAGMENT = 4, + COMPUTE = 5, +}; + VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType); Gfx::SeDescriptorType cast(const VkDescriptorType &descriptorType); VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage); @@ -26,5 +37,13 @@ VkAttachmentStoreOp cast(const Gfx::SeAttachmentStoreOp &storeOp); Gfx::SeAttachmentStoreOp cast(const VkAttachmentStoreOp &storeOp); VkAttachmentLoadOp cast(const Gfx::SeAttachmentLoadOp &loadOp); Gfx::SeAttachmentLoadOp cast(const VkAttachmentLoadOp &loadOp); +VkIndexType cast(const Gfx::SeIndexType &indexType); +Gfx::SeIndexType cast(const VkIndexType &indexType); +VkPrimitiveTopology cast(const Gfx::SePrimitiveTopology &topology); +Gfx::SePrimitiveTopology cast(const VkPrimitiveTopology &topology); +VkPolygonMode cast(const Gfx::SePolygonMode &mode); +Gfx::SePolygonMode cast(const VkPolygonMode &mode); +VkCompareOp cast(const Gfx::SeCompareOp &op); +Gfx::SeCompareOp cast(const VkCompareOp &op); } // namespace Vulkan } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp index b66c2ca..483fc9f 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp @@ -7,6 +7,49 @@ using namespace Seele; using namespace Seele::Vulkan; +List QueueOwnedResourceDeletion::deletionQueue; +volatile bool QueueOwnedResourceDeletion::running; +std::mutex QueueOwnedResourceDeletion::mutex; +std::condition_variable QueueOwnedResourceDeletion::cv; + +QueueOwnedResourceDeletion::QueueOwnedResourceDeletion() +{ + worker = std::thread(&run); + running = true; +} + +QueueOwnedResourceDeletion::~QueueOwnedResourceDeletion() +{ + worker.join(); +} + +void QueueOwnedResourceDeletion::addPendingDelete(PFence fence, std::function func) +{ + PendingItem item; + item.fence = fence; + item.func = func; + deletionQueue.add(item); + std::unique_lock lock(mutex); + cv.notify_all(); +} + +void QueueOwnedResourceDeletion::run() +{ + while (running || !deletionQueue.empty()) + { + std::unique_lock lock(mutex); + cv.wait(lock); + auto entry = deletionQueue.begin(); + PFence fence = entry->fence; + fence->wait(1000ull); + if (fence->isSignaled()) + { + entry->func(); + deletionQueue.remove(entry); + } + } +} + QueueOwnedResource::QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType) : graphics(graphics), currentOwner(startQueueType) { diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h index ad09d29..1fccbdd 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h @@ -1,5 +1,8 @@ #pragma once #include "Graphics/GraphicsResources.h" +#include +#include +#include #include namespace Seele @@ -39,6 +42,10 @@ public: return fence; } void wait(uint32 timeout); + bool operator<(const Fence &other) const + { + return fence < other.fence; + } private: bool signaled; @@ -76,6 +83,26 @@ struct QueueFamilyMapping return srcIndex != dstIndex; } }; +class QueueOwnedResourceDeletion +{ +public: + QueueOwnedResourceDeletion(); + virtual ~QueueOwnedResourceDeletion(); + static void addPendingDelete(PFence fence, std::function function); + +private: + std::thread worker; + static volatile bool running; + static void run(); + struct PendingItem + { + PFence fence; + std::function func; + }; + static std::mutex mutex; + static std::condition_variable cv; + static List deletionQueue; +}; class QueueOwnedResource { public: @@ -154,7 +181,7 @@ DEFINE_REF(StructuredBuffer); class VertexBuffer : public Buffer, public Gfx::VertexBuffer { public: - VertexBuffer(PGraphics graphics, const BulkResourceData &resourceData); + VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData); virtual ~VertexBuffer(); protected: @@ -166,7 +193,7 @@ DEFINE_REF(VertexBuffer); class IndexBuffer : public Buffer, public Gfx::IndexBuffer { public: - IndexBuffer(PGraphics graphics, const BulkResourceData &resourceData); + IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData); virtual ~IndexBuffer(); protected: @@ -251,7 +278,8 @@ class Texture2D : public TextureBase, public Gfx::Texture2D public: Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY, bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format, - uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE); + uint32 samples, Gfx::SeImageUsageFlags usage, + Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE); virtual ~Texture2D(); inline uint32 getSizeX() const { @@ -334,6 +362,7 @@ public: virtual ~Viewport(); virtual void resize(uint32 newX, uint32 newY); virtual void move(uint32 newOffsetX, uint32 newOffsetY); + protected: private: PGraphics graphics; diff --git a/src/Engine/Graphics/Vulkan/VulkanPipeline.cpp b/src/Engine/Graphics/Vulkan/VulkanPipeline.cpp new file mode 100644 index 0000000..30243dc --- /dev/null +++ b/src/Engine/Graphics/Vulkan/VulkanPipeline.cpp @@ -0,0 +1,28 @@ +#include "VulkanPipeline.h" +#include "VulkanDescriptorSets.h" +#include "VulkanGraphics.h" + +using namespace Seele; +using namespace Seele::Vulkan; + +GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo) + : Gfx::GraphicsPipeline(createInfo) + , graphics(graphics) + , layout(pipelineLayout) + , pipeline(handle) +{ +} + +GraphicsPipeline::~GraphicsPipeline() +{ +} + +void GraphicsPipeline::bind(VkCommandBuffer handle) +{ + vkCmdBindPipeline(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); +} + +VkPipelineLayout GraphicsPipeline::getLayout() const +{ + return layout->getHandle(); +} \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanPipeline.h b/src/Engine/Graphics/Vulkan/VulkanPipeline.h new file mode 100644 index 0000000..643b98f --- /dev/null +++ b/src/Engine/Graphics/Vulkan/VulkanPipeline.h @@ -0,0 +1,24 @@ +#pragma once +#include "VulkanGraphicsResources.h" + +namespace Seele +{ +namespace Vulkan +{ +DECLARE_REF(PipelineLayout); +DECLARE_REF(Graphics); +class GraphicsPipeline : public Gfx::GraphicsPipeline +{ +public: + GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo); + virtual ~GraphicsPipeline(); + void bind(VkCommandBuffer handle); + VkPipelineLayout getLayout() const; +private: + VkPipeline pipeline; + PPipelineLayout layout; + PGraphics graphics; +}; +DEFINE_REF(GraphicsPipeline); +} // namespace Vulkan +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp new file mode 100644 index 0000000..a69506b --- /dev/null +++ b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp @@ -0,0 +1,240 @@ +#include "VulkanPipelineCache.h" +#include "VulkanGraphics.h" +#include "VulkanGraphicsEnums.h" +#include "VulkanInitializer.h" +#include "VulkanRenderPass.h" +#include "VulkanDescriptorSets.h" +#include "VulkanShader.h" + +using namespace Seele; +using namespace Seele::Vulkan; + +PipelineCache::PipelineCache(PGraphics graphics, const std::string& cacheFilePath) + : graphics(graphics) + , cacheFile(cacheFilePath) +{ + std::ifstream stream(cacheFilePath, std::ios::binary | std::ios::ate); + VkPipelineCacheCreateInfo cacheCreateInfo; + cacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + cacheCreateInfo.pNext = nullptr; + cacheCreateInfo.flags = 0; + cacheCreateInfo.initialDataSize = 0; + if(stream.good()) + { + Array cacheData; + uint32 fileSize = static_cast(stream.tellg()); + cacheData.resize(fileSize); + stream.seekg(0); + stream.read((char*)cacheData.data(), fileSize); + cacheCreateInfo.initialDataSize = fileSize; + cacheCreateInfo.pInitialData = cacheData.data(); + } + VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache)); +} + +PipelineCache::~PipelineCache() +{ + VkDeviceSize cacheSize; + vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, nullptr); + Array cacheData; + vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, cacheData.data()); + std::ofstream stream(cacheFile, std::ios::binary); + stream.write((char*)cacheData.data(), cacheSize); + stream.flush(); + stream.close(); + vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr); +} + +PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo& gfxInfo) +{ + VkGraphicsPipelineCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + createInfo.pNext = 0; + createInfo.flags = 0; + createInfo.stageCount = 0; + VkPipelineTessellationStateCreateInfo tessInfo; + VkPipelineShaderStageCreateInfo stageInfos[5]; + std::memset(stageInfos, 0, sizeof(stageInfos)); + if(gfxInfo.vertexShader != nullptr) + { + PVertexShader shader = gfxInfo.vertexShader.cast(); + VkPipelineShaderStageCreateInfo& vertInfo = stageInfos[createInfo.stageCount++]; + vertInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertInfo.module = shader->getModuleHandle(); + vertInfo.pName = shader->getEntryPointName(); + } + if(gfxInfo.controlShader != nullptr) + { + assert(gfxInfo.evalShader != nullptr); + PControlShader control = gfxInfo.controlShader.cast(); + PEvaluationShader eval = gfxInfo.evalShader.cast(); + + VkPipelineShaderStageCreateInfo& controlInfo = stageInfos[createInfo.stageCount++]; + controlInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + controlInfo.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + controlInfo.module = control->getModuleHandle(); + controlInfo.pName = control->getEntryPointName(); + + VkPipelineShaderStageCreateInfo& evalInfo = stageInfos[createInfo.stageCount++]; + evalInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + evalInfo.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + evalInfo.module = eval->getModuleHandle(); + evalInfo.pName = eval->getEntryPointName(); + + tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; + tessInfo.pNext = 0; + tessInfo.flags = 0; + tessInfo.patchControlPoints = control->getNumPatches(); + } + if(gfxInfo.geometryShader != nullptr) + { + PGeometryShader geometry = gfxInfo.geometryShader.cast(); + + VkPipelineShaderStageCreateInfo& geometryInfo = stageInfos[createInfo.stageCount++]; + geometryInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + geometryInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT; + geometryInfo.module = geometry->getModuleHandle(); + geometryInfo.pName = geometry->getEntryPointName(); + } + if(gfxInfo.fragmentShader != nullptr) + { + PFragmentShader fragment = gfxInfo.fragmentShader.cast(); + + VkPipelineShaderStageCreateInfo& fragmentInfo = stageInfos[createInfo.stageCount++]; + fragmentInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragmentInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragmentInfo.module = fragment->getModuleHandle(); + fragmentInfo.pName = fragment->getEntryPointName(); + } + VkPipelineVertexInputStateCreateInfo vertexInput = + init::PipelineVertexInputStateCreateInfo(); + Gfx::PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration; + auto vertexStreams = vertexDecl->getVertexStreams(); + Array bindingDesc(vertexStreams.size()); + Array attribDesc; + uint32 bindingNum = 0; + for(auto vertexBinding : vertexStreams) + { + uint32 stride = vertexBinding.getVertexBuffer()->getVertexSize(); + for(auto vertexAttrib : vertexBinding.getVertexDescriptions()) + { + auto attrib = attribDesc.add(); + attrib.binding = bindingNum; + attrib.format = cast(vertexAttrib.vertexFormat); + attrib.location = vertexAttrib.location; + attrib.offset = vertexAttrib.offset; + } + bindingDesc[bindingNum].binding = bindingNum; + bindingDesc[bindingNum].stride = stride; + bindingDesc[bindingNum].inputRate = vertexBinding.isInstanced() ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; + bindingNum++; + } + vertexInput.pVertexBindingDescriptions = bindingDesc.data(); + vertexInput.vertexBindingDescriptionCount = bindingDesc.size(); + vertexInput.pVertexAttributeDescriptions = attribDesc.data(); + vertexInput.vertexAttributeDescriptionCount = attribDesc.size(); + + VkPipelineInputAssemblyStateCreateInfo assemblyInfo = + init::PipelineInputAssemblyStateCreateInfo( + cast(gfxInfo.topology), + 0, + false + ); + + VkPipelineViewportStateCreateInfo viewportInfo = + init::PipelineViewportStateCreateInfo( + 1, + 1, + 0 + ); + + VkPipelineRasterizationStateCreateInfo rasterizationState = + init::PipelineRasterizationStateCreateInfo( + cast(gfxInfo.rasterizationState.polygonMode), + gfxInfo.rasterizationState.cullMode, + (VkFrontFace)gfxInfo.rasterizationState.frontFace, + 0 + ); + rasterizationState.depthBiasEnable = gfxInfo.rasterizationState.depthBiasEnable; + rasterizationState.depthBiasClamp = gfxInfo.rasterizationState.depthBiasClamp; + rasterizationState.depthBiasConstantFactor = gfxInfo.rasterizationState.depthBoasConstantFactor; + rasterizationState.depthBiasSlopeFactor = gfxInfo.rasterizationState.depthBiasSlopeFactor; + rasterizationState.depthClampEnable = gfxInfo.rasterizationState.depthClampEnable; + rasterizationState.lineWidth = gfxInfo.rasterizationState.lineWidth; + rasterizationState.rasterizerDiscardEnable = gfxInfo.rasterizationState.rasterizerDiscardEnable; + + VkPipelineMultisampleStateCreateInfo multisampleState = + init::PipelineMultisampleStateCreateInfo((VkSampleCountFlagBits)gfxInfo.multisampleState.samples, 0); + multisampleState.alphaToCoverageEnable = gfxInfo.multisampleState.alphaCoverageEnable; + multisampleState.alphaToOneEnable = gfxInfo.multisampleState.alphaToOneEnable; + multisampleState.minSampleShading = gfxInfo.multisampleState.minSampleShading; + multisampleState.sampleShadingEnable = gfxInfo.multisampleState.sampleShadingEnable; + + VkPipelineDepthStencilStateCreateInfo depthStencilState = + init::PipelineDepthStencilStateCreateInfo( + gfxInfo.depthStencilState.depthTestEnable, + gfxInfo.depthStencilState.depthWriteEnable, + cast(gfxInfo.depthStencilState.depthCompareOp) + ); + + const auto colorAttachments = gfxInfo.renderPass->getLayout()->colorAttachments; + Array blendAttachments(colorAttachments.size()); + for(uint32 i = 0; i < colorAttachments.size(); ++i) + { + const Gfx::ColorBlendState::BlendAttachment& attachment = gfxInfo.colorBlend.blendAttachments[i]; + VkPipelineColorBlendAttachmentState& blendAttachment = blendAttachments[i]; + blendAttachment.alphaBlendOp = (VkBlendOp)attachment.alphaBlendOp; + blendAttachment.blendEnable = attachment.blendEnable; + blendAttachment.colorBlendOp = (VkBlendOp)attachment.colorBlendOp; + blendAttachment.colorWriteMask = attachment.colorWriteMask; + blendAttachment.dstAlphaBlendFactor = (VkBlendFactor)attachment.dstAlphaBlendFactor; + blendAttachment.srcAlphaBlendFactor = (VkBlendFactor)attachment.srcAlphaBlendFactor; + blendAttachment.dstColorBlendFactor = (VkBlendFactor)attachment.dstColorBlendFactor; + blendAttachment.srcColorBlendFactor = (VkBlendFactor)attachment.srcColorBlendFactor; + } + VkPipelineColorBlendStateCreateInfo blendState = + init::PipelineColorBlendStateCreateInfo( + blendAttachments.size(), + blendAttachments.data() + ); + blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable; + blendState.logicOp = (VkLogicOp)gfxInfo.colorBlend.logicOp; + std::memcpy(blendState.blendConstants, gfxInfo.colorBlend.blendConstants, sizeof(float)*4); + + uint32 numDynamicEnabled = 0; + StaticArray dynamicEnabled; + dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_VIEWPORT; + dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_SCISSOR; + + VkPipelineDynamicStateCreateInfo dynamicState = + init::PipelineDynamicStateCreateInfo( + dynamicEnabled.data(), + numDynamicEnabled, + 0 + ); + + createInfo.pStages = stageInfos; + createInfo.pVertexInputState = &vertexInput; + createInfo.pInputAssemblyState = &assemblyInfo; + createInfo.pTessellationState = &tessInfo; + createInfo.pViewportState = &viewportInfo; + createInfo.pRasterizationState = &rasterizationState; + createInfo.pMultisampleState = &multisampleState; + createInfo.pDepthStencilState = &depthStencilState; + createInfo.pColorBlendState = &blendState; + createInfo.pDynamicState = &dynamicState; + createInfo.renderPass = gfxInfo.renderPass.cast()->getHandle(); + createInfo.layout = gfxInfo.pipelineLayout.cast()->getHandle(); + createInfo.subpass = 0; + + VkPipeline pipelineHandle; + auto beginTime = std::chrono::high_resolution_clock::now(); + VK_CHECK(vkCreateGraphicsPipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle)); + auto endTime = std::chrono::high_resolution_clock::now(); + int64 delta = std::chrono::duration_cast(endTime - beginTime).count(); + std::cout << "Gfx creation time: " << delta << std::endl; + + PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, gfxInfo.pipelineLayout.cast(), gfxInfo); + return result; +} \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.h b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.h new file mode 100644 index 0000000..21814ee --- /dev/null +++ b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.h @@ -0,0 +1,21 @@ +#pragma once +#include "VulkanPipeline.h" + +namespace Seele +{ +namespace Vulkan +{ +class PipelineCache +{ +public: + PipelineCache(PGraphics graphics, const std::string& cacheFilePath); + ~PipelineCache(); + PGraphicsPipeline createPipeline(const GraphicsPipelineCreateInfo& createInfo); +private: + VkPipelineCache cache; + PGraphics graphics; + std::string cacheFile; +}; +DEFINE_REF(PipelineCache); +} // namespace Vulkan +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp index 7b388b9..7c0878d 100644 --- a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp @@ -9,22 +9,19 @@ using namespace Seele; using namespace Seele::Vulkan; Queue::Queue(PGraphics graphics, Gfx::QueueType queueType, uint32 familyIndex, uint32 queueIndex) - : familyIndex(familyIndex) - , graphics(graphics) - , queueType(queueType) -{ + : familyIndex(familyIndex), graphics(graphics), queueType(queueType) +{ vkGetDeviceQueue(graphics->getDevice(), familyIndex, queueIndex, &queue); } Queue::~Queue() { - } -void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore* signalSemaphores) +void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores) { assert(cmdBuffer->state == CmdBuffer::State::Ended); - + PFence fence = cmdBuffer->fence; assert(!fence->isSignaled()); @@ -38,9 +35,9 @@ void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores submitInfo.pSignalSemaphores = signalSemaphores; Array waitSemaphores; - if(cmdBuffer->waitSemaphores.size() > 0) + if (cmdBuffer->waitSemaphores.size() > 0) { - for(PSemaphore semaphore : cmdBuffer->waitSemaphores) + for (PSemaphore semaphore : cmdBuffer->waitSemaphores) { waitSemaphores.add(semaphore->getHandle()); } @@ -55,7 +52,7 @@ void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores cmdBuffer->waitFlags.clear(); cmdBuffer->waitSemaphores.clear(); - if(Gfx::waitIdleOnSubmit) + if (Gfx::waitIdleOnSubmit) { fence->wait(200 * 1000ull); } diff --git a/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp b/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp index 624f454..a2069e5 100644 --- a/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanRenderPass.cpp @@ -8,7 +8,8 @@ using namespace Seele; using namespace Seele::Vulkan; RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout) - : layout(layout), graphics(graphics) + : Gfx::RenderPass(layout) + , graphics(graphics) { Array attachments; Array inputRefs; @@ -108,17 +109,17 @@ uint32 RenderPass::getFramebufferHash() { FramebufferDescription description; std::memset(&description, 0, sizeof(FramebufferDescription)); - for(auto inputAttachment : layout->inputAttachments) + for (auto inputAttachment : layout->inputAttachments) { PTexture2D tex = inputAttachment->getTexture().cast(); description.inputAttachments[description.numInputAttachments++] = tex->getView(); } - for(auto colorAttachment : layout->colorAttachments) + for (auto colorAttachment : layout->colorAttachments) { PTexture2D tex = colorAttachment->getTexture().cast(); - description.colorAttachments[description.numColorAttachments++] = tex->getView(); + description.colorAttachments[description.numColorAttachments++] = tex->getView(); } - if(layout->depthAttachment != nullptr) + if (layout->depthAttachment != nullptr) { PTexture2D tex = layout->depthAttachment->getTexture().cast(); description.depthAttachment = tex->getView(); diff --git a/src/Engine/Graphics/Vulkan/VulkanRenderPass.h b/src/Engine/Graphics/Vulkan/VulkanRenderPass.h index 065ad2a..c8dcebf 100644 --- a/src/Engine/Graphics/Vulkan/VulkanRenderPass.h +++ b/src/Engine/Graphics/Vulkan/VulkanRenderPass.h @@ -30,13 +30,8 @@ public: { return subpassContents; } - inline Gfx::PRenderTargetLayout getLayout() - { - return layout; - } private: PGraphics graphics; - Gfx::PRenderTargetLayout layout; VkRenderPass renderPass; Array clearValues; VkRect2D renderArea; diff --git a/src/Engine/Graphics/Vulkan/VulkanShader.cpp b/src/Engine/Graphics/Vulkan/VulkanShader.cpp new file mode 100644 index 0000000..5b52311 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/VulkanShader.cpp @@ -0,0 +1,4 @@ +#include "VulkanShader.h" + +using namespace Seele; +using namespace Seele::Vulkan; \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanShader.h b/src/Engine/Graphics/Vulkan/VulkanShader.h new file mode 100644 index 0000000..341db35 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/VulkanShader.h @@ -0,0 +1,57 @@ +#pragma once +#include "VulkanGraphicsResources.h" +#include "VulkanGraphicsEnums.h" + +namespace Seele +{ +namespace Vulkan +{ + +class Shader +{ +public: + Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage); + virtual ~Shader(); + + VkShaderModule getModuleHandle() const + { + return module; + } + const char* getEntryPointName() const + { + return entryPointName.c_str(); + } +private: + VkShaderModule module; + std::string entryPointName; +}; +DEFINE_REF(Shader); + +template +class ShaderBase : public Base, public Shader +{ +public: + ShaderBase(PGraphics graphics) + : Shader(graphics, shaderType, stage) + { + } + virtual ~ShaderBase() + { + } +}; +typedef ShaderBase VertexShader; +typedef ShaderBase ControlShader; +typedef ShaderBase EvaluationShader; +typedef ShaderBase GeometryShader; +typedef ShaderBase FragmentShader; +typedef ShaderBase ComputeShader; + +DEFINE_REF(VertexShader); +DEFINE_REF(ControlShader); +DEFINE_REF(EvaluationShader); +DEFINE_REF(GeometryShader); +DEFINE_REF(FragmentShader); +DEFINE_REF(ComputeShader); + +} // namespace Vulkan +} \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp index eb43cb5..ad88444 100644 --- a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp @@ -32,7 +32,7 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format) TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ, bool bArray, uint32 arraySize, uint32 mipLevel, Gfx::SeFormat format, uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage) - : QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format)) + : QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format)), image(existingImage), layout(VK_IMAGE_LAYOUT_UNDEFINED) { if (existingImage == VK_NULL_HANDLE) { @@ -105,8 +105,13 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3 TextureHandle::~TextureHandle() { - vkDestroyImageView(graphics->getDevice(), defaultView, nullptr); - vkDestroyImage(graphics->getDevice(), image, nullptr); + auto &deletionQueue = graphics->getDeletionQueue(); + auto fence = getCommands()->getCommands()->getFence(); + VkDevice device = graphics->getDevice(); + VkImageView view = defaultView; + VkImage img = image; + deletionQueue.addPendingDelete(fence, [device, view]() { vkDestroyImageView(device, view, nullptr); }); + deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); }); } void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner) @@ -145,7 +150,7 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner) dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstManager = graphics->getTransferCommands(); } - else if(currentOwner == Gfx::QueueType::DEDICATED_TRANSFER) + else if (currentOwner == Gfx::QueueType::DEDICATED_TRANSFER) { imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; diff --git a/src/Engine/Graphics/Vulkan/VulkanViewport.cpp b/src/Engine/Graphics/Vulkan/VulkanViewport.cpp index 45f3655..eaa53e7 100644 --- a/src/Engine/Graphics/Vulkan/VulkanViewport.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanViewport.cpp @@ -9,7 +9,7 @@ using namespace Seele; using namespace Seele::Vulkan; Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo) - : Gfx::Window(createInfo), graphics(graphics), instance(graphics->getInstance()) + : Gfx::Window(createInfo), graphics(graphics), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr); @@ -19,7 +19,28 @@ Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo) glfwCreateWindowSurface(instance, handle, nullptr, &surface); - createSwapchain(); + uint32_t numQueueFamilies = 0; + vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, nullptr); + Array queueProperties(numQueueFamilies); + vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, queueProperties.data()); + + bool viableDevice = false; + for (uint32 i = 0; i < numQueueFamilies; ++i) + { + VkBool32 supportsPresent; + vkGetPhysicalDeviceSurfaceSupportKHR(graphics->getPhysicalDevice(), i, surface, &supportsPresent); + if (supportsPresent) + { + viableDevice = true; + break; + } + } + if (!viableDevice) + { + std::cerr << "Device not suitable for presenting to surface " << surface << ", use a different one" << std::endl; + } + + recreateSwapchain(createInfo); } Window::~Window() @@ -30,6 +51,7 @@ Window::~Window() void Window::beginFrame() { + glfwPollEvents(); advanceBackBuffer(); } @@ -75,16 +97,9 @@ void Window::advanceBackBuffer() imageAcquiredSemaphore = imageAcquired[semaphoreIndex]; currentImageIndex = imageIndex; - VkImageMemoryBarrier barrier = - init::ImageMemoryBarrier( - backBufferImages[currentImageIndex]->getHandle(), - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + backBufferImages[currentImageIndex]->changeLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands(); - vkCmdPipelineBarrier(cmdBuffer->getHandle(), - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - 0, 0, nullptr, 0, nullptr, 1, &barrier); - cmdBuffer->addWaitSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore); + graphics->getGraphicsCommands()->getCommands()->addWaitSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore); graphics->getGraphicsCommands()->submitCommands(); } @@ -187,7 +202,10 @@ void Window::createSwapchain() void Window::destroySwapchain() { - vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr); + if (swapchain != VK_NULL_HANDLE) + { + vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr); + } for (uint32 i = 0; i < Gfx::numFramesBuffered; ++i) { imageAcquired[i] = nullptr; diff --git a/src/Engine/Graphics/Window.cpp b/src/Engine/Graphics/Window.cpp index 35eccb9..562b618 100644 --- a/src/Engine/Graphics/Window.cpp +++ b/src/Engine/Graphics/Window.cpp @@ -7,7 +7,6 @@ Seele::Window::Window(Gfx::PWindow handle) Seele::Window::~Window() { - } void Seele::Window::addView(PView view) @@ -18,7 +17,7 @@ void Seele::Window::addView(PView view) void Seele::Window::beginFrame() { gfxHandle->beginFrame(); - for(auto view : viewports) + for (auto view : viewports) { view->beginFrame(); } @@ -26,7 +25,7 @@ void Seele::Window::beginFrame() void Seele::Window::render() { - for(auto view : viewports) + for (auto view : viewports) { view->render(); } @@ -35,7 +34,7 @@ void Seele::Window::render() void Seele::Window::endFrame() { gfxHandle->endFrame(); - for(auto view : viewports) + for (auto view : viewports) { view->endFrame(); } diff --git a/src/Engine/Graphics/Window.h b/src/Engine/Graphics/Window.h index 90d5d52..a1c53e9 100644 --- a/src/Engine/Graphics/Window.h +++ b/src/Engine/Graphics/Window.h @@ -15,9 +15,10 @@ public: void render(); void endFrame(); Gfx::PWindow getGfxHandle(); + private: Array viewports; Gfx::PWindow gfxHandle; }; DEFINE_REF(Window); -} \ No newline at end of file +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/WindowManager.cpp b/src/Engine/Graphics/WindowManager.cpp index e82f248..14291ca 100644 --- a/src/Engine/Graphics/WindowManager.cpp +++ b/src/Engine/Graphics/WindowManager.cpp @@ -24,10 +24,12 @@ Seele::WindowManager::~WindowManager() { } -void Seele::WindowManager::addWindow(const WindowCreateInfo &createInfo) +PWindow Seele::WindowManager::addWindow(const WindowCreateInfo &createInfo) { - Gfx::PWindow window = graphics->createWindow(createInfo); + Gfx::PWindow handle = graphics->createWindow(createInfo); + PWindow window = new Window(handle); windows.add(window); + return window; } void Seele::WindowManager::beginFrame() diff --git a/src/Engine/Graphics/WindowManager.h b/src/Engine/Graphics/WindowManager.h index ee5f3e3..358af0b 100644 --- a/src/Engine/Graphics/WindowManager.h +++ b/src/Engine/Graphics/WindowManager.h @@ -2,6 +2,7 @@ #include "GraphicsResources.h" #include "Graphics.h" #include "Containers/Array.h" +#include "Window.h" namespace Seele { @@ -10,16 +11,20 @@ class WindowManager public: WindowManager(); ~WindowManager(); - void addWindow(const WindowCreateInfo &createInfo); + PWindow addWindow(const WindowCreateInfo &createInfo); void beginFrame(); void endFrame(); + Gfx::PGraphics getGraphics() + { + return graphics; + } inline bool isActive() const { return windows.size(); } private: - Array windows; + Array windows; Gfx::PGraphics graphics; }; DEFINE_REF(WindowManager); diff --git a/src/Engine/Material/CMakeLists.txt b/src/Engine/Material/CMakeLists.txt new file mode 100644 index 0000000..9174620 --- /dev/null +++ b/src/Engine/Material/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(SeeleEngine + PRIVATE + Material.h + Material.cpp + MaterialInstance.h + MaterialInstance.cpp) \ No newline at end of file diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp new file mode 100644 index 0000000..e41c5ee --- /dev/null +++ b/src/Engine/Material/Material.cpp @@ -0,0 +1,37 @@ +#include "Material.h" +#include + +using namespace Seele; +using json = nlohmann::json; + +Material::Material() +{ +} + +Material::Material(const std::string& directory, const std::string& name) + : FileAsset(directory, name) +{ +} + +Material::Material(const std::string& fullPath) + : FileAsset(fullPath) +{ +} + +Material::~Material() +{ +} + +void Material::compile() +{ + auto& stream = getReadStream(); + stream.seekg(0); + json j; + stream >> j; + std::cout << j["test"] << std::endl; +} + +Gfx::PGraphicsPipeline Material::getPipeline() +{ + return pipeline; +} \ No newline at end of file diff --git a/src/Engine/Material/Material.h b/src/Engine/Material/Material.h new file mode 100644 index 0000000..3514b50 --- /dev/null +++ b/src/Engine/Material/Material.h @@ -0,0 +1,44 @@ +#pragma once +#include "MinimalEngine.h" +#include "Asset/FileAsset.h" +#include "Graphics/GraphicsResources.h" +#include + +namespace Seele +{ +struct FloatExpression +{ + float data; + std::string name; + uint32 location; +}; +struct VectorExpression +{ + Vector data; + std::string name; + uint32 location; +}; +struct TextureExpression +{ + Gfx::PTexture texture; + std::string name; + uint32 location; +}; +DECLARE_NAME_REF(Gfx, GraphicsPipeline); +DECLARE_NAME_REF(Gfx, PipelineLayout); +class Material : public FileAsset +{ +public: + Material(); + Material(const std::string &directory, const std::string &name); + Material(const std::string &fullPath); + ~Material(); + void compile(); + Gfx::PGraphicsPipeline getPipeline(); + +private: + Gfx::PGraphicsPipeline pipeline; + Gfx::PPipelineLayout pipelineLayout; +}; +DEFINE_REF(Material); +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Material/MaterialInstance.cpp b/src/Engine/Material/MaterialInstance.cpp new file mode 100644 index 0000000..b3d6821 --- /dev/null +++ b/src/Engine/Material/MaterialInstance.cpp @@ -0,0 +1,32 @@ +#include "MaterialInstance.h" +#include "Material.h" + +using namespace Seele; + +MaterialInstance::MaterialInstance() +{ +} + +MaterialInstance::MaterialInstance(const std::string& directory, const std::string& name) + : FileAsset(directory, name) +{ +} + +MaterialInstance::MaterialInstance(const std::string& fullPath) + : FileAsset(fullPath) +{ +} + +MaterialInstance::~MaterialInstance() +{ +} + +PMaterial MaterialInstance::getBaseMaterial() const +{ + return baseMaterial; +} + +Gfx::PDescriptorSet MaterialInstance::getDescriptor() +{ + return nullptr; +} \ No newline at end of file diff --git a/src/Engine/Material/MaterialInstance.h b/src/Engine/Material/MaterialInstance.h new file mode 100644 index 0000000..8e45741 --- /dev/null +++ b/src/Engine/Material/MaterialInstance.h @@ -0,0 +1,21 @@ +#pragma once +#include "Asset/FileAsset.h" + +namespace Seele +{ +DECLARE_NAME_REF(Gfx, DescriptorSet); +DECLARE_REF(Material); +class MaterialInstance : public FileAsset +{ +public: + MaterialInstance(); + MaterialInstance(const std::string& directory, const std::string& name); + MaterialInstance(const std::string& fullPath); + ~MaterialInstance(); + PMaterial getBaseMaterial() const; + Gfx::PDescriptorSet getDescriptor(); +private: + PMaterial baseMaterial; +}; +DEFINE_REF(MaterialInstance); +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Math/Math.h b/src/Engine/Math/Math.h index ae743b2..44cb866 100644 --- a/src/Engine/Math/Math.h +++ b/src/Engine/Math/Math.h @@ -1,5 +1,6 @@ #include "Vector.h" #include "Matrix.h" +#include "EngineTypes.h" namespace Seele { @@ -24,6 +25,28 @@ struct Rect Vector2 size; Vector2 offset; }; +//Unsigned int +struct URect +{ + URect() + : size(0, 0), offset(0, 0) + { + } + URect(uint32 sizeX, uint32 sizeY, uint32 offsetX, uint32 offsetY) + : size(sizeX, sizeY), offset(offsetX, offsetY) + { + } + URect(UVector2 size, UVector2 offset) + : size(size), offset(offset) + { + } + bool isEmpty() const + { + return size.x == 0 || size.y == 0; + } + UVector2 size; + UVector2 offset; +}; struct Rect3D { Vector size; diff --git a/src/Engine/Math/Transform.cpp b/src/Engine/Math/Transform.cpp index a6fc343..4913bb6 100644 --- a/src/Engine/Math/Transform.cpp +++ b/src/Engine/Math/Transform.cpp @@ -7,6 +7,19 @@ Transform::Transform() { } +Transform::Transform(Transform &&other) + : position(other.position), rotation(other.rotation), scale(scale) +{ + other.position = Vector4(0, 0, 0, 0); + other.rotation = Quaternion(0, 0, 0, 0); + other.scale = Vector4(0, 0, 0, 0); +} + +Transform::Transform(const Transform &other) + : position(other.position), rotation(other.rotation), scale(scale) +{ +} + Transform::Transform(Vector position) : position(Vector4(position, 0)), rotation(Quaternion(0, 0, 0, 0)), scale(Vector4(1, 1, 1, 0)) { @@ -26,12 +39,61 @@ Transform::Transform(Quaternion rotation, Vector scale) Transform::~Transform() { } -Vector Transform::inverseTransformPosition(const Vector& v) const +Vector Transform::inverseTransformPosition(const Vector &v) const { return (unrotateVector(rotation, v - Vector(position))) * getSafeScaleReciprocal(scale); } +Matrix4 Transform::toMatrix() +{ + Matrix4 mat; -Vector Transform::getSafeScaleReciprocal(const Vector4& inScale, float tolerance) + mat[3][0] = position.x; + mat[3][1] = position.y; + mat[3][2] = position.z; + + const float x2 = rotation.x + rotation.x; + const float y2 = rotation.y + rotation.y; + const float z2 = rotation.z + rotation.z; + { + const float xx2 = rotation.x * x2; + const float yy2 = rotation.y * y2; + const float zz2 = rotation.z * z2; + + mat[0][0] = (1.0f - (yy2 + zz2)) * scale.x; + mat[1][1] = (1.0f - (xx2 + zz2)) * scale.y; + mat[2][2] = (1.0f - (xx2 + yy2)) * scale.z; + } + + { + const float yz2 = rotation.y * z2; + const float wx2 = rotation.w * x2; + + mat[2][1] = (yz2 - wx2) * scale.z; + mat[1][2] = (yz2 + wx2) * scale.y; + } + { + const float xy2 = rotation.x * y2; + const float wz2 = rotation.w * z2; + + mat[1][0] = (xy2 - wz2) * scale.y; + mat[0][1] = (xy2 + wz2) * scale.x; + } + { + const float xz2 = rotation.x * z2; + const float wy2 = rotation.w * y2; + + mat[2][0] = (xz2 + wy2) * scale.z; + mat[0][2] = (xz2 - wy2) * scale.x; + } + + mat[0][3] = 0.0f; + mat[1][3] = 0.0f; + mat[2][3] = 0.0f; + mat[3][3] = 1.0f; + + return mat; +} +Vector Transform::getSafeScaleReciprocal(const Vector4 &inScale, float tolerance) { Vector safeReciprocalScale; if (abs(inScale.x) <= tolerance) @@ -61,24 +123,67 @@ Vector Transform::getSafeScaleReciprocal(const Vector4& inScale, float tolerance return safeReciprocalScale; } -inline Vector Transform::getPosition() const +Vector Transform::getPosition() const { return Vector(position); } -inline Quaternion Transform::getRotation() const +Quaternion Transform::getRotation() const { return rotation; } -inline Vector Transform::getScale() const +Vector Transform::getScale() const { return Vector(scale); } -inline void Transform::multiply(Transform* outTransform, const Transform* a, const Transform* b) +bool Transform::equals(const Transform &other, float tolerance) +{ + if (abs(position - other.position).length() > tolerance) + { + return false; + } + if (abs(rotation.x - other.rotation.x) <= tolerance && abs(rotation.y - other.rotation.y) <= tolerance && abs(rotation.z - other.rotation.z) <= tolerance && abs(rotation.w - other.rotation.w) <= tolerance || abs(rotation.x + other.rotation.x) <= tolerance && abs(rotation.y + other.rotation.y) <= tolerance && abs(rotation.z + other.rotation.z) <= tolerance && abs(rotation.w - other.rotation.w) <= tolerance) + { + return false; + } + if (abs(scale - other.scale).length() > tolerance) + { + return false; + } + return true; +} + +void Transform::multiply(Transform *outTransform, const Transform *a, const Transform *b) { outTransform->rotation = b->rotation * a->rotation; outTransform->position = b->position * (b->scale * a->position) + b->position; outTransform->scale = b->scale * a->scale; } + +Transform &Transform::operator=(const Transform &other) +{ + position = other.position; + rotation = other.rotation; + scale = other.scale; + return *this; +} + +Transform &Transform::operator=(Transform &&other) +{ + position = other.position; + rotation = other.rotation; + scale = other.scale; + other.position = Vector4(0, 0, 0, 0); + other.rotation = Quaternion(0, 0, 0, 0); + other.scale = Vector4(0, 0, 0, 0); + return *this; +} + +Transform &Transform::operator*(const Transform &other) const +{ + Transform outTransform; + multiply(&outTransform, this, &other); + return outTransform; +} diff --git a/src/Engine/Math/Transform.h b/src/Engine/Math/Transform.h index 7b9fb8f..285dc62 100644 --- a/src/Engine/Math/Transform.h +++ b/src/Engine/Math/Transform.h @@ -1,5 +1,6 @@ #pragma once #include "Vector.h" +#include "Matrix.h" namespace Seele { @@ -7,26 +8,27 @@ class Transform { public: Transform(); + Transform(const Transform &other); + Transform(Transform &&other); Transform(Vector position); Transform(Vector position, Quaternion rotation); Transform(Vector position, Quaternion rotation, Vector scale); Transform(Quaternion rotation, Vector scale); ~Transform(); Vector inverseTransformPosition(const Vector &v) const; - static Vector getSafeScaleReciprocal(const Vector4 &inScale, float tolerance = 0.00001f); + Matrix4 toMatrix(); + static Vector getSafeScaleReciprocal(const Vector4 &inScale, float tolerance = 0.000000001f); - inline Vector getPosition() const; - inline Quaternion getRotation() const; - inline Vector getScale() const; + Vector getPosition() const; + Quaternion getRotation() const; + Vector getScale() const; - inline static void multiply(Transform* outTransform, const Transform* a, const Transform* b); + bool equals(const Transform &other, float tolerance = 0.000000001f); + static void multiply(Transform *outTransform, const Transform *a, const Transform *b); - Transform& operator*(const Transform& other) const - { - Transform outTransform; - multiply(&outTransform, this, &other); - return outTransform; - } + Transform &operator=(const Transform &other); + Transform &operator=(Transform &&other); + Transform &operator*(const Transform &other) const; private: Vector4 position; diff --git a/src/Engine/Math/Vector.h b/src/Engine/Math/Vector.h index a4d5a02..cccafab 100644 --- a/src/Engine/Math/Vector.h +++ b/src/Engine/Math/Vector.h @@ -2,7 +2,10 @@ #include #include #include + +#pragma warning(disable : 4201) #include +#pragma warning(default : 4201) namespace Seele { typedef glm::vec2 Vector2; @@ -21,7 +24,7 @@ typedef glm::quat Quaternion; static inline float square(float x) { - return x * x; + return x * x; } static inline Vector unrotateVector(Quaternion quaternion, Vector v) @@ -32,10 +35,9 @@ static inline Vector unrotateVector(Quaternion quaternion, Vector v) return result; } -static inline bool equalsQuaternion(const Quaternion& right, const Quaternion& left, float tolerance) +static inline bool equalsQuaternion(const Quaternion &right, const Quaternion &left, float tolerance) { - return (abs(right.x - left.x) <= tolerance && abs(right.y - left.y) <= tolerance && abs(right.z - left.z) <= tolerance && abs(right.w - left.w) <= tolerance) - || (abs(right.x + left.x) <= tolerance && abs(right.y + left.y) <= tolerance && abs(right.z + left.z) <= tolerance && abs(right.w + left.w) <= tolerance); + return (abs(right.x - left.x) <= tolerance && abs(right.y - left.y) <= tolerance && abs(right.z - left.z) <= tolerance && abs(right.w - left.w) <= tolerance) || (abs(right.x + left.x) <= tolerance && abs(right.y + left.y) <= tolerance && abs(right.z + left.z) <= tolerance && abs(right.w + left.w) <= tolerance); } static inline float clampRotatorAxis(float angle) @@ -58,7 +60,7 @@ static inline float normalizeRotatorAxis(float angle) return angle; } -static inline Quaternion toQuaternion(const Vector& other) +static inline Quaternion toQuaternion(const Vector &other) { Quaternion result; const float DEG_TO_RAD = glm::pi() / (180.f); @@ -71,7 +73,7 @@ static inline Quaternion toQuaternion(const Vector& other) const float SP = sin(PitchNoWinding * RADS_DIVIDED_BY_2); const float SY = sin(YawNoWinding * RADS_DIVIDED_BY_2); const float SR = sin(RollNoWinding * RADS_DIVIDED_BY_2); - + const float CP = cos(PitchNoWinding * RADS_DIVIDED_BY_2); const float CY = cos(YawNoWinding * RADS_DIVIDED_BY_2); const float CR = cos(RollNoWinding * RADS_DIVIDED_BY_2); @@ -83,12 +85,12 @@ static inline Quaternion toQuaternion(const Vector& other) return result; } -static inline Vector toRotator(const Quaternion& other) +static inline Vector toRotator(const Quaternion &other) { const float singularityTest = other.z * other.x - other.w * other.y; const float yawY = 2.f * (other.w * other.z + other.x * other.y); const float yawX = (1.f - 2.f * (square(other.y) + square(other.z))); - + const float SINGULARITY_THRESHOLD = 0.4999995f; const float RAD_TO_DEG = (180.f) / glm::pi(); Vector rotatorFromQuat; diff --git a/src/Engine/MinimalEngine.cpp b/src/Engine/MinimalEngine.cpp index db935b3..b028685 100644 --- a/src/Engine/MinimalEngine.cpp +++ b/src/Engine/MinimalEngine.cpp @@ -1,3 +1,3 @@ #include "MinimalEngine.h" -Seele::Map registeredObjects; +Seele::Map registeredObjects; diff --git a/src/Engine/MinimalEngine.h b/src/Engine/MinimalEngine.h index 05d5059..3a5a582 100644 --- a/src/Engine/MinimalEngine.h +++ b/src/Engine/MinimalEngine.h @@ -8,302 +8,322 @@ #include "EngineTypes.h" #include "Math/Math.h" -#define DEFINE_REF(x) typedef RefPtr P##x; \ - typedef UniquePtr UP##x; \ - typedef WeakPtr W##x; +#define DEFINE_REF(x) \ + typedef RefPtr P##x; \ + typedef UniquePtr UP##x; \ + typedef WeakPtr W##x; -#define DECLARE_REF(x) class x; \ - typedef RefPtr P##x; \ - typedef UniquePtr UP##x; \ - typedef WeakPtr W##x; +#define DECLARE_REF(x) \ + class x; \ + typedef RefPtr P##x; \ + typedef UniquePtr UP##x; \ + typedef WeakPtr W##x; -extern Seele::Map registeredObjects; + +#define DECLARE_NAME_REF(nmsp, x) \ + namespace nmsp \ + { \ + class x; \ + typedef RefPtr P##x; \ + typedef UniquePtr UP##x; \ + typedef WeakPtr W##x; \ + } + +extern Seele::Map registeredObjects; namespace Seele { - template - class RefObject +template +class RefObject +{ +public: + RefObject(T *ptr) + : handle(ptr), refCount(1) { - public: - RefObject(T* ptr) - : handle(ptr) - , refCount(1) - { - registeredObjects[ptr] = this; - } - RefObject(const RefObject& rhs) - : handle(rhs.handle) - , refCount(rhs.refCount) - { - } - RefObject(RefObject&& rhs) - : handle(std::move(rhs.handle)) - , refCount(std::move(rhs.refCount)) - {} - ~RefObject() - { - registeredObjects.erase(handle); - delete handle; - } - RefObject& operator=(const RefObject& rhs) - { - if(*this != rhs) - { - handle = rhs.handle; - refCount = rhs.refCount; - } - return *this; - } - RefObject& operator=(RefObject&& rhs) - { - if(*this != rhs) - { - handle = std::move(rhs.handle); - refCount = std::move(rhs.refCount); - rhs.handle = nullptr; - rhs.refCount = 0; - } - return *this; - } - bool operator==(const RefObject& other) const - { - return handle == other.handle; - } - bool operator!=(const RefObject& other) const - { - return handle != other.handle; - } - bool operator<(const RefObject& other) const - { - return handle < other.handle; - } - void addRef() - { - refCount++; - } - void removeRef() - { - refCount--; - if (refCount.load() == 0) - { - delete this; - } - } - inline T* getHandle() const - { - return handle; - } - private: - T* handle; - std::atomic_uint64_t refCount; - }; - - - template - class RefPtr + registeredObjects[ptr] = this; + } + RefObject(const RefObject &rhs) + : handle(rhs.handle), refCount(rhs.refCount) { - public: - RefPtr() + } + RefObject(RefObject &&rhs) + : handle(std::move(rhs.handle)), refCount(std::move(rhs.refCount)) + { + } + ~RefObject() + { + registeredObjects.erase(handle); + delete handle; + } + RefObject &operator=(const RefObject &rhs) + { + if (*this != rhs) { - object = nullptr; + handle = rhs.handle; + refCount = rhs.refCount; } - RefPtr(nullptr_t) + return *this; + } + RefObject &operator=(RefObject &&rhs) + { + if (*this != rhs) { - object = nullptr; + handle = std::move(rhs.handle); + refCount = std::move(rhs.refCount); + rhs.handle = nullptr; + rhs.refCount = 0; } - RefPtr(T* ptr) + return *this; + } + bool operator==(const RefObject &other) const + { + return handle == other.handle; + } + bool operator!=(const RefObject &other) const + { + return handle != other.handle; + } + bool operator<(const RefObject &other) const + { + return handle < other.handle; + } + void addRef() + { + refCount++; + } + void removeRef() + { + refCount--; + if (refCount.load() == 0) { - auto registeredObj = registeredObjects.find(ptr); - if(registeredObj == registeredObjects.end()) - { - object = new RefObject(ptr); - } - else - { - object = (RefObject*)registeredObj->value; - } + delete this; } - explicit RefPtr(RefObject* other) - : object(other) + } + inline T *getHandle() const + { + return handle; + } + +private: + T *handle; + std::atomic_uint64_t refCount; +}; + +template +class RefPtr +{ +public: + RefPtr() + { + object = nullptr; + } + RefPtr(nullptr_t) + { + object = nullptr; + } + RefPtr(T *ptr) + { + auto registeredObj = registeredObjects.find(ptr); + if (registeredObj == registeredObjects.end()) + { + object = new RefObject(ptr); + } + else + { + object = (RefObject *)registeredObj->value; + } + } + explicit RefPtr(RefObject *other) + : object(other) + { + object->addRef(); + } + RefPtr(const RefPtr &other) + : object(other.object) + { + if (object != nullptr) { object->addRef(); } - RefPtr(const RefPtr& other) - : object(other.object) + } + RefPtr(RefPtr &&rhs) + : object(std::move(rhs.object)) + { + rhs.object = nullptr; + //Dont change references, they stay the same + } + template + RefPtr(const RefPtr &other) + { + F *f = other.getObject()->getHandle(); + static_cast(f); + object = (RefObject *)other.getObject(); + object->addRef(); + } + + template + RefPtr cast() + { + T *t = object->getHandle(); + F *f = dynamic_cast(t); + if (f == nullptr) { - if(object != nullptr) + return nullptr; + } + RefObject *newObject = (RefObject *)object; + return RefPtr(newObject); + } + + template + const RefPtr cast() const + { + T *t = object->getHandle(); + F *f = dynamic_cast(t); + if (f == nullptr) + { + return nullptr; + } + RefObject *newObject = (RefObject *)object; + return RefPtr(newObject); + } + + RefPtr &operator=(const RefPtr &other) + { + if (*this != other) + { + if (object != nullptr) + { + object->removeRef(); + } + object = other.object; + if (object != nullptr) { object->addRef(); } } - RefPtr(RefPtr&& rhs) - : object(std::move(rhs.object)) + return *this; + } + RefPtr &operator=(RefPtr &&rhs) + { + if (*this != rhs) { - rhs.object = nullptr; - //Dont change references, they stay the same - } - template - RefPtr(const RefPtr& other) - { - F* f = other.getObject()->getHandle(); - static_cast(f); - object = (RefObject*)other.getObject(); - object->addRef(); - } - - template - RefPtr cast() - { - T* t = object->getHandle(); - F* f = dynamic_cast(t); - if (f == nullptr) - { - return nullptr; - } - RefObject* newObject = (RefObject*)object; - return RefPtr(newObject); - } - - template - const RefPtr cast() const - { - T* t = object->getHandle(); - F* f = dynamic_cast(t); - if (f == nullptr) - { - return nullptr; - } - RefObject* newObject = (RefObject*)object; - return RefPtr(newObject); - } - - RefPtr& operator=(const RefPtr& other) - { - if (*this != other) - { - if (object != nullptr) - { - object->removeRef(); - } - object = other.object; - if(object != nullptr) - { - object->addRef(); - } - } - return *this; - } - RefPtr& operator=(RefPtr&& rhs) - { - if(*this != rhs) - { - if(object != nullptr) - { - object->removeRef(); - } - object = std::move(rhs.object); - rhs.object = nullptr; - } - return *this; - } - ~RefPtr() - { - if(object != nullptr) + if (object != nullptr) { object->removeRef(); } + object = std::move(rhs.object); + rhs.object = nullptr; } - bool operator==(const RefPtr& other) const - { - return object == other.object; - } - bool operator!=(const RefPtr& other) const - { - return object != other.object; - } - T* operator->() - { - assert(object != nullptr); - return object->getHandle(); - } - const T* operator->() const - { - assert(object != nullptr); - return object->getHandle(); - } - RefObject* getObject() const - { - return object; - } - T* getHandle() - { - return object->getHandle(); - } - const T* getHandle() const - { - return object->getHandle(); - } - private: - RefObject* object; - }; - //A weak pointer has no ownership over an object and thus cant delete it - template - class WeakPtr + return *this; + } + ~RefPtr() { - public: - WeakPtr() - : pointer(nullptr) - {} - WeakPtr(RefPtr& sharedPtr) - : pointer(sharedPtr) - {} - WeakPtr& operator=(WeakPtr& weakPtr) + if (object != nullptr) { - pointer = weakPtr.pointer; - return *this; + object->removeRef(); } - WeakPtr& operator=(RefPtr& sharedPtr) - { - pointer = sharedPtr; - return *this; - } - private: - RefPtr pointer; - }; - template - class UniquePtr + } + bool operator==(const RefPtr &other) const { - public: - UniquePtr(T* ptr) - : handle(ptr) - {} - UniquePtr(const UniquePtr& rhs) = delete; - UniquePtr(UniquePtr&& rhs) noexcept - : handle(rhs.handle) - { - rhs.handle = nullptr; - } - UniquePtr& operator=(const UniquePtr& rhs) = delete; - UniquePtr& operator=(UniquePtr&& rhs) - { - handle = rhs.handle; - rhs.handle = nullptr; - return *this; - } - ~UniquePtr() - { - delete handle; - } - T* operator->() - { - return handle; - } - bool isValid() - { - return handle != nullptr; - } - private: - T* handle; - }; -} + return object == other.object; + } + bool operator!=(const RefPtr &other) const + { + return object != other.object; + } + bool operator<(const RefPtr &other) const + { + return object < other.object; + } + T *operator->() + { + assert(object != nullptr); + return object->getHandle(); + } + const T *operator->() const + { + assert(object != nullptr); + return object->getHandle(); + } + RefObject *getObject() const + { + return object; + } + T *getHandle() + { + return object->getHandle(); + } + const T *getHandle() const + { + return object->getHandle(); + } + +private: + RefObject *object; +}; +//A weak pointer has no ownership over an object and thus cant delete it +template +class WeakPtr +{ +public: + WeakPtr() + : pointer(nullptr) + { + } + WeakPtr(RefPtr &sharedPtr) + : pointer(sharedPtr) + { + } + WeakPtr &operator=(WeakPtr &weakPtr) + { + pointer = weakPtr.pointer; + return *this; + } + WeakPtr &operator=(RefPtr &sharedPtr) + { + pointer = sharedPtr; + return *this; + } + +private: + RefPtr pointer; +}; +template +class UniquePtr +{ +public: + UniquePtr(T *ptr) + : handle(ptr) + { + } + UniquePtr(const UniquePtr &rhs) = delete; + UniquePtr(UniquePtr &&rhs) noexcept + : handle(rhs.handle) + { + rhs.handle = nullptr; + } + UniquePtr &operator=(const UniquePtr &rhs) = delete; + UniquePtr &operator=(UniquePtr &&rhs) + { + handle = rhs.handle; + rhs.handle = nullptr; + return *this; + } + ~UniquePtr() + { + delete handle; + } + T *operator->() + { + return handle; + } + bool isValid() + { + return handle != nullptr; + } + +private: + T *handle; +}; +} // namespace Seele using namespace Seele; \ No newline at end of file diff --git a/src/Engine/Scene/Actor/Actor.cpp b/src/Engine/Scene/Actor/Actor.cpp index c979773..806632e 100644 --- a/src/Engine/Scene/Actor/Actor.cpp +++ b/src/Engine/Scene/Actor/Actor.cpp @@ -1,5 +1,6 @@ #include "Actor.h" -#include "Component.h" +#include "Scene/Components/Component.h" +#include "Scene/Scene.h" using namespace Seele; @@ -11,6 +12,25 @@ Actor::~Actor() { } +void Actor::tick(float deltaTime) +{ + rootComponent->tick(deltaTime); + for(auto child : children) + { + child->tick(deltaTime); + } +} +void Actor::notifySceneAttach(PScene scene) +{ + owningScene = scene; + rootComponent->notifySceneAttach(scene); +} + +PScene Actor::getScene() +{ + return owningScene; +} + void Actor::setParent(PActor newParent) { parent = newParent; @@ -18,10 +38,14 @@ void Actor::setParent(PActor newParent) void Actor::addChild(PActor child) { children.add(child); + child->setParent(this); + child->notifySceneAttach(owningScene); } void Actor::detachChild(PActor child) { children.remove(children.find(child), false); + child->setParent(nullptr); + child->notifySceneAttach(nullptr); } void Actor::setWorldLocation(Vector location) { @@ -55,15 +79,16 @@ void Actor::addWorldRotation(Vector4 rotation) { rootComponent->addWorldRotation(rotation); } -void Actor::addWorldScale(Vector scale) -{ - rootComponent->addWorldScale(scale); -} PComponent Actor::getRootComponent() { return rootComponent; } void Actor::setRootComponent(PComponent newRoot) { + if(rootComponent != nullptr) + { + rootComponent->owner = nullptr; + } rootComponent = newRoot; + rootComponent->owner = this; } diff --git a/src/Engine/Scene/Actor/Actor.h b/src/Engine/Scene/Actor/Actor.h index 8586e37..0ec1de9 100644 --- a/src/Engine/Scene/Actor/Actor.h +++ b/src/Engine/Scene/Actor/Actor.h @@ -1,17 +1,22 @@ #pragma once #include "MinimalEngine.h" -#include "Transform.h" +#include "Math/Transform.h" namespace Seele { DECLARE_REF(Actor); DECLARE_REF(Component); +DECLARE_REF(Scene); class Actor { public: Actor(); virtual ~Actor(); - void setParent(PActor parent); + + void tick(float deltaTime); + void notifySceneAttach(PScene scene); + PScene getScene(); + PActor getParent(); void addChild(PActor child); void detachChild(PActor child); @@ -23,18 +28,20 @@ public: void setRelativeLocation(Vector location); void setRelativeRotation(Vector4 rotation); void setRelativeScale(Vector scale); - + void addWorldTranslation(Vector translation); void addWorldRotation(Vector4 rotation); - void addWorldScale(Vector scale); - + PComponent getRootComponent(); void setRootComponent(PComponent newRoot); + private: + void setParent(PActor parent); + PScene owningScene; PActor parent; Array children; PComponent rootComponent; Transform transform; }; DEFINE_REF(Actor); -} \ No newline at end of file +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Scene/Components/Component.cpp b/src/Engine/Scene/Components/Component.cpp index 734738d..ddda15f 100644 --- a/src/Engine/Scene/Components/Component.cpp +++ b/src/Engine/Scene/Components/Component.cpp @@ -1,4 +1,6 @@ #include "Component.h" +#include "Scene/Actor/Actor.h" +#include "Scene/Scene.h" using namespace Seele; @@ -8,58 +10,123 @@ Component::Component() Component::~Component() { } +void Component::tick(float deltaTime) +{ + for (auto child : children) + { + child->tick(deltaTime); + } +} PComponent Component::getParent() { - + return parent; } PActor Component::getOwner() { + if (owner != nullptr) + { + return owner; + } + if (parent != nullptr) + { + return parent->getOwner(); + } + return nullptr; +} +void Component::notifySceneAttach(PScene scene) +{ + owningScene = scene; + for (auto child : children) + { + child->notifySceneAttach(scene); + } } void Component::setWorldLocation(Vector location) { + Vector newRelLocation = location; + if (parent != nullptr) + { + Transform parentToWorld = getParent()->getTransform(); + newRelLocation = parentToWorld.inverseTransformPosition(location); + } + setRelativeLocation(newRelLocation); } void Component::setWorldRotation(Vector rotation) { + Vector newRelRotator = rotation; + if (parent == nullptr) + { + setRelativeRotation(rotation); + } + else + { + setWorldRotation(toQuaternion(newRelRotator)); + } } void Component::setWorldRotation(Quaternion rotation) { + Quaternion newRelRotation = getRelativeWorldRotation(rotation); + setRelativeRotation(newRelRotation); } void Component::setWorldScale(Vector scale) { + Vector newRelScale = scale; + if (parent != nullptr) + { + Transform parentToWorld = parent->getTransform(); + newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0)); + } + setRelativeScale(newRelScale); } void Component::setRelativeLocation(Vector location) { + setRelativeLocationAndRotation(location, relativeRotation); } void Component::setRelativeRotation(Vector rotation) { + setRelativeLocationAndRotation(relativeLocation, toQuaternion(rotation)); } void Component::setRelativeRotation(Quaternion rotation) { + setRelativeLocationAndRotation(relativeLocation, rotation); } void Component::setRelativeScale(Vector scale) { + if (scale != relativeScale) + { + relativeScale = scale; + updateComponentTransform(relativeRotation); + } } void Component::addWorldTranslation(Vector translation) { + const Vector newWorldLocation = translation + transform.getPosition(); + setWorldLocation(newWorldLocation); } void Component::addWorldRotation(Vector rotation) { + const Quaternion newWorldRotation = toQuaternion(rotation) * transform.getRotation(); + setWorldRotation(newWorldRotation); } void Component::addWorldRotation(Quaternion rotation) { -} -void Component::addWorldScale(Vector scale) -{ + const Quaternion newWorldRotation = rotation * transform.getRotation(); + setWorldRotation(newWorldRotation); } Transform Component::getTransform() const { return transform; } +void Component::setParent(PComponent newParent) +{ + parent = newParent; +} + void Component::internalSetTransform(Vector newLocation, Quaternion newRotation) { - if(parent != nullptr) + if (parent != nullptr) { Transform parentTransform = parent->getTransform(); newLocation = parentTransform.inverseTransformPosition(newLocation); @@ -67,7 +134,7 @@ void Component::internalSetTransform(Vector newLocation, Quaternion newRotation) } const Vector newRelRotation = toRotator(newRotation); - if(newLocation != relativeLocation || newRelRotation != relativeLocation) + if (newLocation != relativeLocation || newRelRotation != relativeLocation) { relativeLocation = newLocation; relativeRotation = newRelRotation; @@ -75,24 +142,21 @@ void Component::internalSetTransform(Vector newLocation, Quaternion newRotation) } } -void Component::propagateTransformUpdate() +void Component::propagateTransformUpdate() { - for(auto child : children) + for (auto child : children) { - if(child != nullptr) - { - child->updateComponentTransform(child->relativeRotation); - } + child->updateComponentTransform(child->relativeRotation); } } -void Component::updateComponentTransform(Quaternion relativeRotationQuat) +void Component::updateComponentTransform(Quaternion relativeRotationQuat) { - if(parent != nullptr && !parent->bComponentTransformClean) + if (parent != nullptr && !parent->bComponentTransformClean) { parent->updateComponentTransform(parent->relativeRotation); - if(bComponentTransformClean) + if (bComponentTransformClean) { return; } @@ -100,9 +164,41 @@ void Component::updateComponentTransform(Quaternion relativeRotationQuat) bComponentTransformClean = true; Transform newTransform; const Transform relTransform(relativeLocation, relativeRotationQuat, relativeScale); - if(parent != nullptr) + if (parent != nullptr) { newTransform = parent->getTransform() * relTransform; } - + bool bHasChanged = !getTransform().equals(newTransform); + if (bHasChanged) + { + transform = newTransform; + propagateTransformUpdate(); + } +} + +Quaternion Component::getRelativeWorldRotation(Quaternion worldRotation) +{ + Quaternion newRelRotation = worldRotation; + if (parent != nullptr) + { + const Transform parentToWorld = parent->getTransform(); + + const Quaternion parentToWorldQuat = parentToWorld.getRotation(); + const Quaternion newRelQuat = glm::inverse(parentToWorldQuat) * worldRotation; + newRelRotation = newRelQuat; + } + return newRelRotation; +} + +void Component::setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation) +{ + if (!bComponentTransformClean) + { + updateComponentTransform(toQuaternion(relativeRotation)); + } + + const Transform desiredRelTransform(newLocation, newRotation); + const Transform desiredWorldTransform = parent->getTransform() * desiredRelTransform; + + internalSetTransform(desiredWorldTransform.getPosition(), desiredWorldTransform.getRotation()); } diff --git a/src/Engine/Scene/Components/Component.h b/src/Engine/Scene/Components/Component.h index 930da3e..213582d 100644 --- a/src/Engine/Scene/Components/Component.h +++ b/src/Engine/Scene/Components/Component.h @@ -1,19 +1,21 @@ #pragma once #include "MinimalEngine.h" -#include "Transform.h" +#include "Math/Transform.h" namespace Seele { DECLARE_REF(Actor); +DECLARE_REF(Scene); +DECLARE_REF(Component); class Component { public: Component(); virtual ~Component(); + void tick(float deltaTime); PComponent getParent(); - void setParent(PComponent parent); PActor getOwner(); - void setOwner(PActor owner); + virtual void notifySceneAttach(PScene scene); void setWorldLocation(Vector location); void setWorldRotation(Vector rotation); @@ -24,25 +26,30 @@ public: void setRelativeRotation(Vector rotation); void setRelativeRotation(Quaternion rotation); void setRelativeScale(Vector scale); - + void addWorldTranslation(Vector translation); void addWorldRotation(Vector rotation); void addWorldRotation(Quaternion rotation); - void addWorldScale(Vector scale); Transform getTransform() const; + private: + void setParent(PComponent parent); void internalSetTransform(Vector newLocation, Quaternion newRotation); void propagateTransformUpdate(); void updateComponentTransform(Quaternion relativeRotationQuat); - uint8 bComponentTransformClean:1; + Quaternion getRelativeWorldRotation(Quaternion worldRotation); + void setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation); + uint8 bComponentTransformClean : 1; Vector relativeLocation; Vector relativeRotation; Vector relativeScale; Transform transform; + PScene owningScene; PActor owner; PComponent parent; Array children; + friend class Actor; }; DEFINE_REF(Component) -} \ No newline at end of file +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Scene/Components/PrimitiveComponent.cpp b/src/Engine/Scene/Components/PrimitiveComponent.cpp index e69de29..60ff942 100644 --- a/src/Engine/Scene/Components/PrimitiveComponent.cpp +++ b/src/Engine/Scene/Components/PrimitiveComponent.cpp @@ -0,0 +1,23 @@ +#include "PrimitiveComponent.h" +#include "Scene/Scene.h" +#include "Material/MaterialInstance.h" + +using namespace Seele; + +PrimitiveComponent::PrimitiveComponent() +{ +} + +PrimitiveComponent::~PrimitiveComponent() +{ +} + +void PrimitiveComponent::notifySceneAttach(PScene scene) +{ + scene->addPrimitiveComponent(this); +} + +Matrix4 PrimitiveComponent::getRenderMatrix() +{ + return getTransform().toMatrix(); +} diff --git a/src/Engine/Scene/Components/PrimitiveComponent.h b/src/Engine/Scene/Components/PrimitiveComponent.h index a4b1004..cbd0896 100644 --- a/src/Engine/Scene/Components/PrimitiveComponent.h +++ b/src/Engine/Scene/Components/PrimitiveComponent.h @@ -1,12 +1,23 @@ #pragma once #include "Component.h" +#include "Graphics/GraphicsResources.h" +#include "Material/MaterialInstance.h" namespace Seele { class PrimitiveComponent : public Component { public: -private: + PrimitiveComponent(); + ~PrimitiveComponent(); + virtual void notifySceneAttach(PScene scene) override; + Matrix4 getRenderMatrix(); +private: + PMaterialInstance instance; + Gfx::PVertexBuffer vertexBuffer; + Gfx::PIndexBuffer indexBuffer; + friend class Scene; }; -} \ No newline at end of file +DEFINE_REF(PrimitiveComponent); +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index e69de29..c163f22 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -0,0 +1,61 @@ +#include "Scene.h" +#include "Components/PrimitiveComponent.h" +#include "Material/MaterialInstance.h" +#include "Material/Material.h" + +using namespace Seele; + +Scene::Scene() +{ +} + +Scene::~Scene() +{ +} + +void Scene::tick(float deltaTime) +{ + for (auto actor : rootActors) + { + actor->tick(deltaTime); + } +} + +void Scene::addActor(PActor actor) +{ + rootActors.add(actor); + actor->notifySceneAttach(this); +} + +void Scene::addPrimitiveComponent(PPrimitiveComponent comp) +{ + primitives.add(comp); +} + +Map Scene::getMeshBatches() +{ + meshBatches.clear(); + for (auto primitive : primitives) + { + PMaterialInstance matInstance = primitive->instance; + PMaterial mat = matInstance->getBaseMaterial(); + DrawInstance inst; + inst.instance = primitive->instance; + inst.vertexBuffer = primitive->vertexBuffer; + inst.indexBuffer = primitive->indexBuffer; + inst.modelMatrix = primitive->getRenderMatrix(); + + if (meshBatches.find(mat) != meshBatches.end()) + { + DrawState &state = meshBatches[mat]; + state.instances.add(inst); + } + else + { + DrawState state; + state.instances.add(inst); + meshBatches[mat] = state; + } + } + return meshBatches; +} \ No newline at end of file diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index ba43cd1..d5b70b5 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -1,14 +1,28 @@ +#pragma once #include "MinimalEngine.h" #include "Actor/Actor.h" +#include "Graphics/GraphicsResources.h" +#include "Components/PrimitiveComponent.h" namespace Seele { +DECLARE_REF(Material); + class Scene { public: Scene(); ~Scene(); + void tick(float deltaTime); + void addActor(PActor actor); + void addPrimitiveComponent(PPrimitiveComponent comp); + private: + Map meshBatches; Array rootActors; + Array primitives; + +public: + Map getMeshBatches(); }; -} \ No newline at end of file +} // namespace Seele \ No newline at end of file diff --git a/test.mat b/test.mat new file mode 100644 index 0000000..c6b2d89 --- /dev/null +++ b/test.mat @@ -0,0 +1,3 @@ +{ + "test": "Hello World" +} \ No newline at end of file