From 57fe68c8a19da54173b5c63afeddc083d7d2f57b Mon Sep 17 00:00:00 2001 From: dpjudas Date: Tue, 31 Oct 2023 03:04:20 +0100 Subject: [PATCH] Draw depth pass and portal occlusion test --- .../rendering/hwrenderer/data/hw_levelmesh.h | 1 + .../vulkan/pipelines/vk_renderpass.cpp | 3 +- .../rendering/vulkan/shaders/vk_shader.cpp | 9 ++- .../rendering/vulkan/shaders/vk_shader.h | 3 +- .../rendering/vulkan/vk_renderdevice.cpp | 61 ++++++++++++++++--- .../hwrenderer/doom_levelsubmesh.cpp | 12 ++-- 6 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 8510f3f9c..d06957bc2 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -268,6 +268,7 @@ public: std::unique_ptr Collision; TArray DrawList; + TArray PortalList; // Lightmap atlas int LMTextureCount = 0; diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp index 58a09f666..0e8732609 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp @@ -240,7 +240,8 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli VkShaderProgram *program = fb->GetShaderManager()->Get(key.ShaderKey); builder.AddVertexShader(program->vert.get()); - builder.AddFragmentShader(program->frag.get()); + if (program->frag) + builder.AddFragmentShader(program->frag.get()); const VkVertexFormat &vfmt = *fb->GetRenderPassManager()->GetVertexFormat(key.VertexFormat); diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 93045e4af..16f147f81 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -75,7 +75,8 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key) const auto& desc = effectshaders[key.SpecialEffect]; program.vert = LoadVertShader(desc.ShaderName, mainvp, desc.defines, key.UseLevelMesh); - program.frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.defines, key); + if (!key.NoFragmentShader) + program.frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.defines, key); } else { @@ -113,7 +114,8 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key) { const auto& desc = defaultshaders[key.EffectState]; program.vert = LoadVertShader(desc.ShaderName, mainvp, desc.Defines, key.UseLevelMesh); - program.frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump, desc.Defines, key); + if (!key.NoFragmentShader) + program.frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump, desc.Defines, key); } else { @@ -122,7 +124,8 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key) FString defines = defaultshaders[desc.shaderType].Defines + desc.defines; program.vert = LoadVertShader(name, mainvp, defines.GetChars(), key.UseLevelMesh); - program.frag = LoadFragShader(name, mainfp, desc.shader.GetChars(), defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump, defines.GetChars(), key); + if (!key.NoFragmentShader) + program.frag = LoadFragShader(name, mainfp, desc.shader.GetChars(), defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump, defines.GetChars(), key); } } return &program; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 43e04b36d..322c34487 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -80,7 +80,8 @@ public: uint64_t LightMode : 2; // LIGHTMODE_DEFAULT, LIGHTMODE_SOFTWARE, LIGHTMODE_VANILLA, LIGHTMODE_BUILD uint64_t UseLevelMesh : 1; // USE_LEVELMESH uint64_t FogBalls : 1; // FOGBALLS - uint64_t Unused : 43; + uint64_t NoFragmentShader : 1; + uint64_t Unused : 42; }; uint64_t AsQWORD = 0; }; diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 431fa484d..dcc4fa8b5 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -789,25 +789,72 @@ void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint) matrices.TextureMatrix.loadIdentity(); rsbuffers->MatrixBuffer->Write(matrices); + PushConstants pushConstants = {}; + pushConstants.uDataIndex = 0; + pushConstants.uLightIndex = -1; + pushConstants.uBoneIndexBase = -1; + auto submesh = GetRaytrace()->GetMesh()->StaticMesh.get(); + + // Draw opaque scene into the depth buffer for (LevelSubmeshDrawRange& range : submesh->DrawList) { - auto& pipelineKey = levelMeshPipelineKeys[range.PipelineID]; - VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh); - cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey)); + VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID]; + if (pipelineKey.ShaderKey.AlphaTest) + continue; + pipelineKey.ShaderKey.NoFragmentShader = true; + + VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh); uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign; uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset(); uint32_t lightsOffset = 0; uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset }; + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey)); cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet()); cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets); cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet()); + cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants); - PushConstants pushConstants = {}; - pushConstants.uDataIndex = 0; - pushConstants.uLightIndex = -1; - pushConstants.uBoneIndexBase = -1; + cmdbuffer->drawIndexed(range.Count, 1, range.Start, 0, 0); + } + + // Draw portal surface occlusion queries + + for (LevelSubmeshDrawRange& range : submesh->PortalList) + { + VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID]; + pipelineKey.ShaderKey.NoFragmentShader = true; + + VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh); + uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign; + uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset(); + uint32_t lightsOffset = 0; + uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset }; + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey)); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet()); + cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants); + + // To do: add occlusion query + + cmdbuffer->drawIndexed(range.Count, 1, range.Start, 0, 0); + } + + // Draw opaque scene + for (LevelSubmeshDrawRange& range : submesh->DrawList) + { + auto& pipelineKey = levelMeshPipelineKeys[range.PipelineID]; + VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh); + uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign; + uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset(); + uint32_t lightsOffset = 0; + uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset }; + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey)); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet()); cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants); cmdbuffer->drawIndexed(range.Count, 1, range.Start, 0, 0); diff --git a/src/rendering/hwrenderer/doom_levelsubmesh.cpp b/src/rendering/hwrenderer/doom_levelsubmesh.cpp index 2734b3206..372641cb1 100644 --- a/src/rendering/hwrenderer/doom_levelsubmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelsubmesh.cpp @@ -217,17 +217,17 @@ void DoomLevelSubmesh::CreateDynamicSurfaces(FLevelLocals& doomMap) void DoomLevelSubmesh::CreateIndexes() { // Order indexes by pipeline - std::unordered_map> pipelineSurfaces; + std::unordered_map> pipelineSurfaces; for (size_t i = 0; i < Surfaces.Size(); i++) { DoomLevelMeshSurface* s = &Surfaces[i]; - pipelineSurfaces[s->PipelineID].Push(i); + pipelineSurfaces[(int64_t(s->PipelineID) << 32) | int64_t(s->bSky)].Push(i); } for (const auto& it : pipelineSurfaces) { LevelSubmeshDrawRange range; - range.PipelineID = it.first; + range.PipelineID = it.first >> 32; range.Start = MeshElements.Size(); for (unsigned int i : it.second) { @@ -289,7 +289,11 @@ void DoomLevelSubmesh::CreateIndexes() } } range.Count = MeshElements.Size() - range.Start; - DrawList.Push(range); + + if ((it.first & 1) == 0) + DrawList.Push(range); + else + PortalList.Push(range); } }