From d53492d07b5d9d9aa1f2899ae3942fb639350fa1 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Tue, 31 Oct 2023 16:16:23 +0100 Subject: [PATCH] Basic meshlet generation algorithm --- res/shaders/MeshletBasePass.slang | 3 +- res/shaders/lib/Meshlet.slang | 14 +- src/Editor/Asset/MeshLoader.cpp | 177 ++++++++++--------- src/Editor/Asset/TextureLoader.h | 2 +- src/Engine/Graphics/Enums.h | 4 + src/Engine/Graphics/Resources.h | 1 - src/Engine/Graphics/ShaderCompiler.cpp | 8 - src/Engine/Graphics/ShaderCompiler.h | 2 - src/Engine/Graphics/StaticMeshVertexData.cpp | 121 ++++++++++++- src/Engine/Graphics/StaticMeshVertexData.h | 28 +-- src/Engine/Graphics/VertexData.cpp | 39 +++- src/Engine/Graphics/VertexData.h | 28 ++- src/Engine/Scene/LightEnvironment.cpp | 51 +++++- src/Engine/Scene/LightEnvironment.h | 8 +- src/Engine/Scene/Scene.cpp | 55 +----- 15 files changed, 350 insertions(+), 191 deletions(-) diff --git a/res/shaders/MeshletBasePass.slang b/res/shaders/MeshletBasePass.slang index 11b7d94..12bd440 100644 --- a/res/shaders/MeshletBasePass.slang +++ b/res/shaders/MeshletBasePass.slang @@ -82,6 +82,7 @@ void meshMain( out Indices indices ){ InstanceData inst = scene.instances[meshPayload.instanceId[groupID]]; + MeshData md = scene.meshData[meshPayload.instanceId[groupID]]; MeshletDescription m = meshlets.meshletInfos[meshPayload.meshletId[groupID]]; const uint vertexLoops = (MAX_VERTICES + MESH_GROUP_SIZE - 1) / MESH_GROUP_SIZE; for(uint loop = 0; loop < vertexLoops; ++loop) @@ -91,7 +92,7 @@ void meshMain( InterlockedMax(gs_numVertices, v + 1); { int vertexIndex = meshlets.vertexIndices[m.vertexOffset + v]; - gs_vertices[v] = vertexData.getAttributes(vertexIndex, inst); + gs_vertices[v] = vertexData.getAttributes(md.indexOffset + vertexIndex, inst); } } diff --git a/res/shaders/lib/Meshlet.slang b/res/shaders/lib/Meshlet.slang index 5006e9f..cf7b37b 100644 --- a/res/shaders/lib/Meshlet.slang +++ b/res/shaders/lib/Meshlet.slang @@ -9,18 +9,11 @@ struct MeshletDescription uint32_t primitiveOffset; }; -struct MeshletData -{ - StructuredBuffer meshletInfos; - StructuredBuffer primitiveIndices; - - StructuredBuffer vertexIndices; -}; - struct MeshData { uint numMeshlets; uint meshletOffset; + uint indicesOffset; }; static const uint MAX_VERTICES = 64; @@ -38,7 +31,10 @@ struct Scene { StructuredBuffer instances; StructuredBuffer meshData; - StructuredBuffer meshlets; + StructuredBuffer meshletInfos; + StructuredBuffer primitiveIndices; + + StructuredBuffer vertexIndices; }; layout(set = INDEX_SCENE_DATA) diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index 57a1abc..11dde76 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -1,11 +1,11 @@ #include "MeshLoader.h" -#include "Graphics/GraphicsResources.h" #include "Graphics/Graphics.h" #include "Asset/MeshAsset.h" #include "Graphics/Mesh.h" -#include "Graphics/StaticMeshVertexInput.h" +#include "Graphics/StaticMeshVertexData.h" #include "Asset/AssetImporter.h" #include "Asset/MaterialAsset.h" +#include #include #include #include @@ -120,7 +120,6 @@ void MeshLoader::loadMaterials(const aiScene* scene, const std::string& baseName } } - void findMeshRoots(aiNode *node, List &meshNodes) { if (node->mNumMeshes > 0) @@ -133,57 +132,7 @@ void findMeshRoots(aiNode *node, List &meshNodes) findMeshRoots(node->mChildren[i], meshNodes); } } -VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics) -{ - Array buffer(size); - for(uint32 i = 0; i < size; ++i) - { - buffer[i] = Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z); - } - VertexBufferCreateInfo vbInfo; - vbInfo.numVertices = size; - vbInfo.vertexSize = sizeof(Vector); - vbInfo.resourceData.data = (uint8 *)buffer.data(); - vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; - vbInfo.resourceData.size = sizeof(Vector) * buffer.size(); - Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); - vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); - return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT); -} -VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics) -{ - Array buffer(size); - for(uint32 i = 0; i < size; ++i) - { - buffer[i] = Vector2(sourceData[i].x, sourceData[i].y); - } - VertexBufferCreateInfo vbInfo; - vbInfo.numVertices = size; - vbInfo.vertexSize = sizeof(Vector2); - vbInfo.resourceData.data = (uint8 *)buffer.data(); - vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; - vbInfo.resourceData.size = sizeof(Vector2) * buffer.size(); - Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); - vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); - return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT); -} -VertexStreamComponent createVertexStream(uint32 size, aiColor4D* sourceData, Gfx::PGraphics graphics) -{ - Array buffer(size); - for(uint32 i = 0; i < size; ++i) - { - buffer[i] = Vector4(sourceData[i].r, sourceData[i].g, sourceData[i].b, sourceData[i].a); - } - VertexBufferCreateInfo vbInfo; - vbInfo.numVertices = size; - vbInfo.vertexSize = sizeof(Vector4); - vbInfo.resourceData.data = (uint8 *)buffer.data(); - vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; - vbInfo.resourceData.size = sizeof(Vector4) * buffer.size(); - Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); - vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); - return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32A32_SFLOAT); -} + void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array& materials, Array& globalMeshes, Component::Collider& collider) { for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) @@ -192,50 +141,106 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const ArraymAABB.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)); - //! \todo duplicate from createVertexStream, clean up - Array vertices(mesh->mNumVertices); + // assume static mesh for now + Array positions(mesh->mNumVertices); + Array texCoords(mesh->mNumVertices); + Array normals(mesh->mNumVertices); + Array tangents(mesh->mNumVertices); + Array biTangents(mesh->mNumVertices); + + StaticMeshVertexData* vertexData = StaticMeshVertexData::getInstance(); + for(uint32 i = 0; i < mesh->mNumVertices; ++i) { - vertices[i] = Vector(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); + 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].x); + 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); } - PStaticMeshVertexInput vertexShaderInput = new StaticMeshVertexInput(std::string(mesh->mName.C_Str())); - StaticMeshDataType data; - data.positionStream = createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics); - - for(uint32 i = 0; i < MAX_TEXCOORDS; ++i) - { - if(mesh->HasTextureCoords(i)) - { - data.textureCoordinates[i] = createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics); - } - } - if(mesh->HasNormals()) - { - data.tangentBasisComponents[0] = createVertexStream(mesh->mNumVertices, mesh->mNormals, graphics); - } - if(mesh->HasTangentsAndBitangents()) - { - //TODO: use bitangent to calculate sign for 4th coordinate of tangentstream - data.tangentBasisComponents[1] = createVertexStream(mesh->mNumVertices, mesh->mTangents, graphics); - data.tangentBasisComponents[2] = createVertexStream(mesh->mNumVertices, mesh->mBitangents, graphics); - } - if(mesh->HasVertexColors(0)) - { - data.colorComponent = createVertexStream(mesh->mNumVertices, mesh->mColors[0], graphics); - } - vertexShaderInput->setData(std::move(data)); - vertexShaderInput->init(graphics); + MeshId id = vertexData->allocateVertexData(mesh->mNumVertices); + vertexData->loadPositions(id, positions); + vertexData->loadTexCoords(id, texCoords); + vertexData->loadNormals(id, normals); + vertexData->loadTangents(id, tangents); + vertexData->loadBiTangents(id, biTangents); Array indices(mesh->mNumFaces * 3); - for (uint32 faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) + for (size_t faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) { indices[faceIndex * 3 + 0] = mesh->mFaces[faceIndex].mIndices[0]; indices[faceIndex * 3 + 1] = mesh->mFaces[faceIndex].mIndices[1]; indices[faceIndex * 3 + 2] = mesh->mFaces[faceIndex].mIndices[2]; } - collider.physicsMesh.addCollider(vertices, indices, Matrix4(1.0f)); + if (Gfx::useMeshShading) + { + 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(); + } + } + } + else + { + // \! todo + } + + + collider.physicsMesh.addCollider(positions, indices, Matrix4(1.0f)); IndexBufferCreateInfo idxInfo; idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32; diff --git a/src/Editor/Asset/TextureLoader.h b/src/Editor/Asset/TextureLoader.h index e632cf3..59253ca 100644 --- a/src/Editor/Asset/TextureLoader.h +++ b/src/Editor/Asset/TextureLoader.h @@ -1,7 +1,7 @@ #pragma once #include "MinimalEngine.h" #include "Containers/List.h" -#include "Graphics/GraphicsEnums.h" +#include "Graphics/Enums.h" #include namespace Seele diff --git a/src/Engine/Graphics/Enums.h b/src/Engine/Graphics/Enums.h index d7e100b..15f62cb 100644 --- a/src/Engine/Graphics/Enums.h +++ b/src/Engine/Graphics/Enums.h @@ -167,6 +167,10 @@ static constexpr bool useAsyncCompute = true; static constexpr bool waitIdleOnSubmit = true; static constexpr bool useMeshShading = true; static constexpr uint32 numFramesBuffered = 8; + +// meshlet dimensions curated by NVIDIA +static constexpr uint32 numVerticesPerMeshlet = 64; +static constexpr uint32 numPrimitivesPerMeshlet = 126; double getCurrentFrameDelta(); enum class RenderPassType : uint8 diff --git a/src/Engine/Graphics/Resources.h b/src/Engine/Graphics/Resources.h index 9260568..5554944 100644 --- a/src/Engine/Graphics/Resources.h +++ b/src/Engine/Graphics/Resources.h @@ -4,7 +4,6 @@ #include "Containers/Array.h" #include "Containers/List.h" #include "Initializer.h" -#include "Buffer.h" #include "CRC.h" #include diff --git a/src/Engine/Graphics/ShaderCompiler.cpp b/src/Engine/Graphics/ShaderCompiler.cpp index a32e1e3..e5d44cb 100644 --- a/src/Engine/Graphics/ShaderCompiler.cpp +++ b/src/Engine/Graphics/ShaderCompiler.cpp @@ -15,12 +15,4 @@ ShaderCompiler::~ShaderCompiler() } -void ShaderCompiler::registerMaterial(PMaterial material) -{ - for(auto& type : VertexInputType::getTypeList()) - { - material->createShaders(graphics, Gfx::RenderPassType::DepthPrepass, type); - material->createShaders(graphics, Gfx::RenderPassType::BasePass, type); - } -} diff --git a/src/Engine/Graphics/ShaderCompiler.h b/src/Engine/Graphics/ShaderCompiler.h index 1b3fe08..b60303b 100644 --- a/src/Engine/Graphics/ShaderCompiler.h +++ b/src/Engine/Graphics/ShaderCompiler.h @@ -11,9 +11,7 @@ class ShaderCompiler public: ShaderCompiler(PGraphics graphics); ~ShaderCompiler(); - void registerMaterial(PMaterial material); private: - Array pendingCompiles; PGraphics graphics; }; DEFINE_REF(ShaderCompiler) diff --git a/src/Engine/Graphics/StaticMeshVertexData.cpp b/src/Engine/Graphics/StaticMeshVertexData.cpp index ebad999..5f3cbc1 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.cpp +++ b/src/Engine/Graphics/StaticMeshVertexData.cpp @@ -1,12 +1,15 @@ #include "StaticMeshVertexData.h" +#include "Graphics.h" using namespace Seele; extern List vertexDataList; -StaticMeshVertexData::StaticMeshVertexData(Gfx::PGraphics graphics) - : VertexData(graphics) - , head(0) +constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024; + +StaticMeshVertexData::StaticMeshVertexData() + : head(0) + , verticesAllocated(NUM_DEFAULT_ELEMENTS) { vertexDataList.add(this); } @@ -14,10 +17,120 @@ StaticMeshVertexData::StaticMeshVertexData(Gfx::PGraphics graphics) StaticMeshVertexData::~StaticMeshVertexData() {} +StaticMeshVertexData* Seele::StaticMeshVertexData::getInstance() +{ + return ; +} + MeshId StaticMeshVertexData::allocateVertexData(uint64 numVertices) { - MeshId res{idCounter++}; + MeshId res{ idCounter++ }; meshOffsets[res] = head; head += numVertices; + if (head > verticesAllocated) + { + ShaderBufferCreateInfo createInfo = { + .resourceData = { + .size = head * sizeof(Vector), + }, + .stride = sizeof(Vector), + .bDynamic = true, + }; + positions = graphics->createShaderBuffer(createInfo); + normals = graphics->createShaderBuffer(createInfo); + tangents = graphics->createShaderBuffer(createInfo); + biTangents = graphics->createShaderBuffer(createInfo); + createInfo.resourceData.size = head * sizeof(Vector2); + createInfo.stride = sizeof(Vector2); + texCoords = graphics->createShaderBuffer(createInfo); + } + positionData.resize(head); + texCoordsData.resize(head); + normalData.resize(head); + tangentData.resize(head); + biTangentData.resize(head); return res; } + +void StaticMeshVertexData::loadPositions(MeshId id, const Array& data) +{ + uint64 offset = meshOffsets[id]; + assert(offset + data.size() < head); + std::memcpy(positionData.data() + offset, data.data(), data.size() * sizeof(Vector)); + dirty = true; +} + +void StaticMeshVertexData::loadTexCoords(MeshId id, const Array& data) +{ + uint64 offset = meshOffsets[id]; + assert(offset + data.size() < head); + std::memcpy(texCoordsData.data() + offset, data.data(), data.size() * sizeof(Vector2)); + dirty = true; +} + +void StaticMeshVertexData::loadNormals(MeshId id, const Array& data) +{ + uint64 offset = meshOffsets[id]; + assert(offset + data.size() < head); + std::memcpy(normalData.data() + offset, data.data(), data.size() * sizeof(Vector)); + dirty = true; +} + +void StaticMeshVertexData::loadTangents(MeshId id, const Array& data) +{ + uint64 offset = meshOffsets[id]; + assert(offset + data.size() < head); + std::memcpy(tangentData.data() + offset, data.data(), data.size() * sizeof(Vector)); + dirty = true; +} + +void StaticMeshVertexData::loadBiTangents(MeshId id, const Array& data) +{ + uint64 offset = meshOffsets[id]; + assert(offset + data.size() < head); + std::memcpy(biTangentData.data() + offset, data.data(), data.size() * sizeof(Vector)); + dirty = true; +} + +void StaticMeshVertexData::init(Gfx::PGraphics graphics) +{ + VertexData::init(graphics); + ShaderBufferCreateInfo createInfo = { + .resourceData = { + .size = NUM_DEFAULT_ELEMENTS * sizeof(Vector), + }, + .stride = sizeof(Vector), + .bDynamic = true, + }; + positions = graphics->createShaderBuffer(createInfo); + normals = graphics->createShaderBuffer(createInfo); + tangents = graphics->createShaderBuffer(createInfo); + biTangents = graphics->createShaderBuffer(createInfo); + createInfo.resourceData.size = NUM_DEFAULT_ELEMENTS * sizeof(Vector2); + createInfo.stride = sizeof(Vector2); + texCoords = graphics->createShaderBuffer(createInfo); +} + +void StaticMeshVertexData::updateBuffers() +{ + positions->updateContents(BulkResourceData{ + .size = positionData.size() * sizeof(Vector), + .data = (uint8*)positionData.data(), + }); + texCoords->updateContents(BulkResourceData{ + .size = texCoordsData.size() * sizeof(Vector2), + .data = (uint8*)texCoordsData.data(), + }); + normals->updateContents(BulkResourceData{ + .size = normalData.size() * sizeof(Vector), + .data = (uint8*)normalData.data(), + }); + tangents->updateContents(BulkResourceData{ + .size = tangentData.size() * sizeof(Vector), + .data = (uint8*)tangentData.data(), + }); + biTangents->updateContents(BulkResourceData{ + .size = biTangentData.size() * sizeof(Vector), + .data = (uint8*)biTangentData.data(), + }); +} diff --git a/src/Engine/Graphics/StaticMeshVertexData.h b/src/Engine/Graphics/StaticMeshVertexData.h index 3385a46..a1b7f95 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.h +++ b/src/Engine/Graphics/StaticMeshVertexData.h @@ -6,26 +6,30 @@ namespace Seele class StaticMeshVertexData : public VertexData { public: - StaticMeshVertexData(Gfx::PGraphics graphics); + StaticMeshVertexData(); virtual ~StaticMeshVertexData(); + static StaticMeshVertexData* getInstance(); virtual MeshId allocateVertexData(uint64 numVertices) override; - void loadPositions(MeshId id, const Array& data); - void loadTexCoords(MeshId id, const Array& data); - void loadNormals(MeshId id, const Array& data); - void loadTangents(MeshId id, const Array& data); - void loadBiTangents(MeshId id, const Array& data); + void loadPositions(MeshId id, const Array& data); + void loadTexCoords(MeshId id, const Array& data); + void loadNormals(MeshId id, const Array& data); + void loadTangents(MeshId id, const Array& data); + void loadBiTangents(MeshId id, const Array& data); + virtual void init(Gfx::PGraphics graphics) override; private: + virtual void updateBuffers() override; Gfx::PShaderBuffer positions; - Array positionData; + Array positionData; Gfx::PShaderBuffer texCoords; - Array texCoordsData; + Array texCoordsData; Gfx::PShaderBuffer normals; - Array normalData; + Array normalData; Gfx::PShaderBuffer tangents; - Array tangentData; + Array tangentData; Gfx::PShaderBuffer biTangents; - Array biTangentData; + Array biTangentData; Map meshOffsets; - uint64 head; + uint64 head; + uint64 verticesAllocated; }; } diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index af6af5a..9141a87 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -9,6 +9,10 @@ using namespace Seele; void VertexData::resetMeshData() { materialData.clear(); + if (dirty) + { + updateBuffers(); + } } void VertexData::updateMesh(const Component::Transform& transform, const Component::Mesh& mesh) @@ -24,6 +28,30 @@ void VertexData::updateMesh(const Component::Transform& transform, const Compone }); } +void VertexData::loadMesh(MeshId id, Array meshlets) +{ + meshData[id].clear(); + uint32 head = 0; + while (head < meshlets.size()) + { + uint32 numMeshlets = std::min(512, meshlets.size() - head); + Array desc(numMeshlets); + for (uint32 i = 0; i < numMeshlets; ++i) + { + Meshlet& m = meshlets[head + i]; + + vertexIndices.resize() + desc.add(MeshletDescription{ + .boundingBox = MeshletAABB(), + .vertexCount = m.numVertices, + .primitiveCount = m.numPrimitives, + }); + } + meshData[id].add(); + head += numMeshlets; + } +} + void VertexData::createDescriptors() { for (const auto& [_, mat] : materialData) @@ -74,10 +102,9 @@ List VertexData::getList() return vertexDataList; } -VertexData::VertexData(Gfx::PGraphics graphics) - : graphics(graphics) - , idCounter(0) +void Seele::VertexData::init(Gfx::PGraphics graphics) { + this->graphics = graphics; instanceDataLayout = graphics->createDescriptorLayout("VertexDataInstanceLayout"); instanceDataLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); if (Gfx::useMeshShading) @@ -96,3 +123,9 @@ VertexData::VertexData(Gfx::PGraphics graphics) } instanceDataLayout->create(); } + +VertexData::VertexData() + : idCounter(0) + , dirty(false) +{ +} diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index f59af0e..b07b16e 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -15,6 +15,17 @@ namespace Component struct MeshId { uint64 id; + std::strong_ordering operator<=>(const MeshId& other) const + { + return id <=> other.id; + } +}; +struct Meshlet +{ + uint32 uniqueVertices[Gfx::numVerticesPerMeshlet]; // unique vertiex indices in the vertex data + uint8 primitiveLayout[Gfx::numPrimitivesPerMeshlet * 3]; // indices into the uniqueVertices array, only uint8 needed + uint32 numVertices; + uint32 numPrimitives; }; class VertexData { @@ -44,9 +55,11 @@ public: { uint32 numMeshlets; uint32 meshletOffset; + uint32 vertexOffset; }; void resetMeshData(); void updateMesh(const Component::Transform& transform, const Component::Mesh& mesh); + void loadMesh(MeshId id, Array meshlets); void createDescriptors(); virtual MeshId allocateVertexData(uint64 numVertices) = 0; virtual void bindBuffers(Gfx::PRenderCommand command) = 0; @@ -57,7 +70,10 @@ public: const Map& getMaterialData() const { return materialData; } const Array& getMeshData(MeshId id) { return meshData[id]; } static List getList(); + virtual void init(Gfx::PGraphics graphics); protected: + virtual void updateBuffers() = 0; + VertexData(); struct MeshletAABB { Vector min; @@ -65,24 +81,26 @@ protected: Vector max; float pad1; }; - struct MeshletData + struct MeshletDescription { MeshletAABB boundingBox; uint32_t vertexCount; - uint32_t primiticeCount; + uint32_t primitiveCount; uint32_t vertexOffset; uint32_t primitiveOffset; }; Map materialData; Map> meshData; - Array meshlets; - Gfx::PDescriptorLayout instanceDataLayout; + Array meshlets; + Array primitiveIndices; + Array vertexIndices; Gfx::PGraphics graphics; + Gfx::PDescriptorLayout instanceDataLayout; // for mesh shading Gfx::PShaderBuffer meshletBuffer; // for legacy pipeline Gfx::PIndexBuffer indexBuffer; - VertexData(Gfx::PGraphics graphics); uint64 idCounter; + bool dirty; }; } diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index 683a9c2..4d8a7a2 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -7,10 +7,33 @@ LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) : graphics(graphics) { layout = graphics->createDescriptorLayout("LightEnvironment"); - layout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + layout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); layout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); layout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); - layout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + layout->create(); + lightEnvBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{ + .resourceData = { + .size = sizeof(LightEnv), + .data = (uint8*) &lightEnv, + }, + .bDynamic = true, + }); + directionalLights = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .resourceData = { + .size = sizeof(Component::DirectionalLight) * MAX_DIRECTIONAL_LIGHTS, + .data = (uint8*)dirs.data(), + }, + .stride = sizeof(Component::DirectionalLight), + .bDynamic = true, + }); + pointLights = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .resourceData = { + .size = sizeof(Component::PointLight) * MAX_POINT_LIGHTS, + .data = (uint8*)dirs.data(), + }, + .stride = sizeof(Component::PointLight), + .bDynamic = true, + }); } LightEnvironment::~LightEnvironment() @@ -19,17 +42,39 @@ LightEnvironment::~LightEnvironment() void LightEnvironment::reset() { - + layout->reset(); + set = layout->allocateDescriptorSet(); + dirs.clear(); + points.clear(); } void LightEnvironment::addDirectionalLight(Component::DirectionalLight dirLight) { + dirs.add(dirLight); } void LightEnvironment::addPointLight(Component::PointLight pointLight) { + points.add(pointLight); } void LightEnvironment::commit() { + lightEnv.numDirectionalLights = dirs.size(); + lightEnv.numPointLights = points.size(); + lightEnvBuffer->updateContents(BulkResourceData{ + .size = sizeof(LightEnv), + .data = (uint8*) & lightEnv, + }); + directionalLights->updateContents(BulkResourceData{ + .size = sizeof(Component::DirectionalLight) * dirs.size(), + .data = (uint8*)dirs.data(), + }); + pointLights->updateContents(BulkResourceData{ + .size = sizeof(Component::PointLight) * points.size(), + .data = (uint8*)points.data(), + }); + set->updateBuffer(0, lightEnvBuffer); + set->updateBuffer(1, directionalLights); + set->updateBuffer(2, pointLights); } diff --git a/src/Engine/Scene/LightEnvironment.h b/src/Engine/Scene/LightEnvironment.h index 6cede36..cb21adc 100644 --- a/src/Engine/Scene/LightEnvironment.h +++ b/src/Engine/Scene/LightEnvironment.h @@ -18,10 +18,14 @@ public: private: #define MAX_DIRECTIONAL_LIGHTS 4 #define MAX_POINT_LIGHTS 256 + struct LightEnv + { + uint32 numDirectionalLights; + uint32 numPointLights; + } lightEnv; Gfx::PShaderBuffer directionalLights; - Gfx::PUniformBuffer numDirectional; + Gfx::PUniformBuffer lightEnvBuffer; Gfx::PShaderBuffer pointLights; - Gfx::PUniformBuffer numPoints;; Array dirs; Array points; Gfx::PDescriptorLayout layout; diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index c20be05..8fcef86 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -15,29 +15,8 @@ using namespace Seele; Scene::Scene(Gfx::PGraphics graphics) : graphics(graphics) , physics(registry) + , lightEnv(new LightEnvironment(graphics)) { - ShaderBufferCreateInfo structInfo = { - .resourceData = { - .size = sizeof(Component::DirectionalLight) * MAX_DIRECTIONAL_LIGHTS, - .data = nullptr, - }, - .stride = sizeof(Component::DirectionalLight), - .bDynamic = true, - }; - lightEnv.directionalLights = graphics->createShaderBuffer(structInfo); - structInfo.resourceData.size = sizeof(Component::PointLight) * MAX_POINT_LIGHTS; - structInfo.stride = sizeof(Component::PointLight); - lightEnv.pointLights = graphics->createShaderBuffer(structInfo); - - UniformBufferCreateInfo uniformInfo = { - .resourceData = { - .size = sizeof(uint32), - .data = nullptr - }, - .bDynamic = true - }; - lightEnv.numDirectional = graphics->createUniformBuffer(uniformInfo); - lightEnv.numPoints = graphics->createUniformBuffer(uniformInfo); } Scene::~Scene() @@ -49,35 +28,3 @@ void Scene::update(float deltaTime) physics.update(deltaTime); } -LightEnv Scene::getLightBuffer() -{ - StaticArray dirLights; - uint32 numDirLights = 0; - for(auto&& [entity, light] : registry.view().each()) - { - dirLights[numDirLights++] = light; - } - lightEnv.directionalLights->updateContents({ - .size = sizeof(Component::DirectionalLight) * numDirLights, - .data = (uint8*)dirLights.data(), - }); - lightEnv.numDirectional->updateContents({ - .size = sizeof(uint32), - .data = (uint8*)&numDirLights, - }); - StaticArray pointLights; - uint32 numPointLights = 0; - for(auto&& [entity, light] : registry.view().each()) - { - pointLights[numPointLights++] = light; - } - lightEnv.pointLights->updateContents({ - .size = sizeof(Component::PointLight) * numPointLights, - .data = (uint8*)pointLights.data(), - }); - lightEnv.numPoints->updateContents({ - .size = sizeof(uint32), - .data = (uint8*)&numPointLights, - }); - return lightEnv; -}