From afa84afc79c9b4fd8c7f285735c30682a05a1020 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Jun 2023 13:19:10 +0900 Subject: [PATCH] [vulkan] Abandon light splats They were an interesting idea and might be useful in the future, but they don't work as well as I had hoped for quake's maps due to the overlapping light volumes causing contention while doing the additive blends in the frame buffer. The cause was made obvious when testing in the marcher map: most of its over 400 lights have infinite radius thus require full screen passes: all those passes fighting for the frame buffer did very nasty things to performance. However, light splats might be useful for many small, non-overlapping light volumes, thus the code is being kept (and I like the cleanups that came with it). --- libs/video/renderer/vulkan/rp_main_def.plist | 34 +++------- .../renderer/vulkan/shader/lighting.frag | 51 +++----------- libs/video/renderer/vulkan/vulkan_lighting.c | 68 +++++++++++++------ 3 files changed, 68 insertions(+), 85 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 17d9dcc2f..60711e15b 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -560,6 +560,11 @@ properties = { name = main; module = $builtin/light_splat.frag; }; + fragment = { + stage = fragment; + name = main; + module = $builtin/lighting.frag; + }; debug_fragment = { stage = fragment; name = main; @@ -1439,45 +1444,26 @@ renderpasses = { color = { light = { layout = color_attachment_optimal; - blend = $additive_blend; + blend = $blend_disable; }; }; preserve = (output); }; pipelines = { - light_splats = { + lights = { @inherit = $compose_base; color = $color.lights; tasks = ( { func = lighting_update_descriptors; }, { func = lighting_bind_descriptors; }, - { func = lighting_draw_splats; }, + { func = lighting_draw_lights; }, ); stages = ( - $lighting.shader.vertex_splat, - $lighting.shader.fragment_splat, + $fstriangle.shader.vertex, + $lighting.shader.fragment, ); - vertexInput = $lighting.vertexInput_splat; - inputAssembly = $lighting.inputAssembly; - layout = $lighting.layout; - rasterization = $cw_cull_back; - //depthStencil = $depth_disable; - }; - light_flat = { - @inherit = $compose_base; - - color = $color.lights; - tasks = ( - { func = lighting_draw_flats; }, - ); - - stages = ( - $lighting.shader.vertex_flat, - $lighting.shader.fragment_splat, - ); - vertexInput = $lighting.vertexInput_flat; layout = $lighting.layout; }; }; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 3e100a55c..1a2f34c60 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -1,46 +1,17 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput depth; -layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput color; -layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput emission; -layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput normal; -layout (input_attachment_index = 4, set = 0, binding = 4) uniform subpassInput position; +#include "lighting.h" -struct LightData { - vec4 color; // .a is intensity - vec4 position; // .w = 0 -> directional, .w = 1 -> point/cone - vec4 direction; // .w = -cos(cone_angle/2) (1 for omni/dir) - vec4 attenuation; -}; +layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput depth; +layout (input_attachment_index = 1, set = 2, binding = 1) uniform subpassInput color; +layout (input_attachment_index = 2, set = 2, binding = 2) uniform subpassInput emission; +layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInput normal; +layout (input_attachment_index = 4, set = 2, binding = 4) uniform subpassInput position; -#define StyleMask 0x07f -#define ModelMask 0x380 -#define ShadowMask 0xc00 - -#define LM_LINEAR (0 << 7) // light - dist (or radius + dist if -ve) -#define LM_INVERSE (1 << 7) // distFactor1 * light / dist -#define LM_INVERSE2 (2 << 7) // distFactor2 * light / (dist * dist) -#define LM_INFINITE (3 << 7) // light -#define LM_AMBIENT (4 << 7) // light -#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2 - -#define ST_NONE (0 << 10) // no shadows -#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight) -#define ST_CASCADE (2 << 10) // cascaded shadow maps -#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight) - -layout (constant_id = 0) const int MaxLights = 768; - -layout (set = 2, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights]; -layout (set = 2, binding = 0) uniform sampler2DShadow shadowPlane[MaxLights]; -layout (set = 2, binding = 0) uniform samplerCubeShadow shadowCube[MaxLights]; - -layout (set = 1, binding = 0) uniform Lights { - LightData lights[MaxLights]; - int lightCount; - //mat4 shadowMat[MaxLights]; - //vec4 shadowCascale[MaxLights]; -}; +layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights]; +layout (set = 3, binding = 0) uniform sampler2DShadow shadowPlane[MaxLights]; +layout (set = 3, binding = 0) uniform samplerCubeShadow shadowCube[MaxLights]; layout (location = 0) out vec4 frag_color; @@ -118,5 +89,5 @@ main (void) } //light = max (light, minLight); - frag_color = vec4 (c * light + e, 1); + frag_color = vec4 (light, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 19e5e7007..1d8c506aa 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -248,19 +248,20 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, QFV_PacketCopyBuffer (packet, lframe->data_buffer, 0, &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); QFV_PacketSubmit (packet); - - packet = QFV_PacketAcquire (ctx->staging); - uint32_t id_count = lframe->ico_count + lframe->cone_count - + lframe->flat_count; - uint32_t *ids = QFV_PacketExtend (packet, id_count * sizeof (uint32_t)); - memcpy (ids, ico_ids, lframe->ico_count * sizeof (uint32_t)); - ids += lframe->ico_count; - memcpy (ids, cone_ids, lframe->cone_count * sizeof (uint32_t)); - ids += lframe->cone_count; - memcpy (ids, flat_ids, lframe->flat_count * sizeof (uint32_t)); - QFV_PacketCopyBuffer (packet, lframe->id_buffer, 0, + if (0) { + packet = QFV_PacketAcquire (ctx->staging); + uint32_t id_count = lframe->ico_count + lframe->cone_count + + lframe->flat_count; + uint32_t *ids = QFV_PacketExtend (packet, id_count * sizeof (uint32_t)); + memcpy (ids, ico_ids, lframe->ico_count * sizeof (uint32_t)); + ids += lframe->ico_count; + memcpy (ids, cone_ids, lframe->cone_count * sizeof (uint32_t)); + ids += lframe->cone_count; + memcpy (ids, flat_ids, lframe->flat_count * sizeof (uint32_t)); + QFV_PacketCopyBuffer (packet, lframe->id_buffer, 0, &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); - QFV_PacketSubmit (packet); + QFV_PacketSubmit (packet); + } } static VkDescriptorBufferInfo base_buffer_info = { @@ -334,15 +335,16 @@ lighting_bind_descriptors (const exprval_t **params, exprval_t *result, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 3, sets, 0, 0); - - VkBuffer buffers[] = { - lframe->id_buffer, - lctx->splat_verts, - }; - VkDeviceSize offsets[] = { 0, 0 }; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 2, buffers, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, lctx->splat_inds, 0, - VK_INDEX_TYPE_UINT32); + if (0) { + VkBuffer buffers[] = { + lframe->id_buffer, + lctx->splat_verts, + }; + VkDeviceSize offsets[] = { 0, 0 }; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 2, buffers, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, lctx->splat_inds, 0, + VK_INDEX_TYPE_UINT32); + } } static void @@ -386,6 +388,25 @@ lighting_draw_flats (const exprval_t **params, exprval_t *result, dfunc->vkCmdDraw (cmd, 3, lframe->flat_count, 0, splat_count); } +static void +lighting_draw_lights (const exprval_t **params, exprval_t *result, + exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto lctx = ctx->lighting_context; + auto cmd = taskctx->cmd; + + auto lframe = &lctx->frames.a[ctx->curFrame]; + if (!(lframe->ico_count + lframe->cone_count + lframe->flat_count)) { + return; + } + + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); +} + static exprfunc_t lighting_update_lights_func[] = { { .func = lighting_update_lights }, {} @@ -406,6 +427,10 @@ static exprfunc_t lighting_draw_flats_func[] = { { .func = lighting_draw_flats }, {} }; +static exprfunc_t lighting_draw_lights_func[] = { + { .func = lighting_draw_lights }, + {} +}; static exprsym_t lighting_task_syms[] = { { "lighting_update_lights", &cexpr_function, lighting_update_lights_func }, { "lighting_update_descriptors", &cexpr_function, @@ -414,6 +439,7 @@ static exprsym_t lighting_task_syms[] = { lighting_bind_descriptors_func }, { "lighting_draw_splats", &cexpr_function, lighting_draw_splats_func }, { "lighting_draw_flats", &cexpr_function, lighting_draw_flats_func }, + { "lighting_draw_lights", &cexpr_function, lighting_draw_lights_func }, {} };