From 2ba2c24f6bc15c9c804fc93f3fab74256ff8ac13 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 13 Sep 2024 20:45:36 +0200 Subject: [PATCH] Add shaders for light tiles --- .../descriptorsets/vk_descriptorset.cpp | 2 +- .../rendering/vulkan/shaders/vk_shader.cpp | 27 ++++++++++++ .../rendering/vulkan/shaders/vk_shader.h | 12 ++++++ .../static/shaders/scene/comp_lighttiles.glsl | 43 +++++++++++++++++++ .../static/shaders/scene/frag_zminmax0.glsl | 17 ++++++++ .../static/shaders/scene/frag_zminmax1.glsl | 16 +++++++ wadsrc/static/shaders/scene/vert_zminmax.glsl | 14 ++++++ 7 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 wadsrc/static/shaders/scene/comp_lighttiles.glsl create mode 100644 wadsrc/static/shaders/scene/frag_zminmax0.glsl create mode 100644 wadsrc/static/shaders/scene/frag_zminmax1.glsl create mode 100644 wadsrc/static/shaders/scene/vert_zminmax.glsl diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index c88b3f85a..9a73a3297 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -91,7 +91,7 @@ void VkDescriptorSetManager::UpdateLevelMeshSet() .AddBuffer(LevelMesh.Set.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->MatrixBuffer->UBO(), 0, sizeof(MatricesUBO)) .AddBuffer(LevelMesh.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetUniformsBuffer()) .AddBuffer(LevelMesh.Set.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightUniformsBuffer()) - .AddBuffer(LevelMesh.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetDynLightBuffer()) + .AddBuffer(LevelMesh.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBuffers()->SceneLightTiles.get()) .AddBuffer(LevelMesh.Set.get(), 5, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, rsbuffers->Fogballbuffer.UBO.get(), 0, sizeof(FogballBufferUBO)) .AddBuffer(LevelMesh.Set.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, rsbuffers->Bonebuffer.SSO.get()) .Execute(fb->GetDevice()); diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 0d1e9b730..d5f916f95 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -32,6 +32,33 @@ VkShaderManager::VkShaderManager(VulkanRenderDevice* fb) : fb(fb) { + ZMinMax.vert = ShaderBuilder() + .Type(ShaderType::Vertex) + .DebugName("ZMinMax.vert") + .AddSource("VersionBlock", GetVersionBlock().GetChars()) + .AddSource("shaders/scene/vert_zminmax.glsl", LoadPrivateShaderLump("shaders/scene/vert_zminmax.glsl").GetChars()) + .Create("ZMinMax.vert", fb->GetDevice()); + + ZMinMax.frag[0] = ShaderBuilder() + .Type(ShaderType::Fragment) + .DebugName("ZMinMax0.frag") + .AddSource("VersionBlock", GetVersionBlock().GetChars()) + .AddSource("shaders/scene/frag_zminmax0.glsl", LoadPrivateShaderLump("shaders/scene/frag_zminmax0.glsl").GetChars()) + .Create("ZMinMax0.frag", fb->GetDevice()); + + ZMinMax.frag[1] = ShaderBuilder() + .Type(ShaderType::Fragment) + .DebugName("ZMinMax1.frag") + .AddSource("VersionBlock", GetVersionBlock().GetChars()) + .AddSource("shaders/scene/frag_zminmax1.glsl", LoadPrivateShaderLump("shaders/scene/frag_zminmax1.glsl").GetChars()) + .Create("ZMinMax1.frag", fb->GetDevice()); + + LightTiles = ShaderBuilder() + .Type(ShaderType::Compute) + .DebugName("LightTiles.comp") + .AddSource("VersionBlock", GetVersionBlock().GetChars()) + .AddSource("shaders/scene/comp_lighttiles.glsl", LoadPrivateShaderLump("shaders/scene/comp_lighttiles.glsl").GetChars()) + .Create("LightTiles.comp", fb->GetDevice()); } VkShaderManager::~VkShaderManager() diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 6048a993d..5e2230630 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -119,6 +119,10 @@ public: void AddVkPPShader(VkPPShader* shader); void RemoveVkPPShader(VkPPShader* shader); + VulkanShader* GetZMinMaxVertexShader() { return ZMinMax.vert.get(); } + VulkanShader* GetZMinMaxFragmentShader(int index) { return ZMinMax.frag[index].get(); } + VulkanShader* GetLightTilesShader() { return LightTiles.get(); } + private: std::unique_ptr LoadVertShader(FString shadername, const char *vert_lump, const char *defines, bool levelmesh); std::unique_ptr LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *lightmodel_lump, const char *defines, const VkShaderKey& key); @@ -134,4 +138,12 @@ private: std::map programs; std::list PPShaders; + + struct + { + std::unique_ptr vert; + std::unique_ptr frag[2]; + } ZMinMax; + + std::unique_ptr LightTiles; }; diff --git a/wadsrc/static/shaders/scene/comp_lighttiles.glsl b/wadsrc/static/shaders/scene/comp_lighttiles.glsl new file mode 100644 index 000000000..38dae0930 --- /dev/null +++ b/wadsrc/static/shaders/scene/comp_lighttiles.glsl @@ -0,0 +1,43 @@ +layout(local_size_x = 32, local_size_y = 32) in; +layout(binding = 0, rg32f) readonly uniform image2D zminmax; + +layout(binding = 1) readonly buffer Lights +{ + vec4 lights[]; +}; + +layout(binding = 1) buffer Tiles +{ + vec4 tiles[]; +}; + +layout(push_constant) uniform PushConstants +{ + int normalLightCount; + int modulatedLightCount; + int subtractiveLightCount; +}; + +void main() +{ + ivec2 zminmaxSize = imageSize(zminmax); + ivec2 tilePos = ivec2(gl_GlobalInvocationID.xy); + if (tilePos.x >= zminmaxSize.x || tilePos.y >= zminmaxSize.y) + return; + + const int maxLights = 16; + const int lightSize = 3; + int tileOffset = (tilePos.x + tilePos.y * zminmaxSize.x) * (1 + maxLights * lightSize); + + vec2 minmax = imageLoad(zminmax, tilePos).xy; + float zmin = minmax.x; + float zmax = minmax.y; + + int tileNormalCount = 0; + int tileModulatedCount = 0; + int tileSubtractiveCount = 0; + + // To do: cull and add lights + + tiles[tileOffset] = vec4(ivec4(tileNormalCount, tileModulatedCount, tileSubtractiveCount, 0)); +} diff --git a/wadsrc/static/shaders/scene/frag_zminmax0.glsl b/wadsrc/static/shaders/scene/frag_zminmax0.glsl new file mode 100644 index 000000000..4347f539d --- /dev/null +++ b/wadsrc/static/shaders/scene/frag_zminmax0.glsl @@ -0,0 +1,17 @@ + +layout(binding = 0) uniform sampler2D Texture; +layout(location = 0) out vec4 FragMinMax; + +void main() +{ + ivec2 size = textureSize(Texture, 0) - 1; + ivec2 pos = ivec2(gl_FragCoord.xy) * 2; + float z0 = texelFetch(Texture, min(pos, size), 0).w; + float z1 = texelFetch(Texture, min(pos + ivec2(1,0), size), 0).w; + float z2 = texelFetch(Texture, min(pos + ivec2(0,1), size), 0).w; + float z3 = texelFetch(Texture, min(pos + ivec2(1,1), size), 0).w; + vec2 zminmax = vec2( + min(min(min(z0, z1), z2), z3), + max(max(max(z0, z1), z2), z3)); + FragMinMax = vec4(zminmax, 0, 0); +} diff --git a/wadsrc/static/shaders/scene/frag_zminmax1.glsl b/wadsrc/static/shaders/scene/frag_zminmax1.glsl new file mode 100644 index 000000000..1b3387025 --- /dev/null +++ b/wadsrc/static/shaders/scene/frag_zminmax1.glsl @@ -0,0 +1,16 @@ + +layout(binding = 0) uniform sampler2D Texture; +layout(location = 0) out vec4 FragMinMax; + +void main() +{ + ivec2 pos = ivec2(gl_FragCoord.xy) * 2; + vec2 z0 = texelFetch(Texture, pos, 0).xy; + vec2 z1 = texelFetch(Texture, pos + ivec2(1,0), 0).xy; + vec2 z2 = texelFetch(Texture, pos + ivec2(0,1), 0).xy; + vec2 z3 = texelFetch(Texture, pos + ivec2(1,1), 0).xy; + vec2 zminmax = vec2( + min(min(min(z0.x, z1.x), z2.x), z3.x), + max(max(max(z0.y, z1.y), z2.y), z3.y)); + FragMinMax = vec4(zminmax, 0, 0); +} diff --git a/wadsrc/static/shaders/scene/vert_zminmax.glsl b/wadsrc/static/shaders/scene/vert_zminmax.glsl new file mode 100644 index 000000000..bead3156a --- /dev/null +++ b/wadsrc/static/shaders/scene/vert_zminmax.glsl @@ -0,0 +1,14 @@ + +vec2 positions[6] = vec2[]( + vec2(-1.0, -1.0), + vec2( 1.0, -1.0), + vec2(-1.0, 1.0), + vec2(-1.0, 1.0), + vec2( 1.0, -1.0), + vec2( 1.0, 1.0) +); + +void main() +{ + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); +}