From a626dc7ca89a6be7f79150a52d09b20c3389bb32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Aug 2023 17:52:57 +0900 Subject: [PATCH] [vulkan] Split the lighting pass into per-type passes This takes care of the type punning issue by each pass using the correct sampler type with the correct view types bound. Also, point light and spot light shadow maps are now guaranteed to be separated (it was just luck that they were before) and spot light maps may be significantly smaller as their cone angle is taken into account. Lighting is quite borked, but at least the engine is running again. --- include/QF/Vulkan/qf_lighting.h | 23 +- libs/video/renderer/Makemodule.am | 31 +- libs/video/renderer/vulkan/rp_main_def.plist | 39 +- libs/video/renderer/vulkan/shader.c | 15 +- .../renderer/vulkan/shader/light_attach.h | 4 + libs/video/renderer/vulkan/shader/lighting.h | 1 - .../vulkan/shader/lighting_cascade.frag | 12 + .../renderer/vulkan/shader/lighting_cube.frag | 17 + .../{lighting.frag => lighting_main.finc} | 50 +- .../renderer/vulkan/shader/lighting_none.frag | 10 + .../vulkan/shader/lighting_plane.frag | 12 + libs/video/renderer/vulkan/vulkan_lighting.c | 557 ++++++++++++------ 12 files changed, 512 insertions(+), 259 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/light_attach.h create mode 100644 libs/video/renderer/vulkan/shader/lighting_cascade.frag create mode 100644 libs/video/renderer/vulkan/shader/lighting_cube.frag rename libs/video/renderer/vulkan/shader/{lighting.frag => lighting_main.finc} (53%) create mode 100644 libs/video/renderer/vulkan/shader/lighting_none.frag create mode 100644 libs/video/renderer/vulkan/shader/lighting_plane.frag diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 7424dca2d..29bf1f9a6 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -49,11 +49,6 @@ typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t; #define ST_CASCADE 2 // cascaded shadow maps #define ST_CUBE 3 // cubemap (omni, large spotlight) -typedef struct qfv_lightid_buffer_s { - uint32_t lightCount; - uint32_t lightIds[MaxLights]; -} qfv_lightid_buffer_t; - typedef struct qfv_light_render_s { // mat_id (13) map_id (5) layer (11) type (2) uint32_t id_data; @@ -69,6 +64,11 @@ typedef struct qfv_light_render_s { typedef struct qfv_framebufferset_s DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t; +typedef struct light_queue_s { + uint16_t start; + uint16_t count; +} light_queue_t; + typedef struct lightingframe_s { VkDescriptorSet shadowmat_set; VkDescriptorSet lights_set; @@ -79,6 +79,7 @@ typedef struct lightingframe_s { VkBuffer render_buffer; VkBuffer style_buffer; VkBuffer id_buffer; + light_queue_t light_queue[4]; uint32_t ico_count; uint32_t cone_count; uint32_t flat_count; @@ -113,15 +114,21 @@ typedef struct lightingctx_s { struct qfv_resource_s *light_resources; qfv_lightmatset_t light_mats; - qfv_imageset_t light_images; - qfv_imageviewset_t light_views; + VkImage *map_images; + VkImageView *map_views; + bool *map_cube; + int num_maps; + VkImage default_map; + VkImageView default_view_cube; + VkImageView default_view_2d; light_control_set_t light_control; qfv_attachmentinfo_t shadow_info; VkSampler shadow_sampler; - VkDescriptorSet shadow_set; + VkDescriptorSet shadow_cube_set; + VkDescriptorSet shadow_2d_set; VkBuffer splat_verts; VkBuffer splat_inds; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d5883a28b..7545ebc90 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -330,6 +330,7 @@ bsp_turbf_src = $(vkshaderpath)/bsp_turb.frag bsp_turbf_c = $(vkshaderpath)/bsp_turb.frag.spvc debug_src = $(vkshaderpath)/debug.frag debug_c = $(vkshaderpath)/debug.frag.spvc +light_attach_h = $(vkshaderpath)/light_attach.h light_flat_src = $(vkshaderpath)/light_flat.vert light_flat_c = $(vkshaderpath)/light_flat.vert.spvc light_splatv_src = $(vkshaderpath)/light_splat.vert @@ -338,8 +339,15 @@ light_splatf_src = $(vkshaderpath)/light_splat.frag light_splatf_c = $(vkshaderpath)/light_splat.frag.spvc light_debug_src = $(vkshaderpath)/light_debug.frag light_debug_c = $(vkshaderpath)/light_debug.frag.spvc -lightingf_src = $(vkshaderpath)/lighting.frag -lightingf_c = $(vkshaderpath)/lighting.frag.spvc +lighting_cascadef_src = $(vkshaderpath)/lighting_cascade.frag +lighting_cascadef_c = $(vkshaderpath)/lighting_cascade.frag.spvc +lighting_cubef_src = $(vkshaderpath)/lighting_cube.frag +lighting_cubef_c = $(vkshaderpath)/lighting_cube.frag.spvc +lighting_main = $(vkshaderpath)/lighting_main.finc +lighting_nonef_src = $(vkshaderpath)/lighting_none.frag +lighting_nonef_c = $(vkshaderpath)/lighting_none.frag.spvc +lighting_planef_src = $(vkshaderpath)/lighting_plane.frag +lighting_planef_c = $(vkshaderpath)/lighting_plane.frag.spvc lighting_h = $(vkshaderpath)/lighting.h composef_src = $(vkshaderpath)/compose.frag composef_c = $(vkshaderpath)/compose.frag.spvc @@ -437,7 +445,13 @@ $(light_splatf_c): $(light_splatf_src) $(lighting_h) $(light_debug_c): $(light_debug_src) $(lighting_h) -$(lightingf_c): $(lightingf_src) $(lighting_h) +$(lighting_nonef_c): $(lighting_nonef_src) $(lighting_h) $(light_attach_h) $(lighting_main) + +$(lighting_cascadef_c): $(lighting_cascadef_src) $(lighting_h) $(light_attach_h) $(lighting_main) + +$(lighting_cubef_c): $(lighting_cubef_src) $(lighting_h) $(light_attach_h) $(lighting_main) + +$(lighting_planef_c): $(lighting_planef_src) $(lighting_h) $(light_attach_h) $(lighting_main) $(composef_c): $(composef_src) $(oit_blend) $(oit_h) @@ -504,7 +518,10 @@ vkshader_c = \ $(light_splatv_c) \ $(light_splatf_c) \ $(light_debug_c) \ - $(lightingf_c) \ + $(lighting_cascadef_c) \ + $(lighting_cubef_c) \ + $(lighting_nonef_c) \ + $(lighting_planef_c) \ $(composef_c) \ $(aliasv_c) \ $(alias_depth_c) \ @@ -591,11 +608,15 @@ EXTRA_DIST += \ $(bsp_skyf_src) \ $(bsp_turbf_src) \ $(debug_src) \ + $(light_attach_h) \ $(light_flat_src) \ $(light_splatv_src) \ $(light_splatf_src) \ $(light_debug_src) \ - $(lightingf_src) \ + $(lighting_cascadef_src) \ + $(lighting_cubef_src) \ + $(lighting_nonef_src) \ + $(lighting_planef_src) \ $(lighting_h) \ $(composef_src) \ $(aliasv_src) \ diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 79327af0f..17ba2f3a8 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -618,51 +618,25 @@ properties = { name = main; module = $builtin/light_splat.frag; }; - shadow_specialization = { - mapEntries = ( - // ShadowType - { size = 4; offset = 0; constantID = 0; }, - ); - }; fragment_none = { stage = fragment; name = main; - module = $builtin/lighting.frag; - specializationInfo = { - @inherit = $lighting.shader.shadow_specialization; - // ShadowType - data = "array(0)"; - }; + module = $builtin/lighting_none.frag; }; fragment_plane = { stage = fragment; name = main; - module = $builtin/lighting.frag; - specializationInfo = { - @inherit = $lighting.shader.shadow_specialization; - // ShadowType - data = "array(1)"; - }; + module = $builtin/lighting_plane.frag; }; fragment_cascade = { stage = fragment; name = main; - module = $builtin/lighting.frag; - specializationInfo = { - @inherit = $lighting.shader.shadow_specialization; - // ShadowType - data = "array(2)"; - }; + module = $builtin/lighting_cascade.frag; }; fragment_cube = { stage = fragment; name = main; - module = $builtin/lighting.frag; - specializationInfo = { - @inherit = $lighting.shader.shadow_specialization; - // ShadowType - data = "array(3)"; - }; + module = $builtin/lighting_cube.frag; }; debug_fragment = { stage = fragment; @@ -698,6 +672,11 @@ properties = { layout = { descriptorSets = (shadowmat_set, lighting_lights, lighting_attach, lighting_shadow); + pushConstants = { + fragment = { + queue = uint; + }; + }; }; }; compose = { diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index d03ddd5e2..5b372ba5a 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -99,7 +99,13 @@ static static #include "libs/video/renderer/vulkan/shader/light_debug.frag.spvc" static -#include "libs/video/renderer/vulkan/shader/lighting.frag.spvc" +#include "libs/video/renderer/vulkan/shader/lighting_cascade.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/lighting_cube.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/lighting_none.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/lighting_plane.frag.spvc" static #include "libs/video/renderer/vulkan/shader/compose.frag.spvc" static @@ -172,7 +178,12 @@ static shaderdata_t builtin_shaders[] = { { "light_splat.vert", light_splat_vert, sizeof (light_splat_vert) }, { "light_splat.frag", light_splat_frag, sizeof (light_splat_frag) }, { "light_debug.frag", light_debug_frag, sizeof (light_debug_frag) }, - { "lighting.frag", lighting_frag, sizeof (lighting_frag) }, + { "lighting_cascade.frag", lighting_cascade_frag, + sizeof (lighting_cascade_frag) }, + { "lighting_cube.frag", lighting_cube_frag, sizeof (lighting_cube_frag) }, + { "lighting_none.frag", lighting_none_frag, sizeof (lighting_none_frag) }, + { "lighting_plane.frag", lighting_plane_frag, + sizeof (lighting_plane_frag) }, { "compose.frag", compose_frag, sizeof (compose_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, diff --git a/libs/video/renderer/vulkan/shader/light_attach.h b/libs/video/renderer/vulkan/shader/light_attach.h new file mode 100644 index 000000000..2876d4858 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/light_attach.h @@ -0,0 +1,4 @@ +layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput color; +layout (input_attachment_index = 1, set = 2, binding = 1) uniform subpassInput emission; +layout (input_attachment_index = 2, set = 2, binding = 2) uniform subpassInput normal; +layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInput position; diff --git a/libs/video/renderer/vulkan/shader/lighting.h b/libs/video/renderer/vulkan/shader/lighting.h index 48a31dbae..77a0c5c91 100644 --- a/libs/video/renderer/vulkan/shader/lighting.h +++ b/libs/video/renderer/vulkan/shader/lighting.h @@ -16,7 +16,6 @@ struct LightRender { }; layout (set = 1, binding = 0) buffer LightIds { - uint lightCount; uint lightIds[]; }; layout (set = 1, binding = 1) buffer Lights { diff --git a/libs/video/renderer/vulkan/shader/lighting_cascade.frag b/libs/video/renderer/vulkan/shader/lighting_cascade.frag new file mode 100644 index 000000000..7f453a0ed --- /dev/null +++ b/libs/video/renderer/vulkan/shader/lighting_cascade.frag @@ -0,0 +1,12 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadow_map[32]; + +float +shadow (uint map_id, uint layer, uint mat_id, vec3 pos) +{ + return 1; +} + +#include "lighting_main.finc" diff --git a/libs/video/renderer/vulkan/shader/lighting_cube.frag b/libs/video/renderer/vulkan/shader/lighting_cube.frag new file mode 100644 index 000000000..05fab8045 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/lighting_cube.frag @@ -0,0 +1,17 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout (set = 0, binding = 0) buffer ShadowMatrices { + mat4 shadow_mats[]; +}; +layout (set = 3, binding = 0) uniform samplerCubeArrayShadow shadow_map[32]; + +float +shadow (uint map_id, uint layer, uint mat_id, vec3 pos) +{ + vec4 p = shadow_mats[mat_id] * vec4 (pos, 1); + float depth = (p / p.w).z; + return texture (shadow_map[map_id], vec4 (p.xyz, layer), depth); +} + +#include "lighting_main.finc" diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting_main.finc similarity index 53% rename from libs/video/renderer/vulkan/shader/lighting.frag rename to libs/video/renderer/vulkan/shader/lighting_main.finc index eb7c08eed..ceb5bd151 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting_main.finc @@ -1,20 +1,11 @@ -#version 450 -#extension GL_GOOGLE_include_directive : enable - #include "lighting.h" - -layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput color; -layout (input_attachment_index = 1, set = 2, binding = 1) uniform subpassInput emission; -layout (input_attachment_index = 2, set = 2, binding = 2) uniform subpassInput normal; -layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInput position; - -layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadowCascade[32]; -layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadowPlane[32]; -layout (set = 3, binding = 0) uniform samplerCubeArrayShadow shadowCube[32]; +#include "light_attach.h" layout (location = 0) out vec4 frag_color; -layout (constant_id = 0) const int ShadowType = ST_NONE; +layout (push_constant) uniform PushConstants { + uint queue; +}; float spot_cone (LightData light, vec3 incoming) @@ -32,24 +23,6 @@ diffuse (vec3 incoming, vec3 normal) return clamp (lightdot, 0, 1); } -float -shadow_cascade (sampler2DArrayShadow map, uint layer, uint mat_id, vec3 pos) -{ - return 1; -} - -float -shadow_plane (sampler2DArrayShadow map, uint layer, uint mat_id, vec3 pos) -{ - return 1; -} - -float -shadow_cube (samplerCubeArrayShadow map, uint layer, uint mat_id, vec3 pos) -{ - return 1; -} - void main (void) { @@ -59,8 +32,10 @@ main (void) vec3 p = subpassLoad (position).rgb; vec3 light = vec3 (0); - //vec3 minLight = vec3 (0); - for (int i = 0; i < lightCount; i++) { + uint start = bitfieldExtract (queue, 0, 16); + uint count = bitfieldExtract (queue, 16, 16); + + for (uint i = start; i < count; i++) { uint id = lightIds[i]; LightData l = lights[id]; vec3 dir = l.position.xyz - l.position.w * p; @@ -78,13 +53,8 @@ main (void) uint mat_id = bitfieldExtract (id_data, 0, 13); uint map_id = bitfieldExtract (id_data, 13, 5); uint layer = bitfieldExtract (id_data, 18, 11); - if (ShadowType == ST_CASCADE) { - I *= shadow_cascade (shadowCascade[map_id], layer, mat_id, p); - } else if (ShadowType == ST_PLANE) { - I *= shadow_plane (shadowPlane[map_id], layer, mat_id, p); - } else if (ShadowType == ST_CUBE) { - I *= shadow_cube (shadowCube[map_id], layer, mat_id, p); - } + + I *= shadow (map_id, layer, mat_id, p); float namb = dot(l.direction.xyz, l.direction.xyz); I *= spot_cone (l, incoming) * diffuse (incoming, n); diff --git a/libs/video/renderer/vulkan/shader/lighting_none.frag b/libs/video/renderer/vulkan/shader/lighting_none.frag new file mode 100644 index 000000000..12f908d7e --- /dev/null +++ b/libs/video/renderer/vulkan/shader/lighting_none.frag @@ -0,0 +1,10 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +float +shadow (uint mapid, uint layer, uint mat_id, vec3 pos) +{ + return 1; +} + +#include "lighting_main.finc" diff --git a/libs/video/renderer/vulkan/shader/lighting_plane.frag b/libs/video/renderer/vulkan/shader/lighting_plane.frag new file mode 100644 index 000000000..7f453a0ed --- /dev/null +++ b/libs/video/renderer/vulkan/shader/lighting_plane.frag @@ -0,0 +1,12 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadow_map[32]; + +float +shadow (uint map_id, uint layer, uint mat_id, vec3 pos) +{ + return 1; +} + +#include "lighting_main.finc" diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index b578798c2..62fd1f324 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -94,13 +94,13 @@ static int cone_inds[] = { 1, 6, 5, 4, 3, 2, }; #define num_cone_inds (sizeof (cone_inds) / sizeof (cone_inds[0])) - +#if 0 static const light_t * get_light (entity_t ent) { return Ent_GetComponent (ent.id, scene_light, ent.reg); } - +#endif static uint32_t get_lightstyle (entity_t ent) { @@ -188,7 +188,7 @@ create_view (vulkan_ctx_t *ctx, light_control_t *renderer) VkImageViewCreateInfo cInfo = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = lctx->light_images.a[renderer->map_index], + .image = lctx->map_images[renderer->map_index], .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, .format = VK_FORMAT_X8_D24_UNORM_PACK32, .subresourceRange = { @@ -252,7 +252,7 @@ lighting_draw_shadow_maps (const exprval_t **params, exprval_t *result, auto render = shadow->render; auto lframe = &lctx->frames.a[ctx->curFrame]; - if (!lctx->ldata) { + if (!lctx->num_maps) { return; } //auto pass = Vulkan_Bsp_GetAuxPass (ctx); @@ -293,6 +293,7 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, lframe->ico_count = 0; lframe->cone_count = 0; lframe->flat_count = 0; + memset (lframe->light_queue, 0, sizeof (lframe->light_queue)); if (!lctx->scene || !lctx->scene->lights) { return; } @@ -307,11 +308,10 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, QFV_PacketCopyBuffer (packet, lframe->style_buffer, 0, bb); QFV_PacketSubmit (packet); - uint32_t ico_ids[MaxLights]; - uint32_t cone_ids[MaxLights]; - uint32_t flat_ids[MaxLights]; + uint32_t ids[4][MaxLights]; uint32_t light_count = 0; + auto queue = lframe->light_queue; dlight_t *dynamic_lights[MaxLights]; int maxdlight = MaxLights - lctx->dynamic_base; @@ -322,7 +322,9 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, packet = QFV_PacketAcquire (ctx->staging); light_t *lights = QFV_PacketExtend (packet, sizeof (light_t[ndlight])); for (int i = 0; i < ndlight; i++) { - ico_ids[lframe->ico_count++] = lctx->dynamic_base + light_count++; + uint32_t id = lctx->dynamic_base + light_count++; + //FIXME should be ST_CUBE but need to alloc maps for dlights + ids[ST_NONE][queue[ST_NONE].count++] = id; VectorCopy (dynamic_lights[i]->color, lights[i].color); // dynamic lights seem a tad faint, so 16x map lights @@ -355,10 +357,9 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, QFV_PacketSubmit (packet); } - auto queue = r_ent_queue; //FIXME fetch from scene - for (size_t i = 0; i < queue->ent_queues[mod_light].size; i++) { - entity_t ent = queue->ent_queues[mod_light].a[i]; - auto l = get_light (ent); + auto entqueue = r_ent_queue; //FIXME fetch from scene + for (size_t i = 0; i < entqueue->ent_queues[mod_light].size; i++) { + entity_t ent = entqueue->ent_queues[mod_light].a[i]; auto ls = get_lightstyle (ent); if (!d_lightstylevalue[ls]) { continue; @@ -366,16 +367,8 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, light_count++; uint32_t id = lctx->light_control.a[get_lightid (ent)].light_id; - if (l->position[3] && !VectorIsZero (l->direction) - && l->attenuation[3]) { - if (l->direction[3] < 0) { - cone_ids[lframe->cone_count++] = id; - } else { - ico_ids[lframe->ico_count++] = id; - } - } else { - flat_ids[lframe->flat_count++] = id; - } + int mode = lctx->light_control.a[get_lightid (ent)].mode; + ids[mode][queue[mode].count++] = id; } if (developer & SYS_lighting) { Vulkan_Draw_String (vid.width - 32, 8, @@ -383,21 +376,17 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, ctx); } - uint32_t id_count = lframe->ico_count + lframe->cone_count - + lframe->flat_count; - if (id_count != light_count) { - Sys_Error ("taniwha can't count: %d != %d", id_count, light_count); - } - if (id_count) { + if (light_count) { + for (int i = 1; i < 4; i++) { + queue[i].start = queue[i - 1].start + queue[i - 1].count; + } packet = QFV_PacketAcquire (ctx->staging); - uint32_t *count = QFV_PacketExtend (packet, sizeof (uint32_t)); - *count = id_count; - uint32_t *ids = QFV_PacketExtend (packet, sizeof (uint32_t[id_count])); - 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)); + uint32_t *lids = QFV_PacketExtend (packet, + sizeof (uint32_t[light_count])); + for (int i = 0; i < 4; i++) { + memcpy (lids + queue[i].start, ids[i], + sizeof (uint32_t[queue[i].count])); + } QFV_PacketCopyBuffer (packet, lframe->id_buffer, 0, &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); QFV_PacketSubmit (packet); @@ -470,17 +459,25 @@ lighting_bind_descriptors (const exprval_t **params, exprval_t *result, auto device = ctx->device; auto dfunc = device->funcs; auto lctx = ctx->lighting_context; + if (!lctx->num_maps) { + return; + } auto cmd = taskctx->cmd; auto layout = taskctx->pipeline->layout; auto lframe = &lctx->frames.a[ctx->curFrame]; + auto shadow_type = *(int *) params[0]->value; VkDescriptorSet sets[] = { - //Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), lframe->shadowmat_set, lframe->lights_set, lframe->attach_set, - lctx->shadow_set, + (VkDescriptorSet[]) { + lctx->shadow_2d_set, + lctx->shadow_2d_set, + lctx->shadow_2d_set, + lctx->shadow_cube_set + }[shadow_type], }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 4, sets, 0, 0); @@ -546,13 +543,22 @@ lighting_draw_lights (const exprval_t **params, exprval_t *result, auto device = ctx->device; auto dfunc = device->funcs; auto lctx = ctx->lighting_context; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; auto lframe = &lctx->frames.a[ctx->curFrame]; - if (!(lframe->ico_count + lframe->cone_count + lframe->flat_count)) { + auto shadow_type = *(int *) params[0]->value; + auto queue = lframe->light_queue[shadow_type]; + + if (!queue.count) { return; } + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (queue), &queue }, + }; + QFV_PushConstants (device, cmd, layout, 1, push_constants); + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } @@ -661,6 +667,54 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) QFV_Render_AddAttachments (ctx, 1, attachments); } +static void +make_default_map (int size, VkImage default_map, vulkan_ctx_t *ctx) +{ + auto device = ctx->device; + auto dfunc = device->funcs; + + auto packet = QFV_PacketAcquire (ctx->staging); + size_t imgsize = size * size * sizeof (uint32_t); + uint32_t *img = QFV_PacketExtend (packet, imgsize); + for (int i = 0; i < 64; i++) { + for (int j = 0; j < 64; j++) { + img[i * 64 + j] = ((j ^ i) & 1) ? 0x00ffffff : 0; + } + } + + auto ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = default_map; + ib.barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, 1, &ib.barrier); + + VkBufferImageCopy copy_region[6]; + for (int i = 0; i < 6; i++) { + copy_region[i] = (VkBufferImageCopy) { + .bufferOffset = packet->offset, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, i, 1}, + {0, 0, 0}, {size, size, 1}, + }; + } + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + default_map, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 6, copy_region); + + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = default_map; + ib.barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, 1, &ib.barrier); + QFV_PacketSubmit (packet); +} + static void make_ico (qfv_packet_t *packet) { @@ -732,8 +786,6 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) #endif DARRAY_INIT (&lctx->light_mats, 16); - DARRAY_INIT (&lctx->light_images, 16); - DARRAY_INIT (&lctx->light_views, 16); DARRAY_INIT (&lctx->light_control, 16); auto rctx = ctx->render_context; @@ -747,6 +799,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) + sizeof (qfv_resobj_t) // splat indices + sizeof (qfv_resobj_t) + // default shadow map and views + + 3 * sizeof (qfv_resobj_t) // light ids + sizeof (qfv_resobj_t[frames]) // light data @@ -757,20 +811,23 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) + sizeof (qfv_resobj_t[frames]) // light matrices + sizeof (qfv_resobj_t[frames])); - auto splat_verts = (qfv_resobj_t *) &lctx->light_resources[1]; - auto splat_inds = &splat_verts[1]; - auto light_ids = &splat_inds[1]; - auto light_data = &light_ids[frames]; - auto light_render = &light_data[frames]; - auto light_styles = &light_render[frames]; - auto light_mats = &light_styles[frames]; lctx->light_resources[0] = (qfv_resource_t) { .name = "lights", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .num_objects = 2 + 5 * frames, - .objects = splat_verts, + .num_objects = 2 + 3 + 5 * frames, + .objects = (qfv_resobj_t *) &lctx->light_resources[1], }; + auto splat_verts = lctx->light_resources->objects; + auto splat_inds = &splat_verts[1]; + auto default_map = &splat_inds[1]; + auto default_view_cube = &default_map[1]; + auto default_view_2d = &default_view_cube[1]; + auto light_ids = &default_view_2d[1]; + auto light_data = &light_ids[frames]; + auto light_render = &light_data[frames]; + auto light_styles = &light_render[frames]; + auto light_mats = &light_styles[frames]; splat_verts[0] = (qfv_resobj_t) { .name = "splat:vertices", .type = qfv_res_buffer, @@ -789,6 +846,49 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, }, }; + default_map[0] = (qfv_resobj_t) { + .name = "default_map", + .type = qfv_res_image, + .image = { + .flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, + .type = VK_IMAGE_TYPE_2D, + .format = VK_FORMAT_X8_D24_UNORM_PACK32, + .extent = { 64, 64, 1 }, + .num_mipmaps = 1, + .num_layers = 6, + .samples = VK_SAMPLE_COUNT_1_BIT, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, + }, + }; + default_view_cube[0] = (qfv_resobj_t) { + .name = "default_map:view_cube", + .type = qfv_res_image_view, + .image_view = { + .image = default_map - lctx->light_resources->objects, + .type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, + .format = VK_FORMAT_X8_D24_UNORM_PACK32, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, + .levelCount = VK_REMAINING_MIP_LEVELS, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }, + }; + default_view_2d[0] = (qfv_resobj_t) { + .name = "default_map:view_2d", + .type = qfv_res_image_view, + .image_view = { + .image = default_map - lctx->light_resources->objects, + .type = VK_IMAGE_VIEW_TYPE_2D_ARRAY, + .format = VK_FORMAT_X8_D24_UNORM_PACK32, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, + .levelCount = VK_REMAINING_MIP_LEVELS, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }, + }; for (size_t i = 0; i < frames; i++) { light_ids[i] = (qfv_resobj_t) { .name = "ids", @@ -843,11 +943,17 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) lctx->splat_verts = splat_verts[0].buffer.buffer; lctx->splat_inds = splat_inds[0].buffer.buffer; + lctx->default_map = default_map[0].image.image; + lctx->default_view_cube = default_view_cube[0].image_view.view; + lctx->default_view_2d = default_view_2d[0].image_view.view; auto shadow_mgr = QFV_Render_DSManager (ctx, "lighting_shadow"); - lctx->shadow_set = QFV_DSManager_AllocSet (shadow_mgr); + lctx->shadow_cube_set = QFV_DSManager_AllocSet (shadow_mgr); + lctx->shadow_2d_set = QFV_DSManager_AllocSet (shadow_mgr); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, - lctx->shadow_set, "lighting:shadow_set"); + lctx->shadow_cube_set, "lighting:shadow_cube_set"); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, + lctx->shadow_2d_set, "lighting:shadow_2d_set"); lctx->shadow_sampler = QFV_Render_Sampler (ctx, "shadow_sampler"); auto attach_mgr = QFV_Render_DSManager (ctx, "lighting_attach"); @@ -927,6 +1033,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) dfunc->vkUpdateDescriptorSets (device->dev, 5, bufferWrite, 0, 0); } + make_default_map (64, lctx->default_map, ctx); + auto packet = QFV_PacketAcquire (ctx->staging); make_ico (packet); make_cone (packet); @@ -953,8 +1061,13 @@ clear_shadows (vulkan_ctx_t *ctx) free (lctx->shadow_resources); lctx->shadow_resources = 0; } - lctx->light_images.size = 0; - lctx->light_views.size = 0; + free (lctx->map_images); + free (lctx->map_views); + free (lctx->map_cube); + lctx->map_images = 0; + lctx->map_views = 0; + lctx->map_cube = 0; + lctx->num_maps = 0; lctx->light_control.size = 0; } @@ -977,9 +1090,10 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) } DARRAY_CLEAR (&lctx->light_mats); - DARRAY_CLEAR (&lctx->light_images); - DARRAY_CLEAR (&lctx->light_views); DARRAY_CLEAR (&lctx->light_control); + free (lctx->map_images); + free (lctx->map_views); + free (lctx->map_cube); free (lctx->frames.a); free (lctx); } @@ -1129,6 +1243,23 @@ upload_light_data (lightingctx_t *lctx, vulkan_ctx_t *ctx) lctx->dynamic_count = 0; } +static int +light_shadow_type (const light_t *light) +{ + if (!light->position[3]) { + if (!VectorIsZero (light->direction)) { + return ST_CASCADE; + } + } else { + if (light->direction[3] > -0.5) { + return ST_CUBE; + } else { + return ST_PLANE; + } + } + return ST_NONE; +} + static int light_compare (const void *_li2, const void *_li1, void *_lights) { @@ -1149,14 +1280,91 @@ light_compare (const void *_li2, const void *_li1, void *_lights) return s1 - s2; } +typedef struct { + int size; + int layers; + int cube; +} mapdesc_t; + +typedef struct { + mapdesc_t *maps; + int numMaps; + int numLights; + const light_t *lights; + int *imageMap; + const int *lightMap; + light_control_t *control; + int maxLayers; +} mapctx_t; + +static int +allocate_map (mapctx_t *mctx, int type, int (*getsize) (const light_t *light)) +{ + int size = -1; + int numLayers = 0; + int totalLayers = 0; + int layers = ((int[4]) { 0, 1, 4, 6 })[type]; + int cube = type == ST_CUBE; + + for (int i = 0; i < mctx->numLights; i++) { + auto li = mctx->lightMap[i]; + auto lr = &mctx->control[li]; + + if (lr->mode != type) { + continue; + } + int light_size = getsize (&mctx->lights[li]); + if (size != light_size || numLayers + layers > mctx->maxLayers) { + if (numLayers) { + mctx->maps[mctx->numMaps++] = (mapdesc_t) { + .size = size, + .layers = numLayers, + .cube = cube, + }; + numLayers = 0; + } + size = light_size; + } + mctx->imageMap[li] = mctx->numMaps; + lr->size = size; + lr->layer = numLayers; + lr->numLayers = layers; + numLayers += layers; + totalLayers += layers; + } + if (numLayers) { + mctx->maps[mctx->numMaps++] = (mapdesc_t) { + .size = size, + .layers = numLayers, + .cube = cube, + }; + } + return totalLayers; +} + +static int +get_point_size (const light_t *light) +{ + return abs ((int) light->color[3]); +} + +static int +get_spot_size (const light_t *light) +{ + float c = light->direction[3]; + float s = sqrt (1 - c * c); + return abs ((int) (s * light->color[3])); +} + +static int +get_direct_size (const light_t *light) +{ + return 1024; +} + static void build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) { - typedef struct { - int size; - int layers; - int cube; - } mapdesc_t; qfv_device_t *device = ctx->device; qfv_physdev_t *physDev = device->physDev; @@ -1168,12 +1376,9 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) auto light_pool = ®->comp_pools[scene_light]; auto lights = (light_t *) light_pool->data; int numLights = light_pool->count; - int size = -1; - int numLayers = 0; int totalLayers = 0; int imageMap[numLights]; int lightMap[numLights]; - int numMaps = 0; mapdesc_t maps[numLights]; for (int i = 0; i < numLights; i++) { @@ -1183,108 +1388,51 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->light_control, numLights); for (int i = 0; i < numLights; i++) { - int layers = 1; auto li = lightMap[i]; auto lr = &lctx->light_control.a[li]; - *lr = (light_control_t) { .light_id = li, }; + *lr = (light_control_t) { + .mode = light_shadow_type (&lights[li]), + .light_id = li, + }; set_lightid (light_pool->dense[li], reg, li); - - if (!lights[li].position[3]) { - if (!VectorIsZero (lights[li].direction)) { - lr->mode = ST_CASCADE; - } - } else { - if (lights[li].direction[3] > -0.5) { - lr->mode = ST_CUBE; - } else { - lr->mode = ST_PLANE; - } - } - if (lr->mode == ST_CASCADE || lr->mode == ST_NONE) { - // cascade shadows will be handled separately, and "none" has no - // shadow map at all - imageMap[li] = -1; - continue; - } - if (lr->mode == ST_CUBE) { - layers = 6; - } - if (size != abs ((int) lights[li].color[3]) - || numLayers + layers > maxLayers) { - if (numLayers) { - maps[numMaps++] = (mapdesc_t) { - .size = size, - .layers = numLayers, - .cube = 1, - }; - numLayers = 0; - } - size = abs ((int) lights[li].color[3]); - } - imageMap[li] = numMaps; - lr->size = size; - lr->layer = numLayers; - lr->numLayers = layers; - numLayers += layers; - totalLayers += layers; - } - if (numLayers) { - maps[numMaps++] = (mapdesc_t) { - .size = size, - .layers = numLayers, - .cube = 1, - }; + // assume all lights have no shadows + imageMap[li] = -1; } - numLayers = 0; - size = 1024; - for (int i = 0; i < numLights; i++) { - int layers = 4; - auto li = lightMap[i]; - auto lr = &lctx->light_control.a[li]; + mapctx_t mctx = { + .maps = maps, + .numLights = numLights, + .lights = lights, + .imageMap = imageMap, + .lightMap = lightMap, + .control = lctx->light_control.a, + .maxLayers = maxLayers, + }; + totalLayers += allocate_map (&mctx, ST_CUBE, get_point_size); + totalLayers += allocate_map (&mctx, ST_PLANE, get_spot_size); + totalLayers += allocate_map (&mctx, ST_CASCADE, get_direct_size); - if (lr->mode != ST_CASCADE) { - continue; - } - if (numLayers + layers > maxLayers) { - maps[numMaps++] = (mapdesc_t) { - .size = size, - .layers = numLayers, - .cube = 0, - }; - numLayers = 0; - } - imageMap[li] = numMaps; - lr->size = size; - lr->layer = numLayers; - lr->numLayers = layers; - numLayers += layers; - totalLayers += layers; - } - if (numLayers) { - maps[numMaps++] = (mapdesc_t) { - .size = size, - .layers = numLayers, - .cube = 0, - }; - } - - if (numMaps) { + lctx->num_maps = mctx.numMaps; + if (mctx.numMaps) { qfv_resource_t *shad = calloc (1, sizeof (qfv_resource_t) - + sizeof (qfv_resobj_t[numMaps]) - + sizeof (qfv_resobj_t[numMaps])); + + sizeof (qfv_resobj_t[mctx.numMaps]) + + sizeof (qfv_resobj_t[mctx.numMaps])); lctx->shadow_resources = shad; *shad = (qfv_resource_t) { .name = "shadow", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .num_objects = 2 * numMaps, + .num_objects = 2 * mctx.numMaps, .objects = (qfv_resobj_t *) &shad[1], }; + lctx->map_images = malloc (sizeof (VkImage[mctx.numMaps])); + lctx->map_views = malloc (sizeof (VkImageView[mctx.numMaps])); + lctx->map_cube = malloc (sizeof (bool[mctx.numMaps])); auto images = shad->objects; - auto views = &images[numMaps]; - for (int i = 0; i < numMaps; i++) { - int cube = maps[i].layers < 6 ? 0 : maps[i].cube; + auto views = &images[mctx.numMaps]; + for (int i = 0; i < mctx.numMaps; i++) { + int cube = maps[i].cube; + lctx->map_cube[i] = cube; images[i] = (qfv_resobj_t) { .name = va (ctx->va_ctx, "map:image:%d:%d", i, maps[i].size), .type = qfv_res_image, @@ -1317,9 +1465,9 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) }; } QFV_CreateResource (device, shad); - for (int i = 0; i < numMaps; i++) { - DARRAY_APPEND (&lctx->light_images, images[i].image.image); - DARRAY_APPEND (&lctx->light_views, views[i].image_view.view); + for (int i = 0; i < mctx.numMaps; i++) { + lctx->map_images[i] = images[i].image.image; + lctx->map_views[i] = views[i].image_view.view; } } @@ -1348,9 +1496,51 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) lr->map_index = imageMap[li]; } Sys_MaskPrintf (SYS_lighting, - "shadow maps: %d layers in %zd images: %"PRId64"\n", - totalLayers, lctx->light_images.size, - lctx->shadow_resources->size); + "shadow maps: %d layers in %d images: %"PRId64"\n", + totalLayers, lctx->num_maps, + lctx->shadow_resources ? lctx->shadow_resources->size + : (VkDeviceSize) 0); +} + +static void +transition_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) +{ + auto device = ctx->device; + auto dfunc = device->funcs; + + VkCommandBufferAllocateInfo aInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = ctx->cmdpool, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + VkCommandBuffer cmd; + dfunc->vkAllocateCommandBuffers (device->dev, &aInfo, &cmd); + VkCommandBufferBeginInfo bInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + dfunc->vkBeginCommandBuffer (cmd, &bInfo); + + auto ib = imageBarriers[qfv_LT_Undefined_to_ShaderReadOnly]; + ib.barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + VkImageMemoryBarrier barriers[lctx->num_maps]; + for (int i = 0; i < lctx->num_maps; i++) { + barriers[i] = ib.barrier; + barriers[i].image = lctx->map_images[i]; + } + dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, lctx->num_maps, barriers); + dfunc->vkEndCommandBuffer (cmd); + + VkSubmitInfo submitInfo = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &cmd, + }; + dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, 0); } static void @@ -1359,28 +1549,48 @@ update_shadow_descriptors (lightingctx_t *lctx, vulkan_ctx_t *ctx) auto device = ctx->device; auto dfunc = device->funcs; - VkDescriptorImageInfo imageInfo[32]; - VkWriteDescriptorSet imageWrite[1]; - for (size_t i = 0; i < 32; i++) { - VkImageView view = ctx->default_black->view; - if (i < lctx->light_views.size) { - view = lctx->light_views.a[i]; + VkDescriptorImageInfo imageInfoCube[32]; + VkDescriptorImageInfo imageInfo2d[32]; + for (int i = 0; i < 32; i++) { + VkImageView viewCube = lctx->default_view_cube; + VkImageView view2d = lctx->default_view_2d; + if (i < lctx->num_maps) { + if (lctx->map_cube[i]) { + viewCube = lctx->map_views[i]; + } else { + view2d = lctx->map_views[i]; + } } - imageInfo[i] = (VkDescriptorImageInfo) { + imageInfoCube[i] = (VkDescriptorImageInfo) { .sampler = lctx->shadow_sampler, - .imageView = view, + .imageView = viewCube, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + imageInfo2d[i] = (VkDescriptorImageInfo) { + .sampler = lctx->shadow_sampler, + .imageView = view2d, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; } - imageWrite[0] = (VkWriteDescriptorSet) { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = lctx->shadow_set, - .dstBinding = 0, - .descriptorCount = 32, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = imageInfo, + VkWriteDescriptorSet imageWrite[2] = { + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = lctx->shadow_cube_set, + .dstBinding = 0, + .descriptorCount = 32, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = imageInfoCube, + }, + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = lctx->shadow_2d_set, + .dstBinding = 0, + .descriptorCount = 32, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = imageInfo2d, + }, }; - dfunc->vkUpdateDescriptorSets (device->dev, 1, imageWrite, 0, 0); + dfunc->vkUpdateDescriptorSets (device->dev, 2, imageWrite, 0, 0); } void @@ -1398,6 +1608,7 @@ Vulkan_LoadLights (scene_t *scene, vulkan_ctx_t *ctx) auto light_pool = ®->comp_pools[scene_light]; if (light_pool->count) { build_shadow_maps (lctx, ctx); + transition_shadow_maps (lctx, ctx); update_shadow_descriptors (lctx, ctx); create_light_matrices (lctx); upload_light_matrices (lctx, ctx);