diff --git a/res/shaders/DrawListTask.slang b/res/shaders/DrawListTask.slang index f74f9ab..7d08ef8 100644 --- a/res/shaders/DrawListTask.slang +++ b/res/shaders/DrawListTask.slang @@ -26,7 +26,7 @@ void taskMain( uint cull = p.cullingOffset + i; MeshletDescription meshlet = pScene.meshletInfos[m]; MeshletCullingInfo culling = pScene.cullingInfos[cull]; - if(culling.wasVisible()) + //if(culling.wasVisible()) { uint index; InterlockedAdd(head, 1, index); diff --git a/slangdconfig.json b/slangdconfig.json new file mode 100644 index 0000000..ac53a3d --- /dev/null +++ b/slangdconfig.json @@ -0,0 +1,8 @@ +{ + "slang.predefinedMacros": [ + ], + "slang.additionalSearchPaths": [ + "res/shaders/lib", + "c:\\Program Files\\Seele\\res\\shaders\\lib" + ] +} \ No newline at end of file diff --git a/src/Editor/Asset/EnvironmentLoader.cpp b/src/Editor/Asset/EnvironmentLoader.cpp index 2c27439..92cb44c 100644 --- a/src/Editor/Asset/EnvironmentLoader.cpp +++ b/src/Editor/Asset/EnvironmentLoader.cpp @@ -129,18 +129,22 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset }); Gfx::ORenderPass cubeRenderPass = graphics->createRenderPass( Gfx::RenderTargetLayout{ - .colorAttachments = {Gfx::RenderTargetAttachment(cubeMap, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, - Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE)}, + .colorAttachments = + { + Gfx::RenderTargetAttachment(cubeMap, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE), + }, + }, + { + Gfx::SubPassDependency{ + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, + }, }, - {Gfx::SubPassDependency{ - .srcSubpass = 0, - .dstSubpass = ~0U, - .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .dstStage = Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, - }}, { .size = {SOURCE_RESOLUTION, SOURCE_RESOLUTION}, .offset = {0, 0}, diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index 9b0a2ed..8431669 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -155,7 +155,6 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array& if (material->GetTexture(type, index, &texPath, &mapping, &uvIndex, &blend, &op, &mapMode) != AI_SUCCESS) { std::cout << "fuck" << std::endl; } - uvIndex = 1; std::string textureKey = fmt::format("{0}Texture{1}", paramKey, index); auto texFilename = std::filesystem::path(texPath.C_Str()); PTextureAsset texture; diff --git a/src/Engine/Actor/DirectionalLightActor.cpp b/src/Engine/Actor/DirectionalLightActor.cpp index c3936a5..ff7c02b 100644 --- a/src/Engine/Actor/DirectionalLightActor.cpp +++ b/src/Engine/Actor/DirectionalLightActor.cpp @@ -5,7 +5,7 @@ using namespace Seele; DirectionalLightActor::DirectionalLightActor(PScene scene) : Actor(scene) { attachComponent(); } DirectionalLightActor::DirectionalLightActor(PScene scene, Vector color, float intensity, Vector direction) : Actor(scene) { - attachComponent(Vector4(color, intensity), Vector4(direction, 0)); + attachComponent(Vector4(color, intensity), Vector4(glm::normalize(direction), 0)); } DirectionalLightActor::~DirectionalLightActor() {} diff --git a/src/Engine/Component/Camera.h b/src/Engine/Component/Camera.h index 46d0270..b2ca8f9 100644 --- a/src/Engine/Component/Camera.h +++ b/src/Engine/Component/Camera.h @@ -6,7 +6,8 @@ namespace Seele { namespace Component { struct Camera { - Matrix4 viewMatrix; + float nearPlane = 0.001f; + float farPlane = 10000.0f; bool mainCamera = false; }; } // namespace Component diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 9eb4bfc..9191db6 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -35,6 +35,11 @@ struct WindowCreateInfo { struct ViewportCreateInfo { URect dimensions; float fieldOfView = glm::radians(70.0f); + // ortho params + float left = 0; + float right = 0; + float top = 0; + float bottom = 0; }; // doesnt own the data, only proxy it struct DataSource { diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index a05a8e3..3cb3c9d 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -89,7 +89,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics) BasePass::~BasePass() {} void BasePass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { - RenderPass::beginFrame(cam, transform); + viewParamsSet = createViewParamsSet(cam, transform); cameraPos = transform.getPosition(); cameraForward = transform.getForward(); @@ -136,6 +136,7 @@ void BasePass::beginFrame(const Component::Camera& cam, const Component::Transfo } void BasePass::render() { + graphics->beginDebugRegion("BasePass"); opaqueCulling->updateBuffer(LIGHTINDEX_NAME, 0, oLightIndexList); opaqueCulling->updateTexture(LIGHTGRID_NAME, 0, oLightGrid); transparentCulling->updateBuffer(LIGHTINDEX_NAME, 0, tLightIndexList); @@ -151,110 +152,118 @@ void BasePass::render() { permutation.setDepthCulling(true); // always use the culling info permutation.setPositionOnly(false); Array transparentData; - // Base Rendering - for (VertexData* vertexData : VertexData::getList()) { - transparentData.addAll(vertexData->getTransparentData()); - permutation.setVertexData(vertexData->getTypeName()); - for (const auto& materialData : vertexData->getMaterialData()) { - // material not used for any active meshes, skip - if (materialData.instances.size() == 0) - continue; - // 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(), materialData.material->getProfile()); - Gfx::PermutationId id(permutation); + { + graphics->beginDebugRegion("Opaque"); + // Base Rendering + for (VertexData* vertexData : VertexData::getList()) { + transparentData.addAll(vertexData->getTransparentData()); + permutation.setVertexData(vertexData->getTypeName()); + for (const auto& materialData : vertexData->getMaterialData()) { + // material not used for any active meshes, skip + if (materialData.instances.size() == 0) + continue; + // 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(), materialData.material->getProfile()); + 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); + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); + assert(collection != nullptr); - bool twoSided = materialData.material->isTwoSided(); + bool twoSided = materialData.material->isTwoSided(); - if (graphics->supportMeshShading()) { - Gfx::MeshPipelineCreateInfo pipelineInfo = { - .taskShader = collection->taskShader, - .meshShader = collection->meshShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .multisampleState = - { - .samples = msColorAttachment.getNumSamples(), - }, - .rasterizationState = - { - .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, - }, - .colorBlend = - { - .attachmentCount = 1, - }, - }; - command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo))); - } else { - Gfx::LegacyPipelineCreateInfo pipelineInfo = { - .vertexShader = collection->vertexShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .multisampleState = - { - .samples = msColorAttachment.getNumSamples(), - }, - .rasterizationState = - { - .cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT), - }, - .colorBlend = - { - .attachmentCount = 1, - }, - }; - command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo))); - } - command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), - scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), opaqueCulling}); - for (const auto& drawCall : materialData.instances) { - command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | - Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, - 0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets); if (graphics->supportMeshShading()) { - command->drawMesh((uint32)drawCall.instanceMeshData.size(), 1, 1); + Gfx::MeshPipelineCreateInfo pipelineInfo = { + .taskShader = collection->taskShader, + .meshShader = collection->meshShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = + { + .samples = msColorAttachment.getNumSamples(), + }, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo))); } else { - command->bindIndexBuffer(vertexData->getIndexBuffer()); - for (const auto& meshData : drawCall.instanceMeshData) { - // all meshlets of a mesh share the same indices offset - command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset, - vertexData->getIndicesOffset(meshData.meshletRange.offset), 0); + Gfx::LegacyPipelineCreateInfo pipelineInfo = { + .vertexShader = collection->vertexShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .multisampleState = + { + .samples = msColorAttachment.getNumSamples(), + }, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo))); + } + command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), + scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), opaqueCulling}); + for (const auto& drawCall : materialData.instances) { + command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | + Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets); + if (graphics->supportMeshShading()) { + command->drawMesh((uint32)drawCall.instanceMeshData.size(), 1, 1); + } else { + command->bindIndexBuffer(vertexData->getIndexBuffer()); + for (const auto& meshData : drawCall.instanceMeshData) { + // all meshlets of a mesh share the same indices offset + command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset, + vertexData->getIndicesOffset(meshData.meshletRange.offset), 0); + } } } + commands.add(std::move(command)); } - commands.add(std::move(command)); } + graphics->endDebugRegion(); } + //commands.add(waterRenderer->render(viewParamsSet)); //commands.add(terrainRenderer->render(viewParamsSet)); // Skybox { + graphics->beginDebugRegion("Skybox"); Gfx::ORenderCommand skyboxCommand = graphics->createRenderCommand("SkyboxRender"); skyboxCommand->setViewport(viewport); skyboxCommand->bindPipeline(skyboxPipeline); skyboxCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet}); skyboxCommand->draw(36, 1, 0, 0); graphics->executeCommands(std::move(skyboxCommand)); + graphics->endDebugRegion(); } // Transparent rendering { + graphics->beginDebugRegion("Transparent"); permutation.setDepthCulling(false); // ignore visibility infos for transparency Map sortedDraws; for (const auto& t : transparentData) { @@ -352,9 +361,11 @@ void BasePass::render() { } } commands.add(std::move(transparentCommand)); + graphics->endDebugRegion(); } // Debug vertices if (gDebugVertices.size() > 0) { + graphics->beginDebugRegion("Debug"); Gfx::ORenderCommand debugCommand = graphics->createRenderCommand("DebugRender"); debugCommand->setViewport(viewport); debugCommand->bindPipeline(debugPipeline); @@ -362,6 +373,7 @@ void BasePass::render() { debugCommand->bindVertexBuffer({debugVertices}); debugCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0); commands.add(std::move(debugCommand)); + graphics->endDebugRegion(); } graphics->executeCommands(std::move(commands)); @@ -369,6 +381,7 @@ void BasePass::render() { query->endQuery(); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "BaseEnd"); gDebugVertices.clear(); + graphics->endDebugRegion(); } void BasePass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index 8931a29..132d350 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -44,6 +44,7 @@ class BasePass : public RenderPass { // used for transparency sorting Vector cameraPos; Vector cameraForward; + Gfx::PDescriptorSet viewParamsSet; PCameraActor source; Gfx::OPipelineLayout basePassLayout; diff --git a/src/Engine/Graphics/RenderPass/CMakeLists.txt b/src/Engine/Graphics/RenderPass/CMakeLists.txt index a5fd61a..00ec48c 100644 --- a/src/Engine/Graphics/RenderPass/CMakeLists.txt +++ b/src/Engine/Graphics/RenderPass/CMakeLists.txt @@ -15,6 +15,8 @@ target_sources(Engine RenderGraphResources.cpp RenderPass.h RenderPass.cpp + ShadowPass.h + ShadowPass.cpp #TerrainRenderer.h #TerrainRenderer.cpp ToneMappingPass.h @@ -38,6 +40,7 @@ target_sources(Engine RenderGraph.h RenderGraphResources.h RenderPass.h + ShadowPass.h #TerrainRenderer.h UIPass.h VisibilityPass.h) \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp index bcf01a4..e1dbfc6 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp @@ -1,6 +1,6 @@ #include "CachedDepthPass.h" -#include "Graphics/Shader.h" #include "Graphics/Pipeline.h" +#include "Graphics/Shader.h" using namespace Seele; @@ -41,9 +41,12 @@ CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : Render CachedDepthPass::~CachedDepthPass() {} -void CachedDepthPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { RenderPass::beginFrame(cam, transform); } +void CachedDepthPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { + viewParamsSet = createViewParamsSet(cam, transform); +} void CachedDepthPass::render() { + graphics->beginDebugRegion("CachedDepth"); query->beginQuery(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CachedBegin"); graphics->beginRenderPass(renderPass); @@ -78,7 +81,7 @@ void CachedDepthPass::render() { .pipelineLayout = collection->pipelineLayout, .rasterizationState = { - .cullMode = Gfx::SE_CULL_MODE_NONE, + .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, }, .colorBlend = { @@ -95,7 +98,7 @@ void CachedDepthPass::render() { .pipelineLayout = collection->pipelineLayout, .rasterizationState = { - .cullMode = Gfx::SE_CULL_MODE_NONE, + .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, }, .colorBlend = { @@ -125,7 +128,7 @@ void CachedDepthPass::render() { for (const auto& meshData : drawCall.instanceMeshData) { // all meshlets of a mesh share the same indices offset command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset, - vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++); + vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++); } } } @@ -137,6 +140,7 @@ void CachedDepthPass::render() { graphics->endRenderPass(); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CachedEnd"); query->endQuery(); + graphics->endDebugRegion(); } void CachedDepthPass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.h b/src/Engine/Graphics/RenderPass/CachedDepthPass.h index f7340be..58f5d89 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.h +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.h @@ -24,6 +24,7 @@ class CachedDepthPass : public RenderPass { Gfx::OPipelineStatisticsQuery query; Gfx::OTimestampQuery timestamps; + Gfx::PDescriptorSet viewParamsSet; Gfx::PShaderBuffer cullingBuffer; PScene scene; }; diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index 9a4c1c4..9e91b2e 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -65,157 +65,171 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend DepthCullingPass::~DepthCullingPass() {} -void DepthCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { RenderPass::beginFrame(cam, transform); } +void DepthCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { + viewParamsSet = createViewParamsSet(cam, transform); +} void DepthCullingPass::render() { - query->beginQuery(); - depthAttachment.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, - Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - - depthMipBuffer->rotateBuffer(depthMipBuffer->getNumElements() * sizeof(uint32)); - Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet(); - set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture()); - set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer); - set->writeChanges(); - - timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin"); - // First we generate a pixel value per thread, while using a whole threadgroup - // for a single one would be a waste - Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("MipGen"); - computeCommand->bindPipeline(depthSourceCopy); - computeCommand->bindDescriptor({viewParamsSet, set}); - computeCommand->dispatch((viewport->getWidth() + BLOCK_SIZE - 1) / BLOCK_SIZE, (viewport->getHeight() + BLOCK_SIZE - 1) / BLOCK_SIZE, - 1); - graphics->executeCommands(std::move(computeCommand)); - for (uint32 i = 0; i < mipOffsets.size() - 1; ++i) + graphics->beginDebugRegion("DepthCullingPass"); { - depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - MipParam param = { - .sourceOffset = mipOffsets[i], - .destOffset = mipOffsets[i + 1], - .sourceDim = mipDims[i], - .destDim = mipDims[i + 1], - }; - Gfx::OComputeCommand reduceCommand = graphics->createComputeCommand("ReduceCommand"); - reduceCommand->bindPipeline(depthReduceLevel); - reduceCommand->bindDescriptor({viewParamsSet, set}); - reduceCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), ¶m); - auto dispatchDim = (mipDims[i + 1] + uint32(BLOCK_SIZE) - 1u) / uint32(BLOCK_SIZE); - reduceCommand->dispatch(dispatchDim.x, dispatchDim.y, 1); - graphics->executeCommands(std::move(reduceCommand)); - } + graphics->beginDebugRegion("MipGeneration"); + query->beginQuery(); + depthAttachment.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT); + depthMipBuffer->rotateBuffer(depthMipBuffer->getNumElements() * sizeof(uint32)); + Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet(); + set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture()); + set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer); + set->writeChanges(); - depthAttachment.getTexture()->changeLayout( - Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); - - timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CullingBegin"); - graphics->beginRenderPass(renderPass); - Array commands; - - Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass"); - permutation.setPositionOnly(true); - permutation.setDepthCulling(getGlobals().useDepthCulling); - for (VertexData* vertexData : VertexData::getList()) { - permutation.setVertexData(vertexData->getTypeName()); - // Create Pipeline(VertexData) - // Descriptors: - // ViewData => global, static - // VertexData => per meshtype - // SceneData => per meshtype - 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 = { - .taskShader = collection->taskShader, - .meshShader = collection->meshShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .rasterizationState = - { - .cullMode = Gfx::SE_CULL_MODE_NONE, - }, - .colorBlend = - { - .attachmentCount = 1, - }, + timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin"); + // First we generate a pixel value per thread, while using a whole threadgroup + // for a single one would be a waste + Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("MipGen"); + computeCommand->bindPipeline(depthSourceCopy); + computeCommand->bindDescriptor({viewParamsSet, set}); + computeCommand->dispatch((viewport->getWidth() + BLOCK_SIZE - 1) / BLOCK_SIZE, + (viewport->getHeight() + BLOCK_SIZE - 1) / BLOCK_SIZE, 1); + graphics->executeCommands(std::move(computeCommand)); + for (uint32 i = 0; i < mipOffsets.size() - 1; ++i) { + depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + MipParam param = { + .sourceOffset = mipOffsets[i], + .destOffset = mipOffsets[i + 1], + .sourceDim = mipDims[i], + .destDim = mipDims[i + 1], }; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); - } else { - Gfx::LegacyPipelineCreateInfo pipelineInfo = { - .vertexShader = collection->vertexShader, - .fragmentShader = collection->fragmentShader, - .renderPass = renderPass, - .pipelineLayout = collection->pipelineLayout, - .rasterizationState = - { - .cullMode = Gfx::SE_CULL_MODE_NONE, - }, - .colorBlend = - { - .attachmentCount = 1, - }, - }; - Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); - command->bindPipeline(pipeline); + Gfx::OComputeCommand reduceCommand = graphics->createComputeCommand("ReduceCommand"); + reduceCommand->bindPipeline(depthReduceLevel); + reduceCommand->bindDescriptor({viewParamsSet, set}); + reduceCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), ¶m); + auto dispatchDim = (mipDims[i + 1] + uint32(BLOCK_SIZE) - 1u) / uint32(BLOCK_SIZE); + reduceCommand->dispatch(dispatchDim.x, dispatchDim.y, 1); + graphics->executeCommands(std::move(reduceCommand)); } - command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set}); - VertexData::DrawCallOffsets offsets = { - .instanceOffset = 0, - .textureOffset = 0, - .samplerOffset = 0, - .floatOffset = 0, - }; - command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), - &offsets); - if (graphics->supportMeshShading()) { - command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1); - } else { - const auto& materials = vertexData->getMaterialData(); - for (const auto& materialData : materials) { - for (const auto& drawCall : materialData.instances) { - // material not used for any active meshes, skip - if (materialData.instances.size() == 0) - continue; - command->bindIndexBuffer(vertexData->getIndexBuffer()); - uint32 inst = drawCall.offsets.instanceOffset; - for (const auto& meshData : drawCall.instanceMeshData) { - // all meshlets of a mesh share the same indices offset - command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset, - vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++); + + depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT); + + depthAttachment.getTexture()->changeLayout( + Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + + timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CullingBegin"); + graphics->endDebugRegion(); + } + { + graphics->beginDebugRegion("DepthCulling"); + graphics->beginRenderPass(renderPass); + Array commands; + Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet(); + set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture()); + set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer); + set->writeChanges(); + Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass"); + permutation.setPositionOnly(true); + permutation.setDepthCulling(getGlobals().useDepthCulling); + for (VertexData* vertexData : VertexData::getList()) { + permutation.setVertexData(vertexData->getTypeName()); + // Create Pipeline(VertexData) + // Descriptors: + // ViewData => global, static + // VertexData => per meshtype + // SceneData => per meshtype + 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 = { + .taskShader = collection->taskShader, + .meshShader = collection->meshShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } else { + Gfx::LegacyPipelineCreateInfo pipelineInfo = { + .vertexShader = collection->vertexShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set}); + VertexData::DrawCallOffsets offsets = { + .instanceOffset = 0, + .textureOffset = 0, + .samplerOffset = 0, + .floatOffset = 0, + }; + command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, + sizeof(VertexData::DrawCallOffsets), &offsets); + if (graphics->supportMeshShading()) { + command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1); + } else { + const auto& materials = vertexData->getMaterialData(); + for (const auto& materialData : materials) { + for (const auto& drawCall : materialData.instances) { + // material not used for any active meshes, skip + if (materialData.instances.size() == 0) + continue; + command->bindIndexBuffer(vertexData->getIndexBuffer()); + uint32 inst = drawCall.offsets.instanceOffset; + for (const auto& meshData : drawCall.instanceMeshData) { + // all meshlets of a mesh share the same indices offset + command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset, + vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++); + } } } } + commands.add(std::move(command)); } - commands.add(std::move(command)); - } - graphics->executeCommands(std::move(commands)); - graphics->endRenderPass(); - timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CullingEnd"); - query->endQuery(); - // Sync depth read/write with compute read - depthAttachment.getTexture()->pipelineBarrier( - Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - // Sync visibility write with compute read - visibilityAttachment.getTexture()->pipelineBarrier(Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, - Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + graphics->executeCommands(std::move(commands)); + graphics->endRenderPass(); + timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CullingEnd"); + query->endQuery(); + // Sync depth read/write with compute read + depthAttachment.getTexture()->pipelineBarrier( + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + // Sync visibility write with compute read + visibilityAttachment.getTexture()->pipelineBarrier(Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + graphics->endDebugRegion(); + } + graphics->endDebugRegion(); } void DepthCullingPass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.h b/src/Engine/Graphics/RenderPass/DepthCullingPass.h index 607a281..84e908c 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.h +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.h @@ -44,6 +44,7 @@ class DepthCullingPass : public RenderPass { Gfx::PComputePipeline depthSourceCopy; Gfx::OComputeShader depthReduceLevelShader; Gfx::PComputePipeline depthReduceLevel; + Gfx::PDescriptorSet viewParamsSet; Gfx::PShaderBuffer cullingBuffer; PScene scene; diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 2a869e0..68cbccd 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -15,7 +15,7 @@ LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend LightCullingPass::~LightCullingPass() {} void LightCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { - RenderPass::beginFrame(cam, transform); + viewParamsSet = createViewParamsSet(cam, transform); oLightIndexCounter->pipelineBarrier(Gfx::SE_ACCESS_MEMORY_WRITE_BIT | Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_MEMORY_WRITE_BIT, @@ -38,6 +38,7 @@ void LightCullingPass::beginFrame(const Component::Camera& cam, const Component: } void LightCullingPass::render() { + graphics->beginDebugRegion("LightCulling"); query->beginQuery(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "LightCullBegin"); oLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT, @@ -74,6 +75,7 @@ void LightCullingPass::render() { Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); tLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + graphics->endDebugRegion(); } void LightCullingPass::endFrame() {} @@ -223,13 +225,14 @@ void LightCullingPass::createRenderPass() { } void LightCullingPass::setupFrustums() { + graphics->beginDebugRegion("SetupFrustums"); uint32_t viewportWidth = viewport->getWidth(); uint32_t viewportHeight = viewport->getHeight(); numThreads = glm::ceil(glm::vec4(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1, 0)); numThreadGroups = glm::ceil(glm::vec4(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1, 0)); - RenderPass::beginFrame(Component::Camera(), Component::Transform()); + viewParamsSet = createViewParamsSet(Component::Camera(), Component::Transform()); dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams"); dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ @@ -294,4 +297,5 @@ void LightCullingPass::setupFrustums() { graphics->executeCommands(std::move(commands)); frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + graphics->endDebugRegion(); } diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index fa9a5bb..0967e58 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -33,6 +33,7 @@ class LightCullingPass : public RenderPass { Gfx::OComputeShader frustumShader; Gfx::PComputePipeline frustumPipeline; Gfx::OPipelineLayout frustumLayout; + Gfx::PDescriptorSet viewParamsSet; PLightEnvironment lightEnv; Gfx::PTexture2D depthAttachment; diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp index 95049cd..eef43c4 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp @@ -67,7 +67,7 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa static uint32 pass = 0; static Component::Transform lastCam; void RayTracingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { - RenderPass::beginFrame(cam, transform); + viewParamsSet = createViewParamsSet(cam, transform); if (lastCam.getPosition() != transform.getPosition() || lastCam.getForward() != transform.getForward()) { lastCam = transform; pass = 0; @@ -75,6 +75,7 @@ void RayTracingPass::beginFrame(const Component::Camera& cam, const Component::T } void RayTracingPass::render() { + graphics->beginDebugRegion("RayTracingPass"); texture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); Array callableGroups; @@ -185,6 +186,7 @@ void RayTracingPass::render() { Array commands; commands.add(std::move(command)); graphics->executeCommands(std::move(commands)); + graphics->endDebugRegion(); } void RayTracingPass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.h b/src/Engine/Graphics/RenderPass/RayTracingPass.h index 26fdd65..2e63267 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.h +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.h @@ -32,6 +32,7 @@ class RayTracingPass : public RenderPass { Gfx::OAnyHitShader anyhit; Gfx::OMissShader miss; Gfx::PRayTracingPipeline pipeline; + Gfx::PDescriptorSet viewParamsSet; PScene scene; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/RenderPass.cpp b/src/Engine/Graphics/RenderPass/RenderPass.cpp index 727313f..6bf9480 100644 --- a/src/Engine/Graphics/RenderPass/RenderPass.cpp +++ b/src/Engine/Graphics/RenderPass/RenderPass.cpp @@ -23,10 +23,17 @@ RenderPass::RenderPass(Gfx::PGraphics graphics) : graphics(graphics) { RenderPass::~RenderPass() {} -void RenderPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { +void RenderPass::setResources(PRenderGraphResources _resources) { resources = _resources; } + +void RenderPass::setViewport(Gfx::PViewport _viewport) { viewport = _viewport; } + +Gfx::PDescriptorSet RenderPass::createViewParamsSet(const Component::Camera& cam, const Component::Transform& transform) +{ auto screenDim = Vector2(static_cast(viewport->getWidth()), static_cast(viewport->getHeight())); - Matrix4 cameraMatrix = cam.viewMatrix; - Matrix4 projectionMatrix = viewport->getProjectionMatrix(); + Vector eyePos = transform.getPosition(); + Vector lookAt = eyePos + transform.getForward(); + Matrix4 cameraMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0)); + Matrix4 projectionMatrix = viewport->getProjectionMatrix(cam.nearPlane, cam.farPlane); viewParams = { .viewMatrix = cameraMatrix, .inverseViewMatrix = glm::inverse(cameraMatrix), @@ -60,10 +67,10 @@ void RenderPass::beginFrame(const Component::Camera& cam, const Component::Trans corners[i] = world / world.w; } - //extract_planes_from_view_projection_matrix(viewParams.viewProjectionMatrix, viewParams.viewFrustum); + // extract_planes_from_view_projection_matrix(viewParams.viewProjectionMatrix, viewParams.viewFrustum); viewParamsLayout->reset(); - viewParamsSet = viewParamsLayout->allocateDescriptorSet(); + Gfx::PDescriptorSet viewParamsSet = viewParamsLayout->allocateDescriptorSet(); viewParamsSet->updateConstants("viewMatrix", 0, &viewParams.viewMatrix); viewParamsSet->updateConstants("inverseViewMatrix", 0, &viewParams.inverseViewMatrix); viewParamsSet->updateConstants("projectionMatrix", 0, &viewParams.projectionMatrix); @@ -79,12 +86,9 @@ void RenderPass::beginFrame(const Component::Camera& cam, const Component::Trans viewParamsSet->updateConstants("pad0", 0, &viewParams.pad0); viewParamsSet->updateConstants("pad1", 0, &viewParams.pad1); viewParamsSet->writeChanges(); + return viewParamsSet; } -void RenderPass::setResources(PRenderGraphResources _resources) { resources = _resources; } - -void RenderPass::setViewport(Gfx::PViewport _viewport) { viewport = _viewport; } - void RenderPass::normalize_plane(Plane& plane) { float l = sqrtf(plane.n.x * plane.n.x + plane.n.y * plane.n.y + plane.n.z * plane.n.z); plane.n.x /= l; diff --git a/src/Engine/Graphics/RenderPass/RenderPass.h b/src/Engine/Graphics/RenderPass/RenderPass.h index f497240..e873189 100644 --- a/src/Engine/Graphics/RenderPass/RenderPass.h +++ b/src/Engine/Graphics/RenderPass/RenderPass.h @@ -18,7 +18,7 @@ class RenderPass { RenderPass(RenderPass&&) = default; RenderPass& operator=(RenderPass&&) = default; virtual ~RenderPass(); - virtual void beginFrame(const Component::Camera& cam, const Component::Transform& transform); + virtual void beginFrame(const Component::Camera& cam, const Component::Transform& transform) = 0; virtual void render() = 0; virtual void endFrame() = 0; virtual void publishOutputs() = 0; @@ -27,6 +27,7 @@ class RenderPass { void setViewport(Gfx::PViewport _viewport); protected: + Gfx::PDescriptorSet createViewParamsSet(const Component::Camera& cam, const Component::Transform& transform); struct Plane { Vector n; float d; @@ -67,7 +68,6 @@ class RenderPass { } viewParams; PRenderGraphResources resources; Gfx::ODescriptorLayout viewParamsLayout; - Gfx::PDescriptorSet viewParamsSet; Gfx::ORenderPass renderPass; Gfx::PGraphics graphics; Gfx::PViewport viewport; diff --git a/src/Engine/Graphics/RenderPass/ShadowPass.cpp b/src/Engine/Graphics/RenderPass/ShadowPass.cpp new file mode 100644 index 0000000..2faa13d --- /dev/null +++ b/src/Engine/Graphics/RenderPass/ShadowPass.cpp @@ -0,0 +1,202 @@ +#include "ShadowPass.h" +#include "Graphics/Graphics.h" +#include "Graphics/Shader.h" + +using namespace Seele; + +ShadowPass::ShadowPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) { + shadowLayout = graphics->createPipelineLayout("ShadowLayout"); + shadowLayout->addDescriptorLayout(viewParamsLayout); + shadowLayout->addPushConstants(Gfx::SePushConstantRange{ + .stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = sizeof(VertexData::DrawCallOffsets), + }); + if (graphics->supportMeshShading()) { + graphics->getShaderCompiler()->registerRenderPass("ShadowPass", Gfx::PassConfig{ + .baseLayout = shadowLayout, + .taskFile = "DrawListTask", + .mainFile = "DrawListMesh", + .hasFragmentShader = false, + .useMeshShading = true, + .hasTaskShader = true, + .useMaterial = false, + .useVisibility = false, + }); + } else { + graphics->getShaderCompiler()->registerRenderPass("ShadowPass", Gfx::PassConfig{ + .baseLayout = shadowLayout, + .taskFile = "", + .mainFile = "LegacyPass", + .hasFragmentShader = false, + .useMeshShading = false, + .hasTaskShader = false, + .useMaterial = false, + .useVisibility = false, + }); + } +} + +ShadowPass::~ShadowPass() {} + +void ShadowPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {} + +void ShadowPass::render() { + graphics->beginDebugRegion("ShadowPass"); + Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("ShadowPass"); + permutation.setDepthCulling(true); + permutation.setPositionOnly(true); + const auto& shadowMaps = scene->getLightEnvironment()->getShadowMaps(); + for (uint32 shadowIndex = 0; shadowIndex < scene->getLightEnvironment()->getNumDirectionalLights(); ++shadowIndex) { + Array commands; + renderPass = graphics->createRenderPass( + Gfx::RenderTargetLayout{ + .depthAttachment = Gfx::RenderTargetAttachment(shadowMaps[shadowIndex], Gfx::SE_IMAGE_LAYOUT_UNDEFINED, + Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE), + + }, + { + Gfx::SubPassDependency{ + .srcSubpass = ~0U, + .dstSubpass = 0, + .srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_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 | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + }, + Gfx::SubPassDependency{ + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_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 | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + }, + }, + { + .size = {shadowMaps[shadowIndex]->getWidth(), shadowMaps[shadowIndex]->getHeight()}, + .offset = {0, 0}, + }, + "Shadow"); + graphics->beginRenderPass(renderPass); + auto light = scene->getLightEnvironment()->getDirectionalLight(shadowIndex); + Vector lightDirection = Vector(light.direction); + Vector lightPosition = -light.direction * 100.0f; + float dot = glm::dot(lightDirection, Math::Transform::FORWARD); + Quaternion rotation = Quaternion(1, 0, 0, 0); + // Handle the edge cases first + if (glm::epsilonEqual(dot, 1.0f, 0.00001f)) { + // Vectors are the same, no rotation + } else if (glm::epsilonEqual(dot, -1.0f, 0.00001f)) { + // Vectors are opposite need 180-degree rotation around any perpendicular axis + rotation = glm::angleAxis(glm::pi(), Vector(0, 1, 0)); + } else { + // Normal case + Vector axis = glm::normalize(glm::cross(lightDirection, Math::Transform::FORWARD)); + float angle = std::acos(dot); // angle between vectors + rotation = glm::angleAxis(angle, axis); + } + Component::Transform lightTransform = Component::Transform{ + .transform = Math::Transform(lightPosition, rotation), + }; + + Component::Camera lightCamera = Component::Camera{ + .nearPlane = -1000.f, + .farPlane = 1000.0f, + }; + Gfx::PDescriptorSet viewParamsSet = createViewParamsSet(lightCamera, lightTransform); + for (VertexData* vertexData : VertexData::getList()) { + permutation.setVertexData(vertexData->getTypeName()); + Gfx::PermutationId id(permutation); + + Gfx::ORenderCommand command = graphics->createRenderCommand("ShadowRender"); + command->setViewport(shadowViewport); + + const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id); + if (graphics->supportMeshShading()) { + Gfx::MeshPipelineCreateInfo pipelineInfo = { + .taskShader = collection->taskShader, + .meshShader = collection->meshShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_NONE, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } else { + Gfx::LegacyPipelineCreateInfo pipelineInfo = { + .vertexShader = collection->vertexShader, + .fragmentShader = collection->fragmentShader, + .renderPass = renderPass, + .pipelineLayout = collection->pipelineLayout, + .rasterizationState = + { + .cullMode = Gfx::SE_CULL_MODE_NONE, + }, + .colorBlend = + { + .attachmentCount = 1, + }, + }; + Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); + command->bindPipeline(pipeline); + } + command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet()}); + VertexData::DrawCallOffsets offsets = { + .instanceOffset = 0, + }; + command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, + sizeof(VertexData::DrawCallOffsets), &offsets); + if (graphics->supportMeshShading()) { + command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1); + } else { + const auto& materials = vertexData->getMaterialData(); + for (const auto& materialData : materials) { + // material not used for any active meshes, skip + if (materialData.instances.size() == 0) + continue; + for (const auto& drawCall : materialData.instances) { + command->bindIndexBuffer(vertexData->getIndexBuffer()); + uint32 inst = drawCall.offsets.instanceOffset; + for (const auto& meshData : drawCall.instanceMeshData) { + // all meshlets of a mesh share the same indices offset + command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset, + vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++); + } + } + } + } + commands.add(std::move(command)); + } + graphics->executeCommands(std::move(commands)); + graphics->endRenderPass(); + } + graphics->endDebugRegion(); +} + +void ShadowPass::endFrame() {} + +void ShadowPass::publishOutputs() { + shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{.dimensions = + { + .size = {2048, 2048}, + .offset = {0, 0}, + }, + .fieldOfView = 0, + .left = -10, + .right = 10, + .top = -10, + .bottom = 10}); + viewport = shadowViewport; +} + +void ShadowPass::createRenderPass() { cullingBuffer = resources->requestBuffer("CULLINGBUFFER"); } diff --git a/src/Engine/Graphics/RenderPass/ShadowPass.h b/src/Engine/Graphics/RenderPass/ShadowPass.h new file mode 100644 index 0000000..14b8e28 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/ShadowPass.h @@ -0,0 +1,24 @@ +#pragma once +#include "RenderPass.h" + +namespace Seele { +class ShadowPass : public RenderPass { + public: + ShadowPass(Gfx::PGraphics graphics, PScene scene); + ShadowPass(ShadowPass&& other) = default; + ShadowPass& operator=(ShadowPass&& other) = default; + virtual ~ShadowPass(); + virtual void beginFrame(const Component::Camera& cam, const Component::Transform& transform) override; + virtual void render() override; + virtual void endFrame() override; + virtual void publishOutputs() override; + virtual void createRenderPass() override; + private: + AABB cameraFrustumBox; + Gfx::OPipelineLayout shadowLayout; + Gfx::PShaderBuffer cullingBuffer; + Gfx::OViewport shadowViewport; + PScene scene; +}; +DEFINE_REF(ShadowPass) +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/ToneMappingPass.cpp b/src/Engine/Graphics/RenderPass/ToneMappingPass.cpp index 9e85745..1a24d88 100644 --- a/src/Engine/Graphics/RenderPass/ToneMappingPass.cpp +++ b/src/Engine/Graphics/RenderPass/ToneMappingPass.cpp @@ -123,9 +123,12 @@ ToneMappingPass::ToneMappingPass(Gfx::PGraphics graphics) : RenderPass(graphics) ToneMappingPass::~ToneMappingPass() {} -void ToneMappingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { RenderPass::beginFrame(cam, transform); } +void ToneMappingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { + viewParamsSet = createViewParamsSet(cam, transform); +} void ToneMappingPass::render() { + graphics->beginDebugRegion("ToneMapping"); hdrInputTexture.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); @@ -181,6 +184,7 @@ void ToneMappingPass::render() { command->draw(3, 1, 0, 0); graphics->executeCommands(std::move(command)); graphics->endRenderPass(); + graphics->endDebugRegion(); } void ToneMappingPass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/ToneMappingPass.h b/src/Engine/Graphics/RenderPass/ToneMappingPass.h index bbd3787..1181f95 100644 --- a/src/Engine/Graphics/RenderPass/ToneMappingPass.h +++ b/src/Engine/Graphics/RenderPass/ToneMappingPass.h @@ -47,5 +47,7 @@ class ToneMappingPass : public RenderPass { Gfx::OVertexShader vert; Gfx::OFragmentShader frag; Gfx::PGraphicsPipeline pipeline; + + Gfx::PDescriptorSet viewParamsSet; }; } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/UIPass.cpp b/src/Engine/Graphics/RenderPass/UIPass.cpp index 8d55e49..084fae7 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.cpp +++ b/src/Engine/Graphics/RenderPass/UIPass.cpp @@ -54,7 +54,7 @@ UIPass::UIPass(Gfx::PGraphics graphics, UI::PSystem system) : RenderPass(graphic UIPass::~UIPass() {} void UIPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { - RenderPass::beginFrame(cam, transform); + viewParamsSet = createViewParamsSet(cam, transform); glyphs.clear(); usedTextures.clear(); elements.clear(); diff --git a/src/Engine/Graphics/RenderPass/UIPass.h b/src/Engine/Graphics/RenderPass/UIPass.h index 961779b..75e6b59 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.h +++ b/src/Engine/Graphics/RenderPass/UIPass.h @@ -62,6 +62,8 @@ class UIPass : public RenderPass { Gfx::ODescriptorLayout uiDescriptorLayout; Gfx::PDescriptorSet uiDescriptorSet; + Gfx::PDescriptorSet viewParamsSet; + Gfx::OVertexShader uiVertexShader; Gfx::OFragmentShader uiFragmentShader; Gfx::OPipelineLayout uiPipelineLayout; diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp index c7b6bf1..d2f48a3 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp @@ -8,11 +8,12 @@ VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) { VisibilityPass::~VisibilityPass() {} void VisibilityPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { - RenderPass::beginFrame(cam, transform); + viewParamsSet = createViewParamsSet(cam, transform); cullingBuffer->rotateBuffer(VertexData::getMeshletCount() * sizeof(VertexData::MeshletCullingInfo), true); } void VisibilityPass::render() { + graphics->beginDebugRegion("VisibilityPass"); cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT); cullingBuffer->clear(); @@ -40,6 +41,7 @@ void VisibilityPass::render() { cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT | Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT); + graphics->endDebugRegion(); } void VisibilityPass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.h b/src/Engine/Graphics/RenderPass/VisibilityPass.h index cbc627a..b8815a5 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.h +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.h @@ -26,6 +26,7 @@ class VisibilityPass : public RenderPass { Gfx::PComputePipeline visibilityPipeline; Gfx::OPipelineStatisticsQuery query; Gfx::PTimestampQuery timestamps; + Gfx::PDescriptorSet viewParamsSet; constexpr static const char* VISIBILITY_NAME = "visibilityTexture"; // Holds culling information for every meshlet for each instance diff --git a/src/Engine/Graphics/RenderTarget.cpp b/src/Engine/Graphics/RenderTarget.cpp index 4651da7..48174f4 100644 --- a/src/Engine/Graphics/RenderTarget.cpp +++ b/src/Engine/Graphics/RenderTarget.cpp @@ -6,19 +6,20 @@ using namespace Seele::Gfx; RenderTargetAttachment::RenderTargetAttachment(PTexture2D texture, SeImageLayout initialLayout, SeImageLayout finalLayout, SeAttachmentLoadOp loadOp, SeAttachmentStoreOp storeOp, SeAttachmentLoadOp stencilLoadOp, SeAttachmentStoreOp stencilStoreOp) - : clear(), componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp), + : componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout), + loadOp(loadOp), storeOp(storeOp), stencilLoadOp(stencilLoadOp), stencilStoreOp(stencilStoreOp) {} RenderTargetAttachment::RenderTargetAttachment(PTextureCube texture, SeImageLayout initialLayout, SeImageLayout finalLayout, SeAttachmentLoadOp loadOp, SeAttachmentStoreOp storeOp, SeAttachmentLoadOp stencilLoadOp, SeAttachmentStoreOp stencilStoreOp) - : clear(), componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp), + : componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp), storeOp(storeOp), stencilLoadOp(stencilLoadOp), stencilStoreOp(stencilStoreOp) {} RenderTargetAttachment::RenderTargetAttachment(PViewport viewport, SeImageLayout initialLayout, SeImageLayout finalLayout, SeAttachmentLoadOp loadOp, SeAttachmentStoreOp storeOp, SeAttachmentLoadOp stencilLoadOp, SeAttachmentStoreOp stencilStoreOp) - : clear(), componentFlags(0), viewport(viewport), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp), + : componentFlags(0), viewport(viewport), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp), storeOp(storeOp), stencilLoadOp(stencilLoadOp), stencilStoreOp(stencilStoreOp) {} RenderTargetAttachment::~RenderTargetAttachment() {} diff --git a/src/Engine/Graphics/Texture.h b/src/Engine/Graphics/Texture.h index 24b5304..346e9be 100644 --- a/src/Engine/Graphics/Texture.h +++ b/src/Engine/Graphics/Texture.h @@ -12,7 +12,6 @@ class Texture : public QueueOwnedResource { virtual uint32 getWidth() const = 0; virtual uint32 getHeight() const = 0; virtual uint32 getDepth() const = 0; - virtual uint32 getNumFaces() const { return 1; } virtual SeSampleCountFlags getNumSamples() const = 0; virtual uint32 getMipLevels() const = 0; virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, @@ -36,6 +35,7 @@ class Texture2D : public Texture { virtual uint32 getWidth() const = 0; virtual uint32 getHeight() const = 0; virtual uint32 getDepth() const = 0; + virtual uint32 getNumLayers() const = 0; virtual SeSampleCountFlags getNumSamples() const = 0; virtual uint32 getMipLevels() const = 0; virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, @@ -59,6 +59,7 @@ class Texture3D : public Texture { virtual uint32 getWidth() const = 0; virtual uint32 getHeight() const = 0; virtual uint32 getDepth() const = 0; + virtual uint32 getNumLayers() const = 0; virtual SeSampleCountFlags getNumSamples() const = 0; virtual uint32 getMipLevels() const = 0; virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, @@ -82,7 +83,7 @@ class TextureCube : public Texture { virtual uint32 getWidth() const = 0; virtual uint32 getHeight() const = 0; virtual uint32 getDepth() const = 0; - virtual uint32 getNumFaces() const { return 6; } + virtual uint32 getNumLayers() const = 0; virtual SeSampleCountFlags getNumSamples() const = 0; virtual uint32 getMipLevels() const = 0; virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, diff --git a/src/Engine/Graphics/Vulkan/RenderPass.cpp b/src/Engine/Graphics/Vulkan/RenderPass.cpp index 55dbeeb..2a8374a 100644 --- a/src/Engine/Graphics/Vulkan/RenderPass.cpp +++ b/src/Engine/Graphics/Vulkan/RenderPass.cpp @@ -9,9 +9,9 @@ using namespace Seele; using namespace Seele::Vulkan; -RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Array _dependencies, - std::string name, Array viewMasks, Array correlationMasks) - : Gfx::RenderPass(std::move(_layout), std::move(_dependencies)), graphics(graphics) { +RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Array _dependencies, std::string name, + Array viewMasks, Array correlationMasks) + : Gfx::RenderPass(std::move(_layout), std::move(_dependencies)), name(name), graphics(graphics) { subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; Array attachments; Array inputRefs; diff --git a/src/Engine/Graphics/Vulkan/RenderPass.h b/src/Engine/Graphics/Vulkan/RenderPass.h index 3ec4fb3..29649e4 100644 --- a/src/Engine/Graphics/Vulkan/RenderPass.h +++ b/src/Engine/Graphics/Vulkan/RenderPass.h @@ -15,8 +15,10 @@ class RenderPass : public Gfx::RenderPass { constexpr size_t getClearValueCount() const { return clearValues.size(); } constexpr VkClearValue* getClearValues() const { return clearValues.data(); } constexpr VkSubpassContents getSubpassContents() const { return subpassContents; } + constexpr const std::string& getName() const { return name; } private: + std::string name; PGraphics graphics; VkRenderPass renderPass; Array clearValues; diff --git a/src/Engine/Graphics/Vulkan/Texture.h b/src/Engine/Graphics/Vulkan/Texture.h index acd998b..46a933a 100644 --- a/src/Engine/Graphics/Vulkan/Texture.h +++ b/src/Engine/Graphics/Vulkan/Texture.h @@ -83,6 +83,7 @@ class Texture2D : public Gfx::Texture2D, public TextureBase { virtual uint32 getWidth() const override { return handle->width; } virtual uint32 getHeight() const override { return handle->height; } virtual uint32 getDepth() const override { return handle->depth; } + virtual uint32 getNumLayers() const override { return handle->layerCount; } virtual Gfx::SeFormat getFormat() const override { return handle->format; } virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; } virtual uint32 getMipLevels() const override { return handle->mipLevels; } @@ -106,6 +107,7 @@ class Texture3D : public Gfx::Texture3D, public TextureBase { virtual uint32 getWidth() const override { return handle->width; } virtual uint32 getHeight() const override { return handle->height; } virtual uint32 getDepth() const override { return handle->depth; } + virtual uint32 getNumLayers() const override { return handle->layerCount; } virtual Gfx::SeFormat getFormat() const override { return handle->format; } virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; } virtual uint32 getMipLevels() const override { return handle->mipLevels; } @@ -129,6 +131,7 @@ class TextureCube : public Gfx::TextureCube, public TextureBase { virtual uint32 getWidth() const override { return handle->width; } virtual uint32 getHeight() const override { return handle->height; } virtual uint32 getDepth() const override { return handle->depth; } + virtual uint32 getNumLayers() const override { return handle->layerCount; } virtual Gfx::SeFormat getFormat() const override { return handle->format; } virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; } virtual uint32 getMipLevels() const override { return handle->mipLevels; } diff --git a/src/Engine/Graphics/Window.cpp b/src/Engine/Graphics/Window.cpp index 8cc770d..43c81bb 100644 --- a/src/Engine/Graphics/Window.cpp +++ b/src/Engine/Graphics/Window.cpp @@ -9,7 +9,9 @@ Window::~Window() {} Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) : sizeX(viewportInfo.dimensions.size.x), sizeY(viewportInfo.dimensions.size.y), offsetX(viewportInfo.dimensions.offset.x), - offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), owner(owner) { + offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), orthoLeft(viewportInfo.left), + orthoRight(viewportInfo.right), orthoTop(viewportInfo.top), orthoBottom(viewportInfo.bottom), + owner(owner) { if (owner != nullptr) { sizeX = std::min(owner->getFramebufferWidth(), sizeX); sizeY = std::min(owner->getFramebufferHeight(), sizeY); @@ -18,16 +20,12 @@ Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) Viewport::~Viewport() {} -Matrix4 Viewport::getProjectionMatrix() const { +Matrix4 Viewport::getProjectionMatrix(float nearPlane, float farPlane) const { if (fieldOfView > 0.0f) { - Matrix4 projectionMatrix = glm::perspective(fieldOfView, sizeX / static_cast(sizeY), 0.1f, 1000.0f); - Matrix4 correctionMatrix = Matrix4( - 1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, 1 / 2.f, 0, - 0, 0, 1 / 2.f, 1); + Matrix4 projectionMatrix = glm::perspective(fieldOfView, sizeX / static_cast(sizeY), nearPlane, farPlane); + Matrix4 correctionMatrix = Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 / 2.f, 0, 0, 0, 1 / 2.f, 1); return correctionMatrix * projectionMatrix; } else { - return glm::ortho(0.0f, (float)sizeX, (float)sizeY, 0.0f); + return glm::ortho(orthoLeft, orthoRight, orthoTop, orthoBottom, nearPlane, farPlane); } } \ No newline at end of file diff --git a/src/Engine/Graphics/Window.h b/src/Engine/Graphics/Window.h index 7effa72..3ec0830 100644 --- a/src/Engine/Graphics/Window.h +++ b/src/Engine/Graphics/Window.h @@ -52,7 +52,7 @@ class Viewport { constexpr uint32 getOffsetY() const { return offsetY; } constexpr float getContentScaleX() const { return owner->getContentScaleX(); } constexpr float getContentScaleY() const { return owner->getContentScaleY(); } - Matrix4 getProjectionMatrix() const; + Matrix4 getProjectionMatrix(float nearPlane, float farPlane) const; URect getRenderArea() const { return URect{ .size = {sizeX, sizeY}, @@ -66,6 +66,10 @@ class Viewport { uint32 offsetX; uint32 offsetY; float fieldOfView; + float orthoLeft; + float orthoRight; + float orthoTop; + float orthoBottom; PWindow owner; }; DEFINE_REF(Viewport) diff --git a/src/Engine/Math/Transform.h b/src/Engine/Math/Transform.h index 77989e5..10dc73d 100644 --- a/src/Engine/Math/Transform.h +++ b/src/Engine/Math/Transform.h @@ -30,6 +30,10 @@ class Transform { Vector getRight() const; Vector getUp() const; + constexpr static Vector FORWARD = Vector(0, 0, 1); + constexpr static Vector RIGHT = Vector(-1, 0, 0); + constexpr static Vector UP = Vector(0, 1, 0); + bool equals(const Transform& other, float tolerance = 0.000000001f); static void multiply(Transform* outTransform, const Transform* a, const Transform* b); static void add(Transform* outTransform, const Transform* a, const Transform* b); diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index e293840..c6adf95 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -1,7 +1,7 @@ #include "LightEnvironment.h" +#include "Asset/AssetRegistry.h" #include "Asset/EnvironmentMapAsset.h" #include "Graphics/Graphics.h" -#include "Asset/AssetRegistry.h" using namespace Seele; @@ -84,6 +84,17 @@ void LightEnvironment::commit() { set->updateTexture("irradianceMap", 0, environment->getIrradianceMap()); set->updateSampler("irradianceSampler", 0, environmentSampler); set->writeChanges(); + + while (shadowMapArray.size() < dirs.size()) { + shadowMapArray.add(graphics->createTexture2D(TextureCreateInfo{ + .format = Gfx::SE_FORMAT_D32_SFLOAT, + .width = 2048, + .height = 2048, + .elements = (uint32)dirs.size(), + .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, + .name = "ShadowMap", + })); + } } const Gfx::PDescriptorLayout LightEnvironment::getDescriptorLayout() const { return layout; } diff --git a/src/Engine/Scene/LightEnvironment.h b/src/Engine/Scene/LightEnvironment.h index 1cf2435..0a57121 100644 --- a/src/Engine/Scene/LightEnvironment.h +++ b/src/Engine/Scene/LightEnvironment.h @@ -15,11 +15,15 @@ class LightEnvironment { void addPointLight(Component::PointLight pointLight); void commit(); const Gfx::PDescriptorLayout getDescriptorLayout() const; + const Component::DirectionalLight& getDirectionalLight(uint32 lightIndex) const { return dirs[lightIndex]; } Gfx::PDescriptorSet getDescriptorSet(); PEnvironmentMapAsset getEnvironmentMap() { return environment; } + uint64 getNumDirectionalLights() const { return dirs.size(); } + const Array& getShadowMaps() const { return shadowMapArray; } private: Gfx::OShaderBuffer directionalLights; + Array shadowMapArray; Gfx::OShaderBuffer pointLights; Array dirs; Array points; diff --git a/src/Engine/System/CameraUpdater.cpp b/src/Engine/System/CameraUpdater.cpp index a6ae03f..3851527 100644 --- a/src/Engine/System/CameraUpdater.cpp +++ b/src/Engine/System/CameraUpdater.cpp @@ -10,5 +10,4 @@ CameraUpdater::~CameraUpdater() {} void CameraUpdater::update(Component::Camera& camera, Component::Transform& transform) { Vector eyePos = transform.getPosition(); Vector lookAt = eyePos + transform.getForward(); - camera.viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0)); } diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index 45bde43..aad86e4 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -12,6 +12,7 @@ #include "Graphics/RenderPass/RenderGraphResources.h" #include "Graphics/RenderPass/ToneMappingPass.h" #include "Graphics/RenderPass/VisibilityPass.h" +#include "Graphics/RenderPass/ShadowPass.h" #include "System/CameraUpdater.h" #include "System/LightGather.h" #include "System/MeshUpdater.h" @@ -26,6 +27,7 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate renderGraph.addPass(new DepthCullingPass(graphics, scene)); renderGraph.addPass(new VisibilityPass(graphics)); renderGraph.addPass(new LightCullingPass(graphics, scene)); + renderGraph.addPass(new ShadowPass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene)); renderGraph.addPass(new ToneMappingPass(graphics)); renderGraph.setViewport(viewport);