diff --git a/CMakeLists.txt b/CMakeLists.txt index 01e1cde..c0645ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,7 +151,7 @@ install( EXPORT EngineTargets FILE_SET HEADERS - DESTINATION ${CMAKE_INSTALL_PREFIX}/include/Seele) + DESTINATION include/Seele) export(EXPORT EngineTargets FILE "${CMAKE_BINARY_DIR}/EngineTargets.cmake" @@ -169,14 +169,14 @@ install(EXPORT EngineTargets NAMESPACE Seele:: DESTINATION - ${CMAKE_INSTALL_PREFIX}/lib/cmake/Seele + lib/cmake/Seele ) install( FILES ${CMAKE_BINARY_DIR}/SeeleConfig.cmake DESTINATION - ${CMAKE_INSTALL_PREFIX}/lib/cmake/Seele + lib/cmake/Seele ) install( @@ -186,5 +186,5 @@ install( ${CMAKE_SOURCE_DIR}/res/shaders ${CMAKE_SOURCE_DIR}/res/textures DESTINATION - ${CMAKE_INSTALL_PREFIX}/bin + bin ) diff --git a/CMakeSettings.json b/CMakeSettings.json index 800a3c7..61aeeec 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -9,14 +9,14 @@ "intelliSenseMode": "windows-msvc-x64", "inheritEnvironments": [ "msvc_x64" ], "cmakeCommandArgs": "-DCMAKE_DEBUG_POSTFIX=\"\" -DCMAKE_PLATFORM=x64", - "buildRoot": "C:/Users/Dynamitos/Seele/bin/", + "buildRoot": "C:/Users/Dynamitos/Seele/build", "installRoot": "C:/Program Files/Seele" }, { "name": "Release", "generator": "Visual Studio 17 2022 Win64", "configurationType": "Release", - "buildRoot": "C:/Users/Dynamitos/Seele/bin/", + "buildRoot": "C:/Users/Dynamitos/Seele/build/", "cmakeCommandArgs": "-DCMAKE_DEBUG_POSTFIX=\"\" -DCMAKE_PLATFORM=x64", "buildCommandArgs": "", "ctestCommandArgs": "", @@ -28,7 +28,7 @@ "name": "RelWithDebInfo", "generator": "Visual Studio 17 2022 Win64", "configurationType": "RelWithDebInfo", - "buildRoot": "C:/Users/Dynamitos/Seele/bin/", + "buildRoot": "C:/Users/Dynamitos/Seele/build/", "installRoot": "C:/Program Files/Seele", "cmakeCommandArgs": "-DCMAKE_DEBUG_POSTFIX=\"\" -DCMAKE_PLATFORM=x64", "buildCommandArgs": "", @@ -45,7 +45,7 @@ "intelliSenseMode": "windows-msvc-x64", "inheritEnvironments": [ "msvc_x64" ], "cmakeCommandArgs": "-DCMAKE_DEBUG_POSTFIX=\"\" -DCMAKE_PLATFORM=x64", - "buildRoot": "C:/Users/Dynamitos/Seele/bin/", + "buildRoot": "C:/Users/Dynamitos/Seele/build/", "installRoot": "C:/Program Files/Seele", "addressSanitizerEnabled": true } diff --git a/Culling.md b/Culling.md new file mode 100644 index 0000000..791a8f5 --- /dev/null +++ b/Culling.md @@ -0,0 +1,29 @@ +# Mesh Shading for Visibility Culling + +## Generelle TODO +- Bounding Box/Sphere intersection fix +- ~~Meshlet generation effizienter machen~~ (Index Buffer mit Tipsy optimiert) +- Vertex Attribute compression + +## Culling Ablauf + +- Erstes Frame: Alle Meshlets Drawcall +- Immer: View Frustum Culling (fertig, wenn Bounding intersection gefixt ist) +- Meshlet ID in separaten Buffer rendern +- Compute Shader über ID Buffer sammelt die Meshlets, die sichtbar waren +- Diese Meshlets wieder rendern +- Aus Depth Buffer eine Mipmap Pyramide generieren +- Im nächsten Frame: Meshlets aus ID Buffer Drawcall +- Für alle anderen Meshlets: Bounding Box/Sphere minimum Depth berechnen und mit Depth Pyramide vergleichen +- Wenn berechnete Depth < Previous, also potentiell visible: Draw call (Indirect mesh invocation aus compute shader?) + +## Evaluierung +Vergleich mit Traditioneller Vertex Pipeline +### Demo Szene +Viel Overdraw, Camera Movement was die Occlusion stark verändert (Work in Progress) +- Ich hätte mir überlegt eine Art Arena mit Säulen vorgestellt, wo die Kamera hinter den Säulen fliegt die immer wieder die Szene verdecken +- Vielleicht verändert sich die Szene nach jeder Säule für pseudo "Animationen", vielleicht nicht sinnvoll und wichtig +### Scripted Benchmark Run +Fixierter Kameraflug durch die Demo Szene, sammelt Timings und andere Statistiken und schreibt sie in eine Datei +### Platformen(optional) +Ich hätte Zugriff auf sowohl Nvidia, AMD und Apple Hardware mit Mesh Shading, und es würde Sinn machen den Unterschied Mesh-Traditionell auf allen Platformed zu vergleichen. Um Apple zu benchmarken, müsste ich ein Metal-Backend implementieren. \ No newline at end of file diff --git a/res/shaders/MeshletBasePass.slang b/res/shaders/MeshletBasePass.slang index cc57793..9c1da09 100644 --- a/res/shaders/MeshletBasePass.slang +++ b/res/shaders/MeshletBasePass.slang @@ -78,8 +78,8 @@ void meshMain( in uint threadID: SV_GroupIndex, in uint groupID: SV_GroupID, in payload MeshPayload meshPayload, - OutputVertices vertices, - OutputIndices indices + out vertices FragmentParameter vertices[MAX_VERTICES], + out indices uint3 indices[MAX_PRIMITIVES] ){ InstanceData inst = pScene.instances[meshPayload.instanceId[groupID]]; MeshData md = pScene.meshData[meshPayload.instanceId[groupID]]; diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index c871ec8..d722bab 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -194,7 +194,16 @@ void MeshLoader::loadMaterials(const aiScene* scene, const std::string& baseName .filePath = meshDirectory / outMatFilename, .importPath = importPath, }); - PMaterialAsset baseMat = AssetRegistry::findMaterial(matCode["name"].get()); + std::string materialAsset; + if (importPath.empty()) + { + materialAsset = matCode["name"].get(); + } + else + { + materialAsset = fmt::format("{0}/{1}", importPath, matCode["name"].get()); + } + PMaterialAsset baseMat = AssetRegistry::findMaterial(materialAsset); globalMaterials[i] = baseMat->instantiate(InstantiationParameter{ .name = fmt::format("{0}_Inst_0", baseMat->getName()), .folderPath = baseMat->getFolderPath(), @@ -220,6 +229,8 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const ArraymNumMeshes; ++meshIndex) { aiMesh* mesh = scene->mMeshes[meshIndex]; + if (!(mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) + continue; collider.boundingbox.adjust(Vector(mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z)); collider.boundingbox.adjust(Vector(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z)); @@ -236,10 +247,25 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const ArraymNumVertices; ++i) { positions[i] = Vector(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); - texCoords[i] = Vector2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y); + if (mesh->HasTextureCoords(0)) + { + texCoords[i] = Vector2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y); + } + else + { + texCoords[i] = Vector2(0, 0); + } normals[i] = Vector(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z); - tangents[i] = Vector(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z); - biTangents[i] = Vector(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z); + if (mesh->HasTangentsAndBitangents()) + { + tangents[i] = Vector(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z); + biTangents[i] = Vector(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z); + } + else + { + tangents[i] = Vector(0, 0, 1); + biTangents[i] = Vector(1, 0, 0); + } if(mesh->HasVertexColors(0)) { colors[i] = Vector(mesh->mColors[0][i].r, mesh->mColors[0][i].g, mesh->mColors[0][i].b); @@ -336,8 +362,9 @@ void MeshLoader::import(MeshImportArgs args, PMeshAsset meshAsset) aiProcess_GenBoundingBoxes | aiProcess_GenSmoothNormals | aiProcess_GenUVCoords | + aiProcess_SortByPType | aiProcess_FindDegenerates)); - const aiScene *scene = importer.ApplyPostProcessing(aiProcess_CalcTangentSpace | aiProcess_ImproveCacheLocality); + const aiScene *scene = importer.ApplyPostProcessing(aiProcess_CalcTangentSpace); Array globalMaterials(scene->mNumMaterials); loadTextures(scene, args.filePath.parent_path(), args.importPath); diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index c91079a..8d3b5e1 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -57,9 +57,10 @@ int main() { AssetImporter::importMesh(MeshImportArgs{ .filePath = sourcePath / "import/models/cube.fbx", }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.blend" - }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.blend", + // .importPath = "Whitechapel" + // }); WindowCreateInfo mainWindowInfo; mainWindowInfo.title = "SeeleEngine"; mainWindowInfo.width = 1920; diff --git a/src/Engine/Asset/AssetRegistry.cpp b/src/Engine/Asset/AssetRegistry.cpp index 5910283..e17ce64 100644 --- a/src/Engine/Asset/AssetRegistry.cpp +++ b/src/Engine/Asset/AssetRegistry.cpp @@ -209,9 +209,6 @@ void AssetRegistry::peekAsset(ArchiveBuffer& buffer) std::string folderPath; Serialization::load(buffer, folderPath); - uint64 assetSize; - Serialization::load(buffer, assetSize); - AssetFolder* folder = getOrCreateFolder(folderPath); OAsset asset; @@ -332,7 +329,7 @@ void AssetRegistry::saveAsset(PAsset asset, uint64 identifier, const std::filesy Serialization::save(buffer, folderPath.string()); // write asset data asset->save(buffer); - assetBuffer.writeToStream(assetStream); + buffer.writeToStream(assetStream); } std::filesystem::path AssetRegistry::getRootFolder() diff --git a/src/Engine/Asset/AssetRegistry.h b/src/Engine/Asset/AssetRegistry.h index 79e7b33..188ab43 100644 --- a/src/Engine/Asset/AssetRegistry.h +++ b/src/Engine/Asset/AssetRegistry.h @@ -74,7 +74,6 @@ private: std::filesystem::path rootFolder; AssetFolder* assetRoot; Gfx::PGraphics graphics; - ArchiveBuffer assetBuffer; bool release = false; friend class MaterialAsset; friend class TextureLoader; diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index f94abb7..317ebcb 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -18,16 +18,11 @@ static Map pendingBuffers; Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool dynamic, std::string name) : graphics(graphics), currentBuffer(0), size(size), owner(queueType), usage(usage), name(name) { - if (dynamic) { - numBuffers = Gfx::numFramesBuffered; - } else { - numBuffers = 1; - } createBuffer(); } Buffer::~Buffer() { - for (uint32 i = 0; i < numBuffers; ++i) { + for (uint32 i = 0; i < buffers.size(); ++i) { graphics->getDestructionManager()->queueBuffer(graphics->getQueueCommands(owner)->getCommands(), buffers[i].buffer, buffers[i].allocation); } @@ -74,12 +69,12 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { VkCommandBuffer srcCommand = sourcePool->getCommands()->getHandle(); VkCommandBuffer dstCommand = dstPool->getCommands()->getHandle(); VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - for (uint32 i = 0; i < numBuffers; ++i) { + for (uint32 i = 0; i < buffers.size(); ++i) { dynamicBarriers[i] = barrier; dynamicBarriers[i].buffer = buffers[i].buffer; } - vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); - vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); + vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, buffers.size(), dynamicBarriers, 0, nullptr); + vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, buffers.size(), dynamicBarriers, 0, nullptr); sourcePool->submitCommands(); } @@ -97,15 +92,14 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag .size = size, }; VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - for (uint32 i = 0; i < numBuffers; ++i) { + for (uint32 i = 0; i < buffers.size(); ++i) { dynamicBarriers[i] = barrier; dynamicBarriers[i].buffer = buffers[i].buffer; } - vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, + vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, buffers.size(), dynamicBarriers, 0, nullptr); } - void* Buffer::map(bool writeOnly) { return mapRegion(0, size, writeOnly); } void* Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) { diff --git a/src/Engine/Graphics/Vulkan/Buffer.h b/src/Engine/Graphics/Vulkan/Buffer.h index eb202aa..1cecb9e 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.h +++ b/src/Engine/Graphics/Vulkan/Buffer.h @@ -31,7 +31,6 @@ protected: Gfx::QueueType &owner; Array buffers; VkBufferUsageFlags usage; - uint32 numBuffers; std::string name; void createBuffer(); diff --git a/vcpkg.json b/vcpkg.json index d023adf..290a6b6 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -11,7 +11,6 @@ "nlohmann-json", "fmt", "gtest", - "vulkan-memory-allocator", - "shader-slang" + "vulkan-memory-allocator" ] } \ No newline at end of file