From c3f65fecdb553ce28250891599081eb50c8999c2 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 16 Sep 2024 21:58:10 +0200 Subject: [PATCH] Half the scene (all upper and lower walls) is drawn as masked unfortunately --- .../rendering/vulkan/shaders/vk_shader.cpp | 1 + .../rendering/vulkan/shaders/vk_shader.h | 3 ++- .../rendering/vulkan/vk_renderstate.cpp | 21 +++++++++++++++++-- src/common/rendering/vulkan/vk_renderstate.h | 2 +- .../hwrenderer/scene/hw_drawinfo.cpp | 5 +++-- wadsrc/static/shaders/scene/frag_main.glsl | 4 ++++ 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index c80f5670a..81797f201 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -219,6 +219,7 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername if (!fb->GetDevice()->EnabledFeatures.Features.shaderClipDistance) definesBlock << "#define NO_CLIPDISTANCE_SUPPORT\n"; if (!key.AlphaTest) definesBlock << "#define NO_ALPHATEST\n"; if (key.GBufferPass) definesBlock << "#define GBUFFER_PASS\n"; + if (key.AlphaTestOnly) definesBlock << "#define ALPHATEST_ONLY\n"; if (key.DepthFadeThreshold) definesBlock << "#define USE_DEPTHFADETHRESHOLD\n"; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 6ad43464c..035a1a60e 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -97,7 +97,8 @@ public: uint64_t FogBalls : 1; // FOGBALLS uint64_t NoFragmentShader : 1; uint64_t DepthFadeThreshold : 1; - uint64_t Unused : 41; + uint64_t AlphaTestOnly : 1; // ALPHATEST_ONLY + uint64_t Unused : 40; }; uint64_t AsQWORD = 0; }; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index f55bdb0f0..9961a64ef 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -874,6 +874,8 @@ void VkRenderState::RunZMinMaxPass() auto buffers = fb->GetBuffers(); auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); + fb->GetCommands()->PushGroup(cmdbuffer, "zminmax"); + int width = ((buffers->GetWidth() + 63) / 64 * 64) >> 1; int height = ((buffers->GetHeight() + 63) / 64 * 64) >> 1; @@ -945,6 +947,8 @@ void VkRenderState::RunZMinMaxPass() .AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false) .AddImage(&fb->GetBuffers()->SceneZMinMax[5], VK_IMAGE_LAYOUT_GENERAL, false) .Execute(cmdbuffer); + + fb->GetCommands()->PopGroup(cmdbuffer); } void VkRenderState::DispatchLightTiles(const VSMatrix& worldToView, float m5) @@ -954,6 +958,8 @@ void VkRenderState::DispatchLightTiles(const VSMatrix& worldToView, float m5) auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); + fb->GetCommands()->PushGroup(cmdbuffer, "lighttiles"); + PipelineBarrier() .AddBuffer(fb->GetBuffers()->SceneLightTiles.get(), VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT) .Execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); @@ -986,6 +992,8 @@ void VkRenderState::DispatchLightTiles(const VSMatrix& worldToView, float m5) PipelineBarrier() .AddBuffer(fb->GetBuffers()->SceneLightTiles.get(), VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) .Execute(cmdbuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + fb->GetCommands()->PopGroup(cmdbuffer); } void VkRenderState::DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) @@ -998,7 +1006,7 @@ void VkRenderState::DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentSha int pipelineID = it.first; const VkPipelineKey& key = fb->GetLevelMeshPipelineKey(pipelineID); - ApplyLevelMeshPipeline(mCommandBuffer, key, noFragmentShader); + ApplyLevelMeshPipeline(mCommandBuffer, key, drawType, noFragmentShader); for (MeshBufferRange& range : it.second) { @@ -1009,6 +1017,8 @@ void VkRenderState::DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentSha void VkRenderState::BeginQuery() { + if (!mCommandBuffer) + ApplyRenderPass(DT_Triangles); mCommandBuffer->beginQuery(mRSBuffers->OcclusionQuery.QueryPool.get(), mRSBuffers->OcclusionQuery.NextIndex++, 0); } @@ -1039,8 +1049,15 @@ void VkRenderState::GetQueryResults(int queryStart, int queryCount, TArray } } -void VkRenderState::ApplyLevelMeshPipeline(VulkanCommandBuffer* cmdbuffer, VkPipelineKey pipelineKey, bool noFragmentShader) +void VkRenderState::ApplyLevelMeshPipeline(VulkanCommandBuffer* cmdbuffer, VkPipelineKey pipelineKey, LevelMeshDrawType drawType, bool noFragmentShader) { + if (drawType == LevelMeshDrawType::Masked && noFragmentShader) + { + // We unfortunately have to run the fragment shader to know which pixels are masked. Use a simplified version to reduce the cost. + noFragmentShader = false; + pipelineKey.ShaderKey.AlphaTestOnly = true; + } + // Global state that don't require rebuilding the mesh pipelineKey.ShaderKey.NoFragmentShader = noFragmentShader; pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1; diff --git a/src/common/rendering/vulkan/vk_renderstate.h b/src/common/rendering/vulkan/vk_renderstate.h index 28a31eabf..163ce72bf 100644 --- a/src/common/rendering/vulkan/vk_renderstate.h +++ b/src/common/rendering/vulkan/vk_renderstate.h @@ -92,7 +92,7 @@ protected: void RunZMinMaxPass(); void ApplyLevelMesh(); - void ApplyLevelMeshPipeline(VulkanCommandBuffer* cmdbuffer, VkPipelineKey pipelineKey, bool noFragmentShader); + void ApplyLevelMeshPipeline(VulkanCommandBuffer* cmdbuffer, VkPipelineKey pipelineKey, LevelMeshDrawType drawType, bool noFragmentShader); VulkanRenderDevice* fb = nullptr; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 6592e2a20..5129bb326 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -443,8 +443,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) state.SetColorMask(false); state.SetCulling(Cull_CW); state.DrawLevelMesh(LevelMeshDrawType::Opaque, true); - state.DispatchLightTiles(VPUniforms.mViewMatrix, VPUniforms.mProjectionMatrix.get()[5]); - state.DrawLevelMesh(LevelMeshDrawType::Masked, false); // To do: properly mark wall top/bottom as opaque so we don't need this + state.DrawLevelMesh(LevelMeshDrawType::Masked, true); if (gl_portals) { state.SetDepthBias(1, 128); @@ -481,6 +480,8 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) state.SetDepthMask(true); int queryEnd = state.GetNextQueryIndex(); + state.DispatchLightTiles(VPUniforms.mViewMatrix, VPUniforms.mProjectionMatrix.get()[5]); + // draw opaque level so the GPU has something to do while we examine the query results state.DrawLevelMesh(LevelMeshDrawType::Opaque, false); state.DrawLevelMesh(LevelMeshDrawType::Masked, false); diff --git a/wadsrc/static/shaders/scene/frag_main.glsl b/wadsrc/static/shaders/scene/frag_main.glsl index def4164b3..8f8acc813 100644 --- a/wadsrc/static/shaders/scene/frag_main.glsl +++ b/wadsrc/static/shaders/scene/frag_main.glsl @@ -32,6 +32,8 @@ void main() if (material.Base.a <= uAlphaThreshold) discard; #endif +#ifndef ALPHATEST_ONLY + #ifdef USE_DEPTHFADETHRESHOLD float behindFragmentDepth = texelFetch(LinearDepth, uViewOffset + ivec2(gl_FragCoord.xy), 0).r; material.Base.a *= clamp((behindFragmentDepth - pixelpos.w) / uDepthFadeThreshold, 0.0, 1.0); @@ -63,4 +65,6 @@ void main() FragFog = vec4(AmbientOcclusionColor(), 1.0); FragNormal = vec4(vEyeNormal.xyz * 0.5 + 0.5, 1.0); #endif + +#endif }