From 7f1bc7d090587a7c708444ac9e5b5aa8da994dc1 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 22 Nov 2023 13:18:54 +0100 Subject: [PATCH] More mesh shading changes --- Seele.natvis | 147 ++++++++++-------- res/shaders/MeshletBasePass.slang | 60 ++++--- res/shaders/lib/MaterialParameter.slang | 18 +-- src/Editor/Asset/MeshLoader.cpp | 61 +------- src/Editor/main.cpp | 44 +++--- src/Engine/Containers/Array.h | 11 +- src/Engine/Graphics/RenderPass/BasePass.cpp | 10 +- .../Graphics/RenderPass/DepthPrepass.cpp | 9 +- src/Engine/Graphics/StaticMeshVertexData.cpp | 2 +- src/Engine/Graphics/VertexData.cpp | 132 +++++++++++++++- src/Engine/Graphics/VertexData.h | 11 +- src/Engine/Graphics/Vulkan/Allocator.cpp | 2 +- src/Engine/Graphics/Vulkan/Graphics.cpp | 23 ++- src/Engine/Graphics/Vulkan/Graphics.h | 3 +- src/Engine/Graphics/Vulkan/PipelineCache.cpp | 1 - src/Engine/Graphics/Vulkan/Window.cpp | 4 +- src/Engine/Material/MaterialInstance.cpp | 1 + src/Engine/Scene/Scene.h | 10 ++ src/Engine/System/MeshUpdater.cpp | 23 ++- src/Engine/System/MeshUpdater.h | 9 +- 20 files changed, 353 insertions(+), 228 deletions(-) diff --git a/Seele.natvis b/Seele.natvis index 2c863d3..462fe75 100644 --- a/Seele.natvis +++ b/Seele.natvis @@ -1,72 +1,81 @@ - - {{ size={arraySize} }} - - arraySize - allocated - - arraySize - _data - - - - - {{ size={_size} }} - - _size - - _size - root - next - data - - - - - [{key}, {value}] - - key - value - - - - {{ size={_size} } - - _size - comp - - _size - nodeContainer._data - - - - - [{pair}] - - pair - leftChild - rightChild - - - - empty - [{nodeContainer._data[node].pair}] - - nodeContainer._data[node].pair - - - - empty - RefPtr {*object} - - object - - - - UniquePtr {*handle} - - handle - - + + {{ size={arraySize} }} + + arraySize + allocated + + arraySize + _data + + + + + {{ size={$T2} }} + + + $T2 + _data + + + + + {{ size={_size} }} + + _size + + _size + root + next + data + + + + + [{key}, {value}] + + key + value + + + + {{ size={_size} } + + _size + comp + + _size + nodeContainer._data + + + + + [{pair}] + + pair + leftChild + rightChild + + + + empty + [{nodeContainer._data[node].pair}] + + nodeContainer._data[node].pair + + + + empty + RefPtr {*object} + + object + + + + UniquePtr {*handle} + + handle + + diff --git a/res/shaders/MeshletBasePass.slang b/res/shaders/MeshletBasePass.slang index 3d091f1..b607634 100644 --- a/res/shaders/MeshletBasePass.slang +++ b/res/shaders/MeshletBasePass.slang @@ -1,8 +1,8 @@ import Common; import BRDF; import Meshlet; -import Scene; import VertexData; +import MaterialParameter; struct MeshPayload { @@ -47,14 +47,17 @@ void taskMain( MeshData mesh = pScene.meshData[groupID]; for(uint i = threadID; i < MAX_MESHLETS_PER_MESH; i += TASK_GROUP_SIZE) { - uint m = mesh.meshletOffset + min(mesh.numMeshlets, i); - MeshletDescription meshlet = pScene.meshlets.meshletInfos[m]; - //if(meshlet.boundingBox.insideFrustum(localToClip, viewFrustum)) + if(i < mesh.numMeshlets) { - uint index; - InterlockedAdd(head, 1, index); - p.meshletId[index] = m; - p.instanceId[index] = groupID; + uint m = mesh.meshletOffset + i; + MeshletDescription meshlet = pScene.meshletInfos[m]; + //if(meshlet.boundingBox.insideFrustum(localToClip, viewFrustum)) + { + uint index; + InterlockedAdd(head, 1, index); + p.meshletId[index] = m; + p.instanceId[index] = groupID; + } } } GroupMemoryBarrierWithGroupSync(); @@ -71,6 +74,12 @@ struct PrimitiveAttributes uint cull: SV_CullPrimitive; }; +struct MeshOutput +{ + FragmentParameter parameter : PARAMETER; + float4 position_CS : SV_Position; +}; + [numthreads(MESH_GROUP_SIZE, 1, 1)] [outputtopology("triangle")] [shader("mesh")] @@ -78,7 +87,7 @@ void meshMain( in uint threadID: SV_GroupIndex, in uint groupID: SV_GroupID, in payload MeshPayload meshPayload, - out Vertices vertices, + out Vertices vertices, out Indices indices ){ InstanceData inst = pScene.instances[meshPayload.instanceId[groupID]]; @@ -92,10 +101,10 @@ void meshMain( InterlockedMax(gs_numVertices, v + 1); { int vertexIndex = pScene.vertexIndices[m.vertexOffset + v]; - gs_vertices[v] = pVertexData.getAttributes(md.indexOffset + vertexIndex, inst); + gs_vertices[v] = pVertexData.getAttributes(md.indicesOffset + vertexIndex, inst.transformMatrix); } } - + GroupMemoryBarrierWithGroupSync(); const uint primitiveLoops = (MAX_PRIMITIVES + MESH_GROUP_SIZE - 1) / MESH_GROUP_SIZE; for(uint loop = 0; loop < primitiveLoops; ++loop) { @@ -103,15 +112,12 @@ void meshMain( p = min(p, m.primitiveCount - 1); InterlockedMax(gs_numPrimitives, p + 1); { - uint8_t local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0]; - uint8_t local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1]; - uint8_t local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2]; - uint32_t idx0 = pScene.vertexIndices[m.vertexOffset + local_idx0]; - uint32_t idx1 = pScene.vertexIndices[m.vertexOffset + local_idx1]; - uint32_t idx2 = pScene.vertexIndices[m.vertexOffset + local_idx2]; - gs_indices[p * 3 + 0] = idx0; - gs_indices[p * 3 + 1] = idx1; - gs_indices[p * 3 + 2] = idx2; + uint32_t local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0]; + uint32_t local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1]; + uint32_t local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2]; + gs_indices[p].x = local_idx0; + gs_indices[p].y = local_idx1; + gs_indices[p].z = local_idx2; } } GroupMemoryBarrierWithGroupSync(); @@ -120,12 +126,16 @@ void meshMain( uint v = threadID; v = min(v, m.vertexCount - 1); - vertices[v] = gs_vertices[v]; + FragmentParameter parameter = gs_vertices[v].getParameter(inst.transformMatrix); + vertices[v].parameter = parameter; + vertices[v].position_CS = parameter.position_CS; if(vertexLoops >= 1) { uint v = threadID + MESH_GROUP_SIZE; v = min(v, m.vertexCount - 1); - vertices[v] = gs_vertices[v]; + FragmentParameter parameter = gs_vertices[v].getParameter(inst.transformMatrix); + vertices[v].parameter = parameter; + vertices[v].position_CS = parameter.position_CS; } uint p = threadID; @@ -134,19 +144,19 @@ void meshMain( if(primitiveLoops >= 1) { - uint p = threadID + MESH_GROUP_SIZE; + p += MESH_GROUP_SIZE; p = min(p, m.primitiveCount - 1); indices[p] = gs_indices[p]; } if(primitiveLoops >= 2) { - uint p = threadID + 2 * MESH_GROUP_SIZE; + p += MESH_GROUP_SIZE; p = min(p, m.primitiveCount - 1); indices[p] = gs_indices[p]; } if(primitiveLoops >= 3) { - uint p = threadID + 3 * MESH_GROUP_SIZE; + p += MESH_GROUP_SIZE; p = min(p, m.primitiveCount - 1); indices[p] = gs_indices[p]; } diff --git a/res/shaders/lib/MaterialParameter.slang b/res/shaders/lib/MaterialParameter.slang index 6284b55..81fb70a 100644 --- a/res/shaders/lib/MaterialParameter.slang +++ b/res/shaders/lib/MaterialParameter.slang @@ -20,15 +20,15 @@ struct LightingParameter // data passed to fragment shader struct FragmentParameter { - float3 position_TS; - float3 viewDir_TS; - float3 normal_WS; - float3 tangent_WS; - float3 biTangent_WS; - float3 position_WS; - float4 position_CS; - float2 texCoords; - float3 vertexColor; + float4 position_CS : SV_Position; + float3 position_TS : POSITION0; + float3 viewDir_TS : POSITION1; + float3 normal_WS : NORMAL0; + float3 tangent_WS : TANGENT0; + float3 biTangent_WS : TANGENT1; + float3 position_WS : POSITION2; + float2 texCoords : TEXCOORD0; + float3 vertexColor : COLOR0; MaterialParameter getMaterialParameter() { MaterialParameter result; diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index f804c03..a3fc41e 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -194,68 +194,9 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array meshlets; meshlets.reserve(indices.size() / (3ull * Gfx::numPrimitivesPerMeshlet)); - std::set uniqueVertices; - Meshlet current = { - .numVertices = 0, - .numPrimitives = 0, - }; - auto insertAndGetIndex = [&uniqueVertices, ¤t](uint32 index) -> int8_t - { - auto [it, inserted] = uniqueVertices.insert(index); - if (inserted) - { - if (current.numVertices == Gfx::numVerticesPerMeshlet) - { - return -1; - } - current.uniqueVertices[current.numVertices] = index; - return current.numVertices++; - } - else - { - for (uint32 i = 0; i < current.numVertices; ++i) - { - if (current.uniqueVertices[i] == index) - { - return i; - } - } - assert(false); - } - }; - auto completeMeshlet = [&meshlets, ¤t, &uniqueVertices]() { - meshlets.add(current); - current = { - .numVertices = 0, - .numPrimitives = 0, - }; - uniqueVertices.clear(); - }; - for (size_t faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) - { - auto i1 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[0]); - auto i2 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[1]); - auto i3 = insertAndGetIndex(mesh->mFaces[faceIndex].mIndices[2]); - if (i1 == -1 || i2 == -1 || i3 == -1) - { - completeMeshlet(); - } - current.primitiveLayout[current.numPrimitives * 3 + 0] = i1; - current.primitiveLayout[current.numPrimitives * 3 + 1] = i2; - current.primitiveLayout[current.numPrimitives * 3 + 2] = i3; - current.numPrimitives++; - if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet) - { - completeMeshlet(); - } - } - if (!uniqueVertices.empty()) - { - completeMeshlet(); - } + Meshlet::buildFromIndexBuffer(indices, meshlets); vertexData->loadMesh(id, meshlets); - collider.physicsMesh.addCollider(positions, indices, Matrix4(1.0f)); IndexBufferCreateInfo idxInfo; diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 19eb1eb..7ecfc79 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -37,39 +37,39 @@ int main() graphics->init(initializer); StaticMeshVertexData* vd = StaticMeshVertexData::getInstance(); vd->init(graphics); - PWindowManager windowManager = new WindowManager(); + OWindowManager windowManager = new WindowManager(); AssetRegistry::init(sourcePath / "Assets", graphics); AssetImporter::init(graphics); AssetImporter::importFont(FontImportArgs{ .filePath = "./fonts/Calibri.ttf", }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath = sourcePath / "old_resources/models/arena.fbx", - }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath = sourcePath / "old_resources/models/arena.fbx", + // }); AssetImporter::importMesh(MeshImportArgs{ .filePath = sourcePath / "old_resources/models/train.fbx", }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath= sourcePath / "old_resources/models/bird.fbx", - }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath= sourcePath / "old_resources/models/bird.fbx", + // }); AssetImporter::importMesh(MeshImportArgs{ .filePath= sourcePath / "old_resources/models/cube.fbx", }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath= sourcePath / "old_resources/models/flameThrower.fbx", - }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath= sourcePath / "old_resources/models/player.fbx", - }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath= sourcePath / "old_resources/models/shotgun.fbx", - }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath= sourcePath / "old_resources/models/track.fbx", - }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath= sourcePath / "old_resources/models/zombie.fbx", - }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath= sourcePath / "old_resources/models/flameThrower.fbx", + // }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath= sourcePath / "old_resources/models/player.fbx", + // }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath= sourcePath / "old_resources/models/shotgun.fbx", + // }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath= sourcePath / "old_resources/models/track.fbx", + // }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath= sourcePath / "old_resources/models/zombie.fbx", + // }); AssetImporter::importTexture(TextureImportArgs{ .filePath= sourcePath / "old_resources/textures/Dirt.png", diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 6af956c..1e85267 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -602,17 +602,18 @@ private: // The array is not big enough, so we make a new one T *newData = allocateArray(newSize); - // And move the current elements into that one - for(size_type i = 0; i < arraySize; ++i) - { - newData[i] = std::forward(_data[i]); - } if constexpr (std::is_integral_v || std::is_floating_point_v) { + std::memcpy(newData, _data, sizeof(T) * arraySize); std::memset(&newData[arraySize], 0, sizeof(T) * (newSize - arraySize)); } else { + // And move the current elements into that one + for(size_type i = 0; i < arraySize; ++i) + { + newData[i] = std::forward(_data[i]); + } // As well as default initialize the others for (size_type i = arraySize; i < newSize; ++i) { diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 1239f38..7b732a0 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -36,7 +36,14 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) lightCullingLayout->create(); basePassLayout->addDescriptorLayout(INDEX_LIGHT_CULLING, lightCullingLayout); - graphics->getShaderCompiler()->registerRenderPass("BasePass", "LegacyBasePass", true, true, "BasePass"); + if (graphics->supportMeshShading()) + { + graphics->getShaderCompiler()->registerRenderPass("BasePass", "MeshletBasePass", true, true, "BasePass", true, true, "MeshletBasePass"); + } + else + { + graphics->getShaderCompiler()->registerRenderPass("BasePass", "LegacyBasePass", true, true, "BasePass"); + } } BasePass::~BasePass() @@ -124,6 +131,7 @@ void BasePass::render() pipelineInfo.pipelineLayout = std::move(layout); pipelineInfo.renderPass = renderPass; pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_LESS_OR_EQUAL; + pipelineInfo.rasterizationState.lineWidth = 10.f; Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); command->bindPipeline(pipeline); } diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index 64e84c3..cead9c9 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -20,7 +20,14 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene) depthPrepassLayout = graphics->createPipelineLayout(); depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewParamsLayout); - graphics->getShaderCompiler()->registerRenderPass("DepthPass", "LegacyBasePass"); + if (graphics->supportMeshShading()) + { + graphics->getShaderCompiler()->registerRenderPass("DepthPass", "MeshletBasePass", false, false, "", true, true, "MeshletBasePass"); + } + else + { + graphics->getShaderCompiler()->registerRenderPass("DepthPass", "LegacyBasePass"); + } } DepthPrepass::~DepthPrepass() diff --git a/src/Engine/Graphics/StaticMeshVertexData.cpp b/src/Engine/Graphics/StaticMeshVertexData.cpp index ff464d7..033e5c6 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.cpp +++ b/src/Engine/Graphics/StaticMeshVertexData.cpp @@ -111,7 +111,7 @@ void StaticMeshVertexData::deserializeMesh(MeshId id, ArchiveBuffer& buffer) loadNormals(id, nor); loadTangents(id, tan); loadBiTangents(id, bit); - loadBiTangents(id, col); + loadColors(id, col); } void StaticMeshVertexData::init(Gfx::PGraphics graphics) diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 8c08735..eb79f01 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -6,10 +6,11 @@ #include "Graphics/Descriptor.h" #include "Component/Mesh.h" #include "Graphics/Shader.h" +#include using namespace Seele; -constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024; +constexpr static uint64 NUM_DEFAULT_ELEMENTS = 16 * 1024; void VertexData::resetMeshData() { @@ -17,7 +18,6 @@ void VertexData::resetMeshData() { mat.material->getDescriptorLayout()->reset(); } - materialData.clear(); if (dirty) { updateBuffers(); @@ -25,7 +25,7 @@ void VertexData::resetMeshData() } } -void VertexData::updateMesh(const Component::Transform& transform, PMesh mesh) +void VertexData::addMesh(PMesh mesh) { PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial(); MaterialData& matData = materialData[mat->getName()]; @@ -34,15 +34,66 @@ void VertexData::updateMesh(const Component::Transform& transform, PMesh mesh) matInstanceData.meshes.add(MeshInstanceData{ .id = mesh->id, .instance = InstanceData { - .transformMatrix = transform.toMatrix(), + .transformMatrix = Matrix4(), }, .indexBuffer = mesh->indexBuffer, }); matInstanceData.materialInstance = mesh->referencedMaterial->getHandle(); - matInstanceData.materialInstance->updateDescriptor(); matInstanceData.numMeshes += meshData[mesh->id].size(); } +void VertexData::removeMesh(PMesh mesh) +{ + PMaterial mat = mesh->referencedMaterial->getHandle()->getBaseMaterial(); + MaterialData& matData = materialData[mat->getName()]; + matData.material = mat; + MaterialInstanceData& matInstanceData = matData.instances[mesh->referencedMaterial->getHandle()->getId()]; + matInstanceData.meshes.remove_if([&mesh](const MeshInstanceData& data) { + return data.id == mesh->id; + }); + matInstanceData.materialInstance = mesh->referencedMaterial->getHandle(); + matInstanceData.numMeshes -= meshData[mesh->id].size(); +} + +void VertexData::updateInstances() +{ + instanceDataLayout->reset(); + for (const auto& [_, mat] : materialData) + { + for (auto& [_, matInst] : mat.instances) + { + Array instanceData; + for (auto& inst : matInst.meshes) + { + inst.meshes = 0; + for (const auto& mesh : meshData[inst.id]) + { + instanceData.add(inst.instance); + inst.meshes++; + } + } + matInst.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = { + .size = sizeof(InstanceData) * instanceData.size(), + .data = (uint8*)instanceData.data(), + }, + .numElements = instanceData.size(), + .dynamic = false, + }); + matInst.descriptorSet = instanceDataLayout->allocateDescriptorSet(); + matInst.descriptorSet->updateBuffer(0, matInst.instanceBuffer); + if (graphics->supportMeshShading()) + { + matInst.descriptorSet->updateBuffer(1, matInst.meshDataBuffer); + matInst.descriptorSet->updateBuffer(2, meshletBuffer); + matInst.descriptorSet->updateBuffer(3, primitiveIndicesBuffer); + matInst.descriptorSet->updateBuffer(4, vertexIndicesBuffer); + } + matInst.descriptorSet->writeChanges(); + } + } +} + void VertexData::createDescriptors() { instanceDataLayout->reset(); @@ -50,14 +101,12 @@ void VertexData::createDescriptors() { for (auto& [_, matInst] : mat.instances) { - Array instanceData; Array meshes; for (auto& inst : matInst.meshes) { inst.meshes = 0; for (const auto& mesh : meshData[inst.id]) { - instanceData.add(inst.instance); meshes.add(mesh); inst.meshes++; } @@ -95,6 +144,9 @@ void VertexData::createDescriptors() void VertexData::loadMesh(MeshId id, Array loadedMeshlets) { + meshlets.reserve(meshlets.size() + loadedMeshlets.size()); + vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet); + vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3); meshData[id].clear(); uint32 currentMesh = 0; while (currentMesh < loadedMeshlets.size()) @@ -239,3 +291,69 @@ void Meshlet::load(ArchiveBuffer& buffer) Serialization::load(buffer, numVertices); Serialization::load(buffer, numPrimitives); } + +void Seele::Meshlet::buildFromIndexBuffer(const Array& indices, Array& meshlets) +{ + std::set uniqueVertices; + Meshlet current = { + .numVertices = 0, + .numPrimitives = 0, + }; + auto insertAndGetIndex = [&uniqueVertices, ¤t](uint32 index) -> int8_t + { + auto [it, inserted] = uniqueVertices.insert(index); + if (inserted) + { + if (current.numVertices == Gfx::numVerticesPerMeshlet) + { + return -1; + } + current.uniqueVertices[current.numVertices] = index; + return current.numVertices++; + } + else + { + for (uint32 i = 0; i < current.numVertices; ++i) + { + if (current.uniqueVertices[i] == index) + { + return i; + } + } + assert(false); + } + }; + auto completeMeshlet = [&meshlets, ¤t, &uniqueVertices]() { + meshlets.add(current); + current = { + .numVertices = 0, + .numPrimitives = 0, + }; + uniqueVertices.clear(); + }; + for (size_t faceIndex = 0; faceIndex < indices.size() / 3; ++faceIndex) + { + auto i1 = insertAndGetIndex(indices[faceIndex * 3 + 0]); + auto i2 = insertAndGetIndex(indices[faceIndex * 3 + 1]); + auto i3 = insertAndGetIndex(indices[faceIndex * 3 + 2]); + if (i1 == -1 || i2 == -1 || i3 == -1) + { + completeMeshlet(); + i1 = insertAndGetIndex(indices[faceIndex * 3 + 0]); + i2 = insertAndGetIndex(indices[faceIndex * 3 + 1]); + i3 = insertAndGetIndex(indices[faceIndex * 3 + 2]); + } + current.primitiveLayout[current.numPrimitives * 3 + 0] = i1; + current.primitiveLayout[current.numPrimitives * 3 + 1] = i2; + current.primitiveLayout[current.numPrimitives * 3 + 2] = i3; + current.numPrimitives++; + if (current.numPrimitives == Gfx::numPrimitivesPerMeshlet) + { + completeMeshlet(); + } + } + if (!uniqueVertices.empty()) + { + completeMeshlet(); + } +} diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index 50aedb5..df6ac98 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -17,6 +17,10 @@ struct MeshId { return id <=> other.id; } + bool operator==(const MeshId& other) const + { + return id == other.id; + } }; struct Meshlet { @@ -26,6 +30,7 @@ struct Meshlet uint32 numPrimitives; void save(ArchiveBuffer& buffer) const; void load(ArchiveBuffer& buffer); + static void buildFromIndexBuffer(const Array& indices, Array& meshlets); }; class VertexData { @@ -47,7 +52,7 @@ public: Gfx::OShaderBuffer instanceBuffer; Gfx::OShaderBuffer meshDataBuffer; Gfx::PDescriptorSet descriptorSet; - uint32 numMeshes; // not necessarily equal to meshes.size() if a MeshId has multiple meshes + uint32 numMeshes = 0; // not necessarily equal to meshes.size() if a MeshId has multiple meshes Array meshes; }; struct MaterialData @@ -62,7 +67,9 @@ public: uint32 indicesOffset; }; void resetMeshData(); - void updateMesh(const Component::Transform& transform, PMesh mesh); + void addMesh(PMesh mesh); + void removeMesh(PMesh mesh); + void updateInstances(); void createDescriptors(); void loadMesh(MeshId id, Array meshlets); MeshId allocateVertexData(uint64 numVertices); diff --git a/src/Engine/Graphics/Vulkan/Allocator.cpp b/src/Engine/Graphics/Vulkan/Allocator.cpp index 300c756..72699bb 100644 --- a/src/Engine/Graphics/Vulkan/Allocator.cpp +++ b/src/Engine/Graphics/Vulkan/Allocator.cpp @@ -327,7 +327,7 @@ OStagingBuffer StagingManager::create(uint64 size) .pNext = nullptr, .flags = 0, .size = size, - .usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 1, .pQueueFamilyIndices = &queueIndex, diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 5fbd3f4..2704b7a 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -359,11 +359,15 @@ void Graphics::pickPhysicalDevice() vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()); VkPhysicalDevice bestDevice = VK_NULL_HANDLE; uint32 deviceRating = 0; + features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + features.pNext = &features12; + features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + features12.pNext = nullptr; for (auto dev : physicalDevices) { uint32 currentRating = 0; vkGetPhysicalDeviceProperties(dev, &props); - vkGetPhysicalDeviceFeatures(dev, &features); + vkGetPhysicalDeviceFeatures2(dev, &features); if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { std::cout << "found dedicated gpu " << props.deviceName << std::endl; @@ -382,8 +386,9 @@ void Graphics::pickPhysicalDevice() } } physicalDevice = bestDevice; + vkGetPhysicalDeviceProperties(physicalDevice, &props); - vkGetPhysicalDeviceFeatures(physicalDevice, &features); + vkGetPhysicalDeviceFeatures2(physicalDevice, &features); if (Gfx::useMeshShading) { uint32 count = 0; @@ -500,31 +505,25 @@ void Graphics::createDevice(GraphicsInitializer initializer) *currentPriority++ = 1.0f; } } - VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexing = { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, - .shaderSampledImageArrayNonUniformIndexing = VK_TRUE, - .descriptorBindingPartiallyBound = VK_TRUE, - .descriptorBindingVariableDescriptorCount = VK_TRUE, - .runtimeDescriptorArray = VK_TRUE, - }; VkPhysicalDeviceMeshShaderFeaturesEXT enabledMeshShaderFeatures = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT, + .pNext = nullptr, .taskShader = VK_TRUE, .meshShader = VK_TRUE, }; if (supportMeshShading()) { - descriptorIndexing.pNext = &enabledMeshShaderFeatures; + features12.pNext = &enabledMeshShaderFeatures; initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME); } VkDeviceCreateInfo deviceInfo = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = &descriptorIndexing, + .pNext = &features12, .queueCreateInfoCount = (uint32)queueInfos.size(), .pQueueCreateInfos = queueInfos.data(), .enabledExtensionCount = (uint32)initializer.deviceExtensions.size(), .ppEnabledExtensionNames = initializer.deviceExtensions.data(), - .pEnabledFeatures = &features, + .pEnabledFeatures = &features.features, }; VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle)); diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index bf13959..98e9fd5 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -91,7 +91,8 @@ protected: thread_local static OCommandPool transferCommands; thread_local static OCommandPool dedicatedTransferCommands; VkPhysicalDeviceProperties props; - VkPhysicalDeviceFeatures features; + VkPhysicalDeviceFeatures2 features; + VkPhysicalDeviceVulkan12Features features12; VkDebugReportCallbackEXT callback; Map allocatedFramebuffers; OAllocator allocator; diff --git a/src/Engine/Graphics/Vulkan/PipelineCache.cpp b/src/Engine/Graphics/Vulkan/PipelineCache.cpp index 58187a0..a55301c 100644 --- a/src/Engine/Graphics/Vulkan/PipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/PipelineCache.cpp @@ -358,7 +358,6 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo gfxI if (graphicsPipelines.contains(hash)) { - std::cout << "Caching pipeline" << std::endl; return graphicsPipelines[hash]; } VkPipeline pipelineHandle; diff --git a/src/Engine/Graphics/Vulkan/Window.cpp b/src/Engine/Graphics/Vulkan/Window.cpp index 61ab2db..e334405 100644 --- a/src/Engine/Graphics/Vulkan/Window.cpp +++ b/src/Engine/Graphics/Vulkan/Window.cpp @@ -257,14 +257,14 @@ void Window::chooseSwapSurfaceFormat() void Window::chooseSwapPresentMode() { - for (const auto& supportedPresentMode : supportedPresentModes) + /*for (const auto& supportedPresentMode : supportedPresentModes) { if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { presentMode = supportedPresentMode; return; } - } + }*/ presentMode = VK_PRESENT_MODE_FIFO_KHR; } diff --git a/src/Engine/Material/MaterialInstance.cpp b/src/Engine/Material/MaterialInstance.cpp index 99cd494..04287f6 100644 --- a/src/Engine/Material/MaterialInstance.cpp +++ b/src/Engine/Material/MaterialInstance.cpp @@ -85,6 +85,7 @@ void MaterialInstance::setBaseMaterial(PMaterialAsset asset) ); } baseMaterial = asset; + updateDescriptor(); } void MaterialInstance::save(ArchiveBuffer& buffer) const diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index 6989cc8..1b4bb67 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -44,6 +44,16 @@ public: { registry.view().each(func); } + template + auto constructCallback() + { + return registry.on_construct(); + } + template + auto destroyCallback() + { + return registry.on_destroy(); + } PLightEnvironment getLightEnvironment() { return lightEnv; } Gfx::PGraphics getGraphics() const { return graphics; } entt::registry registry; diff --git a/src/Engine/System/MeshUpdater.cpp b/src/Engine/System/MeshUpdater.cpp index d184ad1..5f9a3a4 100644 --- a/src/Engine/System/MeshUpdater.cpp +++ b/src/Engine/System/MeshUpdater.cpp @@ -4,18 +4,29 @@ using namespace Seele; using namespace Seele::System; MeshUpdater::MeshUpdater(PScene scene) - : ComponentSystem(scene) + : SystemBase(scene) { + scene->view([&](entt::entity id, Component::Mesh& mesh) { + meshEntities.add(id); + }); + scene->constructCallback().connect<&MeshUpdater::on_construct>(this); + scene->destroyCallback().connect<&MeshUpdater::on_destroy>(this); } MeshUpdater::~MeshUpdater() { } -void MeshUpdater::update(Component::Transform& transform, Component::Mesh& meshComp) +void MeshUpdater::update() { - for(const auto& mesh : meshComp.asset->meshes) - { - mesh->vertexData->updateMesh(transform, mesh); - } +} + +void MeshUpdater::on_construct(entt::registry& reg, entt::entity id) +{ + meshEntities.add(id); +} + +void MeshUpdater::on_destroy(entt::registry& reg, entt::entity id) +{ + meshEntities.remove(id, false); } diff --git a/src/Engine/System/MeshUpdater.h b/src/Engine/System/MeshUpdater.h index c9f6dee..673d0a2 100644 --- a/src/Engine/System/MeshUpdater.h +++ b/src/Engine/System/MeshUpdater.h @@ -1,5 +1,5 @@ #pragma once -#include "ComponentSystem.h" +#include "SystemBase.h" #include "Component/Transform.h" #include "Component/Mesh.h" @@ -7,13 +7,16 @@ namespace Seele { namespace System { -class MeshUpdater : public ComponentSystem +class MeshUpdater : public SystemBase { public: MeshUpdater(PScene scene); virtual ~MeshUpdater(); - virtual void update(Component::Transform& transform, Component::Mesh& mesh) override; + virtual void update() override; private: + Array meshEntities; + void on_construct(entt::registry& reg, entt::entity id); + void on_destroy(entt::registry& reg, entt::entity id); }; } // namespace System } // namespace Seele \ No newline at end of file