From 46a271372949cb406755c2f36cdd7171dd0daab1 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 8 May 2024 10:51:59 +0200 Subject: [PATCH] Starting framework for static mesh rendering --- res/shaders/BasePass.slang | 8 +- ...{LegacyBasePass.slang => LegacyPass.slang} | 0 ...eshletBasePass.slang => MeshletPass.slang} | 0 res/shaders/StaticMeshletPass.slang | 43 ++++ res/shaders/lib/Common.slang | 9 +- src/Editor/Asset/MeshLoader.cpp | 4 +- src/Editor/Asset/TextureLoader.cpp | 7 +- src/Editor/main.cpp | 5 +- src/Engine/Component/KeyboardInput.h | 2 + src/Engine/Component/Mesh.h | 1 + src/Engine/Graphics/Command.h | 8 +- src/Engine/Graphics/Initializer.h | 2 +- src/Engine/Graphics/RenderPass/BasePass.cpp | 232 ++++++++++++------ src/Engine/Graphics/RenderPass/BasePass.h | 15 +- src/Engine/Graphics/RenderPass/CMakeLists.txt | 6 + .../Graphics/RenderPass/DepthPrepass.cpp | 190 ++++++-------- src/Engine/Graphics/RenderPass/DepthPrepass.h | 10 - .../Graphics/RenderPass/LightCullingPass.h | 1 - .../Graphics/RenderPass/StaticBasePass.cpp | 0 .../Graphics/RenderPass/StaticBasePass.h | 0 .../RenderPass/StaticDepthPrepass.cpp | 165 +++++++++++++ .../Graphics/RenderPass/StaticDepthPrepass.h | 24 ++ src/Engine/Graphics/StaticMeshVertexData.cpp | 38 +++ src/Engine/Graphics/StaticMeshVertexData.h | 10 + src/Engine/Graphics/VertexData.cpp | 118 +++++---- src/Engine/Graphics/VertexData.h | 27 +- src/Engine/Graphics/Vulkan/Command.cpp | 16 +- src/Engine/Graphics/Vulkan/Command.h | 8 +- src/Engine/System/KeyboardInput.cpp | 10 + src/Engine/System/KeyboardInput.h | 3 + src/Engine/Window/GameView.cpp | 3 +- 31 files changed, 645 insertions(+), 320 deletions(-) rename res/shaders/{LegacyBasePass.slang => LegacyPass.slang} (100%) rename res/shaders/{MeshletBasePass.slang => MeshletPass.slang} (100%) create mode 100644 res/shaders/StaticMeshletPass.slang create mode 100644 src/Engine/Graphics/RenderPass/StaticBasePass.cpp create mode 100644 src/Engine/Graphics/RenderPass/StaticBasePass.h create mode 100644 src/Engine/Graphics/RenderPass/StaticDepthPrepass.cpp create mode 100644 src/Engine/Graphics/RenderPass/StaticDepthPrepass.h diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index 25f0f7b..0bffada 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -26,12 +26,12 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target { result += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf); } - for(uint i = 0; i < lightCount; ++i) + for(uint i = 0; i < pLightEnv.numPointLights; ++i) { - uint lightIndex = pLightCullingData.lightIndexList[startOffset + i]; - result += pLightEnv.pointLights[lightIndex].illuminate(lightingParams, brdf); + //uint lightIndex = pLightCullingData.lightIndexList[startOffset + i]; + result += pLightEnv.pointLights[i].illuminate(lightingParams, brdf); } - result += brdf.evaluateAmbient(); + //result += brdf.evaluateAmbient(); // gamma correction result = result / (result + float3(1.0)); result = pow(result, float3(1.0/2.2)); diff --git a/res/shaders/LegacyBasePass.slang b/res/shaders/LegacyPass.slang similarity index 100% rename from res/shaders/LegacyBasePass.slang rename to res/shaders/LegacyPass.slang diff --git a/res/shaders/MeshletBasePass.slang b/res/shaders/MeshletPass.slang similarity index 100% rename from res/shaders/MeshletBasePass.slang rename to res/shaders/MeshletPass.slang diff --git a/res/shaders/StaticMeshletPass.slang b/res/shaders/StaticMeshletPass.slang new file mode 100644 index 0000000..9e2eecc --- /dev/null +++ b/res/shaders/StaticMeshletPass.slang @@ -0,0 +1,43 @@ +import Common; +import BRDF; +import Scene; +import VertexData; +import MaterialParameter; + +struct PrimitiveAttributes +{ + uint cull: SV_CullPrimitive; +}; + +[numthreads(MESH_GROUP_SIZE, 1, 1)] +[outputtopology("triangle")] +[shader("mesh")] +void meshMain( + in uint threadID: SV_GroupIndex, + in uint groupID: SV_GroupID, + out vertices FragmentParameter vertices[MAX_VERTICES], + out indices uint3 indices[MAX_PRIMITIVES] +){ + MeshletDescription m = pScene.meshletInfos[groupID]; + SetMeshOutputCounts(m.vertexCount, m.primitiveCount); + + for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE) + { + uint p = min(i, m.primitiveCount - 1); + { + uint local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0]; + uint local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1]; + uint local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2]; + indices[p] = uint3(local_idx0, local_idx1, local_idx2); + } + } + for(uint i = threadID; i < MAX_VERTICES; i+=MESH_GROUP_SIZE) + { + uint v = min(i, m.vertexCount - 1); + { + uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v]; + VertexAttributes attr = pVertexData.getAttributes(md.indicesOffset + vertexIndex); + vertices[v] = attr.getParameter(float4x4(1.0)); + } + } +} \ No newline at end of file diff --git a/res/shaders/lib/Common.slang b/res/shaders/lib/Common.slang index 54df6ff..728434a 100644 --- a/res/shaders/lib/Common.slang +++ b/res/shaders/lib/Common.slang @@ -58,11 +58,16 @@ float4 screenToView(float4 screen) return clipToView(clip); } -float4 screenToModel(float4x4 inverseTransform, float4 screen) +float4 screenToWorld(float4 screen) { float4 view = screenToView(screen); - float4 world = viewToWorld(view); + return viewToWorld(view); +} + +float4 screenToModel(float4x4 inverseTransform, float4 screen) +{ + float4 world = screenToWorld(screen); return worldToModel(inverseTransform, world); } diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index 2348a64..a7f06b2 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -69,6 +69,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& texPath = (meshDirectory / texPath).replace_extension("png"); if (tex->mHeight == 0) { + std::cout << "Dumping texture " << texPath << std::endl; // already compressed, just dump it to the disk std::ofstream file(texPath, std::ios::binary); file.write((const char*)tex->pcData, tex->mWidth); @@ -76,6 +77,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& } else { + std::cout << "Writing extracted png " << texPath << std::endl; // recompress data so that the TextureLoader can read it unsigned char* texData = new unsigned char[tex->mWidth * tex->mHeight * 4]; convertAssimpARGB(texData, tex->pcData, tex->mWidth * tex->mHeight); @@ -412,8 +414,8 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array& case aiShadingMode_Toon: brdf.profile = "CelShading"; break; - case aiShadingMode_CookTorrance: default: + case aiShadingMode_CookTorrance: brdf.profile = "CookTorrance"; brdf.variables["roughness"] = outputRoughness; brdf.variables["metallic"] = outputMetallic; diff --git a/src/Editor/Asset/TextureLoader.cpp b/src/Editor/Asset/TextureLoader.cpp index e832ddd..b4fdcc3 100644 --- a/src/Editor/Asset/TextureLoader.cpp +++ b/src/Editor/Asset/TextureLoader.cpp @@ -61,7 +61,12 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) auto ktxFile = args.filePath; ktxFile.replace_extension("ktx"); std::stringstream ss; - ss << "toktx --encode etc1s " << ktxFile << " " << args.filePath; + ss << "toktx --encode etc1s "; + if (args.type == TextureImportType::TEXTURE_NORMAL) + { + ss << "--normal_mode "; + } + ss << ktxFile << " " << args.filePath; system(ss.str().c_str()); args.filePath = ktxFile; } diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 0f8751c..ad267c4 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -58,15 +58,12 @@ int main() { AssetImporter::importMesh(MeshImportArgs{ .filePath = sourcePath / "import/models/cube.fbx", }); - //AssetImporter::importMesh(MeshImportArgs{ - // .filePath = sourcePath / "import/models/Arissa.fbx", - // }); AssetImporter::importMesh(MeshImportArgs{ .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb", .importPath = "Whitechapel" }); //AssetImporter::importMesh(MeshImportArgs{ - // .filePath = sourcePath / "import/models/Volvo S90/Volvo S90.fbx", + // .filePath = sourcePath / "import/models/Volvo S90/Volvo S90.blend", // .importPath = "Volvo", // }); WindowCreateInfo mainWindowInfo; diff --git a/src/Engine/Component/KeyboardInput.h b/src/Engine/Component/KeyboardInput.h index 48adb0e..cbf83ff 100644 --- a/src/Engine/Component/KeyboardInput.h +++ b/src/Engine/Component/KeyboardInput.h @@ -14,6 +14,8 @@ struct KeyboardInput float mouseY; float deltaX; float deltaY; + float scrollX; + float scrollY; }; } // namespace Component } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Component/Mesh.h b/src/Engine/Component/Mesh.h index 5fad93f..8e3c6f8 100644 --- a/src/Engine/Component/Mesh.h +++ b/src/Engine/Component/Mesh.h @@ -8,6 +8,7 @@ namespace Component struct Mesh { PMeshAsset asset; + bool isStatic = true; }; } // namespace Component } // namespace Seele diff --git a/src/Engine/Graphics/Command.h b/src/Engine/Graphics/Command.h index ab6705c..c2cf7c8 100644 --- a/src/Engine/Graphics/Command.h +++ b/src/Engine/Graphics/Command.h @@ -14,8 +14,8 @@ public: virtual ~RenderCommand(); virtual void setViewport(Gfx::PViewport viewport) = 0; virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0; - virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0; - virtual void bindDescriptor(const Array& sets) = 0; + virtual void bindDescriptor(Gfx::PDescriptorSet set, Array dynamicOffsets = {}) = 0; + virtual void bindDescriptor(const Array& sets, Array dynamicOffsets = {}) = 0; virtual void bindVertexBuffer(const Array& buffer) = 0; virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0; virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0; @@ -31,8 +31,8 @@ public: ComputeCommand(); virtual ~ComputeCommand(); virtual void bindPipeline(Gfx::PComputePipeline pipeline) = 0; - virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0; - virtual void bindDescriptor(const Array& sets) = 0; + virtual void bindDescriptor(Gfx::PDescriptorSet set, Array dynamicOffsets = {}) = 0; + virtual void bindDescriptor(const Array& sets, Array dynamicOffsets = {}) = 0; virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0; virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) = 0; std::string name; diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 5be5bef..95e1202 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -24,7 +24,7 @@ struct GraphicsInitializer : applicationName("SeeleEngine") , engineName("SeeleEngine") , windowLayoutFile(nullptr) - , layers{} + , layers{"VK_LAYER_LUNARG_monitor"} , instanceExtensions{} , deviceExtensions{"VK_KHR_swapchain"} , windowHandle(nullptr) diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index d818907..490feaa 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -12,12 +12,12 @@ #include "Material/MaterialInstance.h" #include "Graphics/Descriptor.h" #include "Graphics/Command.h" +#include "Graphics/StaticMeshVertexData.h" using namespace Seele; BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) - , descriptorSets(6) { } @@ -56,85 +56,77 @@ void BasePass::render() opaqueCulling->writeChanges(); transparentCulling->writeChanges(); - Gfx::ShaderPermutation permutation; - if (graphics->supportMeshShading()) - { - permutation.setTaskFile("MeshletBasePass"); - permutation.setMeshFile("MeshletBasePass"); - } - else - { - permutation.setVertexFile("LegacyBasePass"); - } - permutation.setFragmentFile("BasePass"); graphics->beginRenderPass(renderPass); Array commands; - for (VertexData* vertexData : VertexData::getList()) + // Static Meshes { - permutation.setVertexData(vertexData->getTypeName()); - const auto& materials = vertexData->getMaterialData(); - for (const auto& [_, materialData] : materials) + Gfx::ShaderPermutation permutation; + if (graphics->supportMeshShading()) { - // Create Pipeline(Material, VertexData) - // Descriptors: - // ViewData => global, static - // VertexData => per meshtype - // SceneData => per material instance - // LightEnv => provided by scene - // Material => per material - // LightCulling => calculated by pass - permutation.setMaterial(materialData.material->getName()); - Gfx::PermutationId id(permutation); + permutation.setTaskFile("StaticMeshletPass"); + permutation.setMeshFile("StaticMeshletPass"); + } + else + { + permutation.setVertexFile("StaticLegacyPass"); + } + permutation.setFragmentFile("BasePass"); + StaticMeshVertexData* vd = StaticMeshVertexData::getInstance(); + permutation.setVertexData(vd->getTypeName()); + for (const auto& [_, mappings] : vd->getStaticMeshes()) + { + for (const auto& mapping : mappings) + { + permutation.setMaterial(mapping.material->getBaseMaterial()->getName()); + Gfx::PermutationId id(permutation); - Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender"); - command->setViewport(viewport); + Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender"); + command->setViewport(viewport); - const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); - assert(collection != nullptr); - if (graphics->supportMeshShading()) - { - Gfx::MeshPipelineCreateInfo pipelineInfo; - pipelineInfo.taskShader = collection->taskShader; - pipelineInfo.meshShader = collection->meshShader; - pipelineInfo.fragmentShader = collection->fragmentShader; - pipelineInfo.pipelineLayout = collection->pipelineLayout; - pipelineInfo.renderPass = renderPass; - pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; - pipelineInfo.multisampleState.samples = viewport->getSamples(); - pipelineInfo.colorBlend.attachmentCount = 1; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } - else - { - Gfx::LegacyPipelineCreateInfo pipelineInfo; - pipelineInfo.vertexShader = collection->vertexShader; - pipelineInfo.fragmentShader = collection->fragmentShader; - pipelineInfo.pipelineLayout = collection->pipelineLayout; - pipelineInfo.renderPass = renderPass; - pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; - pipelineInfo.multisampleState.samples = viewport->getSamples(); - pipelineInfo.colorBlend.attachmentCount = 1; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } - command->bindDescriptor(vertexData->getVertexDataSet()); - command->bindDescriptor(viewParamsSet); - command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet()); - command->bindDescriptor(opaqueCulling); - for (const auto& [_, instance] : materialData.instances) - { - command->bindDescriptor(instance.materialInstance->getDescriptorSet()); - command->bindDescriptor(instance.descriptorSet); + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); if (graphics->supportMeshShading()) { - command->drawMesh(instance.meshes.size(), 1, 1); + Gfx::MeshPipelineCreateInfo pipelineInfo; + pipelineInfo.taskShader = collection->taskShader; + pipelineInfo.meshShader = collection->meshShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); } else { - command->bindIndexBuffer(vertexData->getIndexBuffer()); + Gfx::LegacyPipelineCreateInfo pipelineInfo; + pipelineInfo.vertexShader = collection->vertexShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor(vd->getVertexDataSet()); + command->bindDescriptor(viewParamsSet); + command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet()); + command->bindDescriptor(opaqueCulling); + command->bindDescriptor(mapping.material->getDescriptorSet()); + command->bindDescriptor(vd->getInstanceDataSet(), {0, 0}); + if (graphics->supportMeshShading()) + { + command->drawMesh(vd->getMeshData(mapping.mapped).size(), 1, 1); + } + else + { + command->bindIndexBuffer(vd->getIndexBuffer()); uint32 instanceOffset = 0; - for (const auto& [instance, meshData] : instance.meshes) + for (const auto& meshData : vd->getMeshData(mapping.mapped)) { if (meshData.numIndices > 0) { @@ -143,10 +135,104 @@ void BasePass::render() instanceOffset++; } } + + commands.add(std::move(command)); } - commands.add(std::move(command)); } } + // Others + { + Gfx::ShaderPermutation permutation; + if (graphics->supportMeshShading()) + { + permutation.setTaskFile("MeshletPass"); + permutation.setMeshFile("MeshletPass"); + } + else + { + permutation.setVertexFile("LegacyPass"); + } + permutation.setFragmentFile("BasePass"); + for (VertexData* vertexData : VertexData::getList()) + { + permutation.setVertexData(vertexData->getTypeName()); + const auto& materials = vertexData->getMaterialData(); + for (const auto& [_, materialData] : materials) + { + // Create Pipeline(Material, VertexData) + // Descriptors: + // ViewData => global, static + // VertexData => per meshtype + // SceneData => per material instance + // LightEnv => provided by scene + // Material => per material + // LightCulling => calculated by pass + permutation.setMaterial(materialData.material->getName()); + Gfx::PermutationId id(permutation); + + Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender"); + command->setViewport(viewport); + + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); + if (graphics->supportMeshShading()) + { + Gfx::MeshPipelineCreateInfo pipelineInfo; + pipelineInfo.taskShader = collection->taskShader; + pipelineInfo.meshShader = collection->meshShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + else + { + Gfx::LegacyPipelineCreateInfo pipelineInfo; + pipelineInfo.vertexShader = collection->vertexShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor(vertexData->getVertexDataSet()); + command->bindDescriptor(viewParamsSet); + command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet()); + command->bindDescriptor(opaqueCulling); + for (const auto& [_, instance] : materialData.instances) + { + command->bindDescriptor(instance.materialInstance->getDescriptorSet()); + command->bindDescriptor(vertexData->getInstanceDataSet(), {instance.descriptorOffset, instance.descriptorOffset}); + if (graphics->supportMeshShading()) + { + command->drawMesh(vertexData->getMeshData(instance.meshId).size(), 1, 1); + } + else + { + command->bindIndexBuffer(vertexData->getIndexBuffer()); + uint32 instanceOffset = 0; + for (const auto& meshData : vertexData->getMeshData(instance.meshId)) + { + if (meshData.numIndices > 0) + { + command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset); + } + instanceOffset++; + } + } + } + commands.add(std::move(command)); + } + } + } + graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); } @@ -177,18 +263,20 @@ void BasePass::publishOutputs() if (graphics->supportMeshShading()) { - graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletBasePass", true, true, "BasePass", true, true, "MeshletBasePass"); + graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletPass", true, true, "BasePass", true, true, "MeshBasePass"); + graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "StaticBasePass", "StaticMeshletPass", true, true, "BasePass", true, true, "StaticMeshletPass"); } else { - graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "LegacyBasePass", true, true, "BasePass"); + graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "LegacyPass", true, true, "BasePass"); + graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "StaticBasePass", "StaticLegacyPass", true, true, "BasePass"); } } void BasePass::createRenderPass() { depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH"); - depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR); + depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index 7ed0528..be71986 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -17,7 +17,6 @@ public: virtual void endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; - static void modifyRenderPassMacros(Map& defines); private: Gfx::RenderTargetAttachment colorAttachment; Gfx::RenderTargetAttachment depthAttachment; @@ -28,22 +27,10 @@ private: Gfx::PDescriptorSet opaqueCulling; Gfx::PDescriptorSet transparentCulling; - Array descriptorSets; + //Array descriptorSets; PCameraActor source; Gfx::OPipelineLayout basePassLayout; - // Set 0: viewParameter, provided by renderpass - static constexpr uint32 INDEX_VIEW_PARAMS = 0; - // Set 1: vertex buffers, provided by vertexdata - static constexpr uint32 INDEX_VERTEX_DATA = 1; - // Set 2: instance data, provided by vertexdata - static constexpr uint32 INDEX_SCENE_DATA = 2; - // Set 3: light environment, provided by lightenv - static constexpr uint32 INDEX_LIGHT_ENV = 3; - // Set 4: material data, generated from material - static constexpr uint32 INDEX_MATERIAL = 4; - // Set 5: light culling data Gfx::ODescriptorLayout lightCullingLayout; - static constexpr uint32 INDEX_LIGHT_CULLING = 5; }; DEFINE_REF(BasePass) } // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/CMakeLists.txt b/src/Engine/Graphics/RenderPass/CMakeLists.txt index d721e48..2bf1ec2 100644 --- a/src/Engine/Graphics/RenderPass/CMakeLists.txt +++ b/src/Engine/Graphics/RenderPass/CMakeLists.txt @@ -15,6 +15,10 @@ target_sources(Engine RenderPass.cpp SkyboxRenderPass.h SkyboxRenderPass.cpp + StaticDepthPrepass.h + StaticDepthPrepass.cpp + StaticBasePass.h + StaticBasePass.cpp TextPass.h TextPass.cpp UIPass.h @@ -31,5 +35,7 @@ target_sources(Engine RenderGraphResources.h RenderPass.h SkyboxRenderPass.h + StaticDepthPrepass.h + StaticBasePass.h TextPass.h UIPass.h) \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index f0d936b..9c7be0a 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -9,22 +9,22 @@ #include "Math/Vector.h" #include "RenderGraph.h" #include "Graphics/Command.h" +#include "Graphics/StaticMeshVertexData.h" using namespace Seele; DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) - , descriptorSets(3) { depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout"); depthPrepassLayout->addDescriptorLayout(viewParamsLayout); if (graphics->supportMeshShading()) { - graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletBasePass", false, false, "", true, true, "MeshletBasePass"); + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletPass", false, false, "", true, true, "MeshletPass"); } else { - graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyBasePass"); + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass"); } } @@ -35,95 +35,99 @@ DepthPrepass::~DepthPrepass() void DepthPrepass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); - descriptorSets[INDEX_VIEW_PARAMS] = viewParamsSet; } void DepthPrepass::render() { - Gfx::ShaderPermutation permutation; - if(graphics->supportMeshShading()) - { - permutation.setTaskFile("MeshletBasePass"); - permutation.setMeshFile("MeshletBasePass"); - } - else - { - permutation.setVertexFile("LegacyBasePass"); - } graphics->beginRenderPass(renderPass); Array commands; - for (VertexData* vertexData : VertexData::getList()) + + // Others { - permutation.setVertexData(vertexData->getTypeName()); - const auto& materials = vertexData->getMaterialData(); - for (const auto& [_, materialData] : materials) + Gfx::ShaderPermutation permutation; + if (graphics->supportMeshShading()) { - // Create Pipeline(Material, VertexData) - // Descriptors: - // ViewData => global, static - // Material => per material - // VertexData => per meshtype - // SceneData => per material instance - Gfx::PermutationId id(permutation); - - Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender"); - command->setViewport(viewport); - - const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); - assert(collection != nullptr); - if(graphics->supportMeshShading()) + permutation.setTaskFile("MeshletPass"); + permutation.setMeshFile("MeshletPass"); + } + else + { + permutation.setVertexFile("LegacyPass"); + } + for (VertexData* vertexData : VertexData::getList()) + { + permutation.setVertexData(vertexData->getTypeName()); + const auto& materials = vertexData->getMaterialData(); + for (const auto& [_, materialData] : materials) { - Gfx::MeshPipelineCreateInfo pipelineInfo; - pipelineInfo.taskShader = collection->taskShader; - pipelineInfo.meshShader = collection->meshShader; - pipelineInfo.fragmentShader = collection->fragmentShader; - pipelineInfo.pipelineLayout = collection->pipelineLayout; - pipelineInfo.renderPass = renderPass; - pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER; - pipelineInfo.multisampleState.samples = viewport->getSamples(); - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } - else - { - Gfx::LegacyPipelineCreateInfo pipelineInfo; - pipelineInfo.vertexShader = collection->vertexShader; - pipelineInfo.fragmentShader = collection->fragmentShader; - pipelineInfo.pipelineLayout = collection->pipelineLayout; - pipelineInfo.renderPass = renderPass; - //pipelineInfo.depthStencilState.depthWriteEnable = false; - pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER; - pipelineInfo.multisampleState.samples = viewport->getSamples(); - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } + // Create Pipeline(VertexData) + // Descriptors: + // ViewData => global, static + // VertexData => per meshtype + // SceneData => per material instance + permutation.setMaterial(materialData.material->getName()); + Gfx::PermutationId id(permutation); - descriptorSets[INDEX_VERTEX_DATA] = vertexData->getVertexDataSet(); - for (const auto& [_, instance] : materialData.instances) - { - //descriptorSets[INDEX_MATERIAL] = instance.materialInstance->getDescriptorSet(); - descriptorSets[INDEX_SCENE_DATA] = instance.descriptorSet; - command->bindDescriptor(descriptorSets); + Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender"); + command->setViewport(viewport); + + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); if (graphics->supportMeshShading()) { - command->drawMesh(instance.meshes.size(), 1, 1); + Gfx::MeshPipelineCreateInfo pipelineInfo; + pipelineInfo.taskShader = collection->taskShader; + pipelineInfo.meshShader = collection->meshShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); } else { - command->bindIndexBuffer(vertexData->getIndexBuffer()); - uint32 instanceOffset = 0; - for (const auto& [_, meshData] : instance.meshes) + Gfx::LegacyPipelineCreateInfo pipelineInfo; + pipelineInfo.vertexShader = collection->vertexShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor(vertexData->getVertexDataSet()); + command->bindDescriptor(viewParamsSet); + for (const auto& [_, instance] : materialData.instances) + { + command->bindDescriptor(vertexData->getInstanceDataSet(), { instance.descriptorOffset, instance.descriptorOffset }); + if (graphics->supportMeshShading()) { - if (meshData.numIndices > 0) + command->drawMesh(vertexData->getMeshData(instance.meshId).size(), 1, 1); + } + else + { + command->bindIndexBuffer(vertexData->getIndexBuffer()); + uint32 instanceOffset = 0; + for (const auto& meshData : vertexData->getMeshData(instance.meshId)) { - command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset++); + if (meshData.numIndices > 0) + { + command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset); + } + instanceOffset++; } } } + commands.add(std::move(command)); } - commands.add(std::move(command)); } } + graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); } @@ -134,56 +138,8 @@ void DepthPrepass::endFrame() void DepthPrepass::publishOutputs() { - // If we render to a part of an image, the depth buffer itself must - // still match the size of the whole image or their coordinate systems go out of sync - TextureCreateInfo depthBufferInfo = { - .format = Gfx::SE_FORMAT_D32_SFLOAT, - .width = viewport->getOwner()->getFramebufferWidth(), - .height = viewport->getOwner()->getFramebufferHeight(), - .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - }; - depthBuffer = graphics->createTexture2D(depthBufferInfo); - depthAttachment = - Gfx::RenderTargetAttachment(depthBuffer, - Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_GENERAL, - Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); - resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment); } void DepthPrepass::createRenderPass() -{ - Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ - .depthAttachment = depthAttachment, - }; - Array dependency = { - { - .srcSubpass = ~0U, - .dstSubpass = 0, - .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - }, - { - .srcSubpass = 0, - .dstSubpass = ~0U, - .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, - }, - { - .srcSubpass = 0, - .dstSubpass = ~0U, - .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, - } - }; - renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport); -} - -void DepthPrepass::modifyRenderPassMacros(Map&) { } diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.h b/src/Engine/Graphics/RenderPass/DepthPrepass.h index a15e0c1..ffeac57 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -16,20 +16,10 @@ public: virtual void endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; - static void modifyRenderPassMacros(Map& defines); private: Gfx::RenderTargetAttachment depthAttachment; Gfx::OTexture2D depthBuffer; - - Array descriptorSets; - Gfx::OPipelineLayout depthPrepassLayout; - // Set 0: viewParameter - static constexpr uint32 INDEX_VIEW_PARAMS = 0; - // Set 0: vertices, from VertexData - constexpr static uint32 INDEX_VERTEX_DATA = 1; - // Set 2: mesh data, either index buffer or meshlet data - constexpr static uint32 INDEX_SCENE_DATA = 2; Gfx::ODescriptorLayout sceneDataLayout; }; DEFINE_REF(DepthPrepass) diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index cce2715..5fe6a2e 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -20,7 +20,6 @@ public: virtual void endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; - static void modifyRenderPassMacros(Map& defines); private: void setupFrustums(); static constexpr uint32 BLOCK_SIZE = 32; diff --git a/src/Engine/Graphics/RenderPass/StaticBasePass.cpp b/src/Engine/Graphics/RenderPass/StaticBasePass.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/Engine/Graphics/RenderPass/StaticBasePass.h b/src/Engine/Graphics/RenderPass/StaticBasePass.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Engine/Graphics/RenderPass/StaticDepthPrepass.cpp b/src/Engine/Graphics/RenderPass/StaticDepthPrepass.cpp new file mode 100644 index 0000000..09da9a8 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/StaticDepthPrepass.cpp @@ -0,0 +1,165 @@ +#include "StaticDepthPrepass.h" +#include "Graphics/StaticMeshVertexData.h" +#include "Graphics/Shader.h" + +using namespace Seele; + +StaticDepthPrepass::StaticDepthPrepass(Gfx::PGraphics graphics, PScene scene) + : RenderPass(graphics, scene) +{ + depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout"); + depthPrepassLayout->addDescriptorLayout(viewParamsLayout); + if (graphics->supportMeshShading()) + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletPass", false, false, "", true, true, "MeshletPass"); + } + else + { + graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass"); + } +} + +StaticDepthPrepass::~StaticDepthPrepass() +{ +} + +void StaticDepthPrepass::beginFrame(const Component::Camera& cam) +{ + RenderPass::beginFrame(cam); +} + +void StaticDepthPrepass::render() +{ + // Static Meshes + { + Gfx::ShaderPermutation permutation; + if (graphics->supportMeshShading()) + { + permutation.setTaskFile("StaticMeshletPass"); + permutation.setMeshFile("StaticMeshletPass"); + } + else + { + permutation.setVertexFile("LegacyPass"); + } + StaticMeshVertexData* vd = StaticMeshVertexData::getInstance(); + permutation.setVertexData(vd->getTypeName()); + for (const auto& [_, mappings] : vd->) + { + permutation.setMaterial(mapping.material->getBaseMaterial()->getName()); + Gfx::PermutationId id(permutation); + + Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender"); + command->setViewport(viewport); + + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); + if (graphics->supportMeshShading()) + { + Gfx::MeshPipelineCreateInfo pipelineInfo; + pipelineInfo.taskShader = collection->taskShader; + pipelineInfo.meshShader = collection->meshShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + else + { + Gfx::LegacyPipelineCreateInfo pipelineInfo; + pipelineInfo.vertexShader = collection->vertexShader; + pipelineInfo.fragmentShader = collection->fragmentShader; + pipelineInfo.pipelineLayout = collection->pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; + pipelineInfo.multisampleState.samples = viewport->getSamples(); + pipelineInfo.colorBlend.attachmentCount = 1; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor(viewParamsSet); + command->bindDescriptor(vd->getVertexDataSet()); + command->bindDescriptor(vd->getInstanceDataSet(), { 0, 0 }); + if (graphics->supportMeshShading()) + { + command->drawMesh(vd->getMeshData(mapping.mapped).size(), 1, 1); + } + else + { + command->bindIndexBuffer(vd->getIndexBuffer()); + uint32 instanceOffset = 0; + for (const auto& meshData : vd->getMeshData(mapping.mapped)) + { + if (meshData.numIndices > 0) + { + command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset); + } + instanceOffset++; + } + } + + commands.add(std::move(command)); + } + } + } +} + +void StaticDepthPrepass::endFrame() +{ +} + +void StaticDepthPrepass::publishOutputs() +{ + // If we render to a part of an image, the depth buffer itself must + // still match the size of the whole image or their coordinate systems go out of sync + TextureCreateInfo depthBufferInfo = { + .format = Gfx::SE_FORMAT_D32_SFLOAT, + .width = viewport->getOwner()->getFramebufferWidth(), + .height = viewport->getOwner()->getFramebufferHeight(), + .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + }; + depthBuffer = graphics->createTexture2D(depthBufferInfo); + depthAttachment = + Gfx::RenderTargetAttachment(depthBuffer, + Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_GENERAL, + Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); + resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment); +} + +void StaticDepthPrepass::createRenderPass() +{ + Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ + .depthAttachment = depthAttachment, + }; + Array dependency = { + { + .srcSubpass = ~0U, + .dstSubpass = 0, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + } + }; + renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport); +} diff --git a/src/Engine/Graphics/RenderPass/StaticDepthPrepass.h b/src/Engine/Graphics/RenderPass/StaticDepthPrepass.h new file mode 100644 index 0000000..6f2fa1b --- /dev/null +++ b/src/Engine/Graphics/RenderPass/StaticDepthPrepass.h @@ -0,0 +1,24 @@ +#pragma once +#include "RenderPass.h" + +namespace Seele +{ +class StaticDepthPrepass : public RenderPass +{ +public: + StaticDepthPrepass(Gfx::PGraphics graphics, PScene scene); + StaticDepthPrepass(StaticDepthPrepass&&) = default; + StaticDepthPrepass& operator=(StaticDepthPrepass&&) = default; + virtual ~StaticDepthPrepass(); + virtual void beginFrame(const Component::Camera& cam) override; + virtual void render() override; + virtual void endFrame() override; + virtual void publishOutputs() override; + virtual void createRenderPass() override; +private: + Gfx::RenderTargetAttachment depthAttachment; + Gfx::OTexture2D depthBuffer; + Gfx::OPipelineLayout depthPrepassLayout; + Gfx::ODescriptorLayout sceneDataLayout; +}; +} \ No newline at end of file diff --git a/src/Engine/Graphics/StaticMeshVertexData.cpp b/src/Engine/Graphics/StaticMeshVertexData.cpp index 4c303b4..fb47e09 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.cpp +++ b/src/Engine/Graphics/StaticMeshVertexData.cpp @@ -1,6 +1,7 @@ #include "StaticMeshVertexData.h" #include "Graphics.h" #include "Graphics/Enums.h" +#include "Mesh.h" using namespace Seele; @@ -192,6 +193,43 @@ Gfx::PDescriptorSet StaticMeshVertexData::getVertexDataSet() return descriptorSet; } +void StaticMeshVertexData::registerStaticMesh(entt::entity id, const Array& meshes, const Component::Transform& transform) +{ + std::unique_lock l(vertexDataLock); + std::unique_lock l2(mutex); + for (auto& mesh : meshes) + { + uint64 numVertices = meshVertexCounts[mesh->id]; + uint64 offset = meshOffsets[mesh->id]; + MeshId mapped = VertexData::allocateVertexData(numVertices); + Array pos(numVertices); + Matrix4 matrix = transform.toMatrix(); + for (uint64 i = 0; i < numVertices; ++i) + { + pos[i] = matrix * Vector4(positionData[offset + i], 1); + } + loadPositions(mapped, pos); + Array tex(numVertices); + for (size_t i = 0; i < MAX_TEXCOORDS; ++i) + { + std::memcpy(tex.data(), texCoordsData[i].data() + offset, numVertices * sizeof(Vector2)); + loadTexCoords(mapped, i, tex); + } + Array aux(numVertices); + std::memcpy(aux.data(), normalData.data() + offset, numVertices * sizeof(Vector)); + loadNormals(mapped, aux); + std::memcpy(aux.data(), biTangentData.data() + offset, numVertices * sizeof(Vector)); + loadBiTangents(mapped, aux); + std::memcpy(aux.data(), colorData.data() + offset, numVertices * sizeof(Vector)); + loadColors(mapped, aux); + staticMeshes[id].add(StaticMeshMapping{ + .original = mesh->id, + .mapped = mapped, + .material = mesh->referencedMaterial->getHandle(), + }); + } +} + void StaticMeshVertexData::resizeBuffers() { ShaderBufferCreateInfo createInfo = { diff --git a/src/Engine/Graphics/StaticMeshVertexData.h b/src/Engine/Graphics/StaticMeshVertexData.h index 45f58ae..20696fd 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.h +++ b/src/Engine/Graphics/StaticMeshVertexData.h @@ -3,12 +3,19 @@ #include "Graphics/Command.h" #include "Math/Vector.h" #include "VertexData.h" +#include "entt/entt.hpp" namespace Seele { class StaticMeshVertexData : public VertexData { public: + struct StaticMeshMapping + { + MeshId original; + MeshId mapped; + PMaterialInstance material; + }; StaticMeshVertexData(); virtual ~StaticMeshVertexData(); static StaticMeshVertexData* getInstance(); @@ -26,9 +33,12 @@ public: virtual Gfx::PDescriptorLayout getVertexDataLayout() override; virtual Gfx::PDescriptorSet getVertexDataSet() override; virtual std::string getTypeName() const override { return "StaticMeshVertexData"; } + void registerStaticMesh(const Array& meshes, const Component::Transform& transform); private: virtual void resizeBuffers() override; virtual void updateBuffers() override; + Array staticMeshlets; + std::mutex mutex; Gfx::OShaderBuffer positions; Array positionData; diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 95c91f1..6a15ae5 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -36,16 +36,18 @@ void VertexData::updateMesh(PMesh mesh, Component::Transform& transform) MaterialData& matData = materialData[mat->getName()]; matData.material = mat; MaterialInstanceData& matInstanceData = matData.instances[referencedInstance->getId()]; + matInstanceData.descriptorOffset = instanceData.size(); + matInstanceData.numMeshes = 0; + matInstanceData.meshId = mesh->id; for (const auto& data : meshData[mesh->id]) { Matrix4 transformMatrix = transform.toMatrix() * mesh->transform; - matInstanceData.meshes.add(MeshInstanceData{ - .instance = InstanceData { - .transformMatrix = transformMatrix, - .inverseTransformMatrix = glm::inverse(transformMatrix), - }, - .data = data, - }); + instanceData.add(InstanceData { + .transformMatrix = transformMatrix, + .inverseTransformMatrix = glm::inverse(transformMatrix), + }); + instanceMeshData.add(data); + matInstanceData.numMeshes++; for (size_t i = 0; i < 0; ++i) { auto bounding = meshlets[data.meshletOffset + i].bounding; @@ -94,58 +96,45 @@ void VertexData::createDescriptors() { std::unique_lock l(materialDataLock); instanceDataLayout->reset(); - for (const auto& [_, mat] : materialData) - { - for (auto& [_, matInst] : mat.instances) - { - Array instanceData; - Array meshes; - for (auto& inst : matInst.meshes) - { - meshes.add(inst.data); - instanceData.add(inst.instance); - } - matInst.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .sourceData = { - .size = sizeof(InstanceData) * instanceData.size(), - .data = (uint8*)instanceData.data(), - }, - .numElements = instanceData.size(), - .dynamic = false, - .name = "InstanceBuffer" - }); - matInst.instanceBuffer->pipelineBarrier( - Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - Gfx::SE_ACCESS_MEMORY_READ_BIT, - Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT - ); - matInst.descriptorSet = instanceDataLayout->allocateDescriptorSet(); - - matInst.meshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .sourceData = { - .size = sizeof(MeshData) * meshes.size(), - .data = (uint8*)meshes.data(), - }, - .numElements = meshes.size(), - .dynamic = false, - .name = "MeshDataBuffer" - }); - matInst.meshDataBuffer->pipelineBarrier( - Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - Gfx::SE_ACCESS_MEMORY_READ_BIT, - Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT - ); - matInst.descriptorSet->updateBuffer(0, matInst.instanceBuffer); - matInst.descriptorSet->updateBuffer(1, matInst.meshDataBuffer); - matInst.descriptorSet->updateBuffer(2, meshletBuffer); - matInst.descriptorSet->updateBuffer(3, primitiveIndicesBuffer); - matInst.descriptorSet->updateBuffer(4, vertexIndicesBuffer); - - matInst.descriptorSet->writeChanges(); - } - } + instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = { + .size = sizeof(InstanceData) * instanceData.size(), + .data = (uint8*)instanceData.data(), + }, + .numElements = instanceData.size(), + .dynamic = false, + .name = "InstanceBuffer" + }); + instanceBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT, + Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT + ); + descriptorSet = instanceDataLayout->allocateDescriptorSet(); + + instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = { + .size = sizeof(MeshData) * instanceMeshData.size(), + .data = (uint8*)instanceMeshData.data(), + }, + .numElements = instanceMeshData.size(), + .dynamic = false, + .name = "MeshDataBuffer" + }); + instanceMeshDataBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT, + Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT + ); + descriptorSet->updateBuffer(0, instanceBuffer); + descriptorSet->updateBuffer(1, instanceMeshDataBuffer); + descriptorSet->updateBuffer(2, meshletBuffer); + descriptorSet->updateBuffer(3, primitiveIndicesBuffer); + descriptorSet->updateBuffer(4, vertexIndicesBuffer); + + descriptorSet->writeChanges(); } void VertexData::loadMesh(MeshId id, Array loadedIndices, Array loadedMeshlets) @@ -264,7 +253,7 @@ List VertexData::getList() return vertexDataList; } -VertexData* Seele::VertexData::findByTypeName(std::string name) +VertexData* VertexData::findByTypeName(std::string name) { for (auto vd : vertexDataList) { @@ -276,15 +265,16 @@ VertexData* Seele::VertexData::findByTypeName(std::string name) return nullptr; } -void Seele::VertexData::init(Gfx::PGraphics _graphics) +void VertexData::init(Gfx::PGraphics _graphics) { graphics = _graphics; verticesAllocated = NUM_DEFAULT_ELEMENTS; instanceDataLayout = graphics->createDescriptorLayout("pScene"); - instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,}); + // instanceData + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,}); // meshData - instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,}); + instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,}); // meshletData instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); // primitiveIndices @@ -299,6 +289,8 @@ void Seele::VertexData::init(Gfx::PGraphics _graphics) void VertexData::destroy() { + instanceBuffer = nullptr; + instanceMeshDataBuffer = nullptr; instanceDataLayout = nullptr; meshletBuffer = nullptr; vertexIndicesBuffer = nullptr; diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index 5998745..f8171b5 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -43,18 +43,12 @@ public: uint32 indicesOffset = 0; uint32 pad0[3]; }; - struct MeshInstanceData - { - InstanceData instance; - MeshData data; - }; struct MaterialInstanceData { PMaterialInstance materialInstance; - Gfx::OShaderBuffer instanceBuffer; - Gfx::OShaderBuffer meshDataBuffer; - Gfx::PDescriptorSet descriptorSet; - Array meshes; + uint32 descriptorOffset; + uint64 numMeshes; + MeshId meshId; }; struct MaterialData { @@ -76,6 +70,7 @@ public: virtual std::string getTypeName() const = 0; Gfx::PIndexBuffer getIndexBuffer() { return indexBuffer; } Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; } + Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; } const Map& getMaterialData() const { return materialData; } const Array& getMeshData(MeshId id) { return meshData[id]; } static List getList(); @@ -89,10 +84,10 @@ protected: struct MeshletDescription { AABB bounding; - uint32_t vertexCount; - uint32_t primitiveCount; - uint32_t vertexOffset; - uint32_t primitiveOffset; + uint32 vertexCount; + uint32 primitiveCount; + uint32 vertexOffset; + uint32 primitiveOffset; Vector color; float pad; }; @@ -114,6 +109,12 @@ protected: Gfx::OShaderBuffer primitiveIndicesBuffer; // for legacy pipeline Gfx::OIndexBuffer indexBuffer; + // Material data + Array instanceData; + Gfx::OShaderBuffer instanceBuffer; + Array instanceMeshData; + Gfx::OShaderBuffer instanceMeshDataBuffer; + Gfx::PDescriptorSet descriptorSet; uint64 idCounter; uint64 head; uint64 verticesAllocated; diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 50f921d..2f90de1 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -270,7 +270,7 @@ void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline) pipeline = gfxPipeline.cast(); pipeline->bind(handle); } -void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) +void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array dynamicOffsets) { assert(threadId == std::this_thread::get_id()); auto descriptor = descriptorSet.cast(); @@ -279,9 +279,9 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) descriptor->bind(); VkDescriptorSet setHandle = descriptor->getHandle(); - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, 0, nullptr); + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), dynamicOffsets.data()); } -void RenderCommand::bindDescriptor(const Array& descriptorSets) +void RenderCommand::bindDescriptor(const Array& descriptorSets, Array dynamicOffsets) { assert(threadId == std::this_thread::get_id()); VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()]; @@ -294,7 +294,7 @@ void RenderCommand::bindDescriptor(const Array& descriptorS boundDescriptors.add(descriptorSet.getHandle()); sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); } - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr); + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data()); delete[] sets; } void RenderCommand::bindVertexBuffer(const Array& streams) @@ -407,7 +407,7 @@ void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline) pipeline->bind(handle); } -void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) +void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array dynamicOffsets) { assert(threadId == std::this_thread::get_id()); auto descriptor = descriptorSet.cast(); @@ -416,10 +416,10 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) descriptor->bind(); VkDescriptorSet setHandle = descriptor->getHandle(); - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, 0, nullptr); + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), dynamicOffsets.data()); } -void ComputeCommand::bindDescriptor(const Array& descriptorSets) +void ComputeCommand::bindDescriptor(const Array& descriptorSets, Array dynamicOffsets) { assert(threadId == std::this_thread::get_id()); VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()]; @@ -433,7 +433,7 @@ void ComputeCommand::bindDescriptor(const Array& descriptor boundDescriptors.add(descriptorSet.getHandle()); sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); } - vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr); + vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data()); delete[] sets; } diff --git a/src/Engine/Graphics/Vulkan/Command.h b/src/Engine/Graphics/Vulkan/Command.h index 3c9637d..e0af7a4 100644 --- a/src/Engine/Graphics/Vulkan/Command.h +++ b/src/Engine/Graphics/Vulkan/Command.h @@ -72,8 +72,8 @@ public: bool isReady(); virtual void setViewport(Gfx::PViewport viewport) override; virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override; - virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override; - virtual void bindDescriptor(const Array& descriptorSets) override; + virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array dynamicOffsets) override; + virtual void bindDescriptor(const Array& descriptorSets, Array dynamicOffsets) override; virtual void bindVertexBuffer(const Array& buffers) override; virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override; virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, @@ -107,8 +107,8 @@ public: void reset(); bool isReady(); virtual void bindPipeline(Gfx::PComputePipeline pipeline) override; - virtual void bindDescriptor(Gfx::PDescriptorSet set) override; - virtual void bindDescriptor(const Array& sets) override; + virtual void bindDescriptor(Gfx::PDescriptorSet set, Array dynamicOffsets) override; + virtual void bindDescriptor(const Array& sets, Array dynamicOffsets) override; virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override; virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) override; diff --git a/src/Engine/System/KeyboardInput.cpp b/src/Engine/System/KeyboardInput.cpp index 36023de..141e43b 100644 --- a/src/Engine/System/KeyboardInput.cpp +++ b/src/Engine/System/KeyboardInput.cpp @@ -22,10 +22,14 @@ void KeyboardInput::update(Component::KeyboardInput& input) input.mouseY = mouseY; input.mouse1 = mouse1; input.mouse2 = mouse2; + input.scrollX = scrollX; + input.scrollY = scrollY; deltaX = mouseX - lastMouseX; deltaY = mouseY - lastMouseY; lastMouseX = mouseX; lastMouseY = mouseY; + scrollX = 0; + scrollY = 0; } void KeyboardInput::keyCallback(KeyCode code, InputAction action, KeyModifier) @@ -50,3 +54,9 @@ void KeyboardInput::mouseButtonCallback(MouseButton button, InputAction action, mouse2 = action != InputAction::RELEASE; } } + +void KeyboardInput::scrollCallback(double xScroll, double yScroll) +{ + scrollX = xScroll; + scrollY = yScroll; +} diff --git a/src/Engine/System/KeyboardInput.h b/src/Engine/System/KeyboardInput.h index f0fb3b9..934cd8b 100644 --- a/src/Engine/System/KeyboardInput.h +++ b/src/Engine/System/KeyboardInput.h @@ -15,6 +15,7 @@ public: void keyCallback(KeyCode code, InputAction action, KeyModifier modifier); void mouseCallback(double xPos, double yPos); void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier); + void scrollCallback(double xScroll, double yScroll); private: Seele::StaticArray keys; bool mouse1 = false; @@ -25,6 +26,8 @@ private: float mouseY = 0; float deltaX = 0; float deltaY = 0; + float scrollX = 0; + float scrollY = 0; }; DEFINE_REF(KeyboardInput) } diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index 2257cc9..1821033 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -108,8 +108,9 @@ void GameView::mouseButtonCallback(MouseButton button, InputAction action, KeyMo keyboardSystem->mouseButtonCallback(button, action, modifier); } -void GameView::scrollCallback(double, double) +void GameView::scrollCallback(double xScroll, double yScroll) { + keyboardSystem->scrollCallback(xScroll, yScroll); } void GameView::fileCallback(int, const char**)