[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.
This commit is contained in:
Bill Currie 2023-08-02 17:52:57 +09:00
parent 39bb433498
commit a626dc7ca8
12 changed files with 512 additions and 259 deletions

View file

@ -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_CASCADE 2 // cascaded shadow maps
#define ST_CUBE 3 // cubemap (omni, large spotlight) #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 { typedef struct qfv_light_render_s {
// mat_id (13) map_id (5) layer (11) type (2) // mat_id (13) map_id (5) layer (11) type (2)
uint32_t id_data; uint32_t id_data;
@ -69,6 +64,11 @@ typedef struct qfv_light_render_s {
typedef struct qfv_framebufferset_s typedef struct qfv_framebufferset_s
DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t; DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t;
typedef struct light_queue_s {
uint16_t start;
uint16_t count;
} light_queue_t;
typedef struct lightingframe_s { typedef struct lightingframe_s {
VkDescriptorSet shadowmat_set; VkDescriptorSet shadowmat_set;
VkDescriptorSet lights_set; VkDescriptorSet lights_set;
@ -79,6 +79,7 @@ typedef struct lightingframe_s {
VkBuffer render_buffer; VkBuffer render_buffer;
VkBuffer style_buffer; VkBuffer style_buffer;
VkBuffer id_buffer; VkBuffer id_buffer;
light_queue_t light_queue[4];
uint32_t ico_count; uint32_t ico_count;
uint32_t cone_count; uint32_t cone_count;
uint32_t flat_count; uint32_t flat_count;
@ -113,15 +114,21 @@ typedef struct lightingctx_s {
struct qfv_resource_s *light_resources; struct qfv_resource_s *light_resources;
qfv_lightmatset_t light_mats; qfv_lightmatset_t light_mats;
qfv_imageset_t light_images; VkImage *map_images;
qfv_imageviewset_t light_views; 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; light_control_set_t light_control;
qfv_attachmentinfo_t shadow_info; qfv_attachmentinfo_t shadow_info;
VkSampler shadow_sampler; VkSampler shadow_sampler;
VkDescriptorSet shadow_set; VkDescriptorSet shadow_cube_set;
VkDescriptorSet shadow_2d_set;
VkBuffer splat_verts; VkBuffer splat_verts;
VkBuffer splat_inds; VkBuffer splat_inds;

View file

@ -330,6 +330,7 @@ bsp_turbf_src = $(vkshaderpath)/bsp_turb.frag
bsp_turbf_c = $(vkshaderpath)/bsp_turb.frag.spvc bsp_turbf_c = $(vkshaderpath)/bsp_turb.frag.spvc
debug_src = $(vkshaderpath)/debug.frag debug_src = $(vkshaderpath)/debug.frag
debug_c = $(vkshaderpath)/debug.frag.spvc debug_c = $(vkshaderpath)/debug.frag.spvc
light_attach_h = $(vkshaderpath)/light_attach.h
light_flat_src = $(vkshaderpath)/light_flat.vert light_flat_src = $(vkshaderpath)/light_flat.vert
light_flat_c = $(vkshaderpath)/light_flat.vert.spvc light_flat_c = $(vkshaderpath)/light_flat.vert.spvc
light_splatv_src = $(vkshaderpath)/light_splat.vert 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_splatf_c = $(vkshaderpath)/light_splat.frag.spvc
light_debug_src = $(vkshaderpath)/light_debug.frag light_debug_src = $(vkshaderpath)/light_debug.frag
light_debug_c = $(vkshaderpath)/light_debug.frag.spvc light_debug_c = $(vkshaderpath)/light_debug.frag.spvc
lightingf_src = $(vkshaderpath)/lighting.frag lighting_cascadef_src = $(vkshaderpath)/lighting_cascade.frag
lightingf_c = $(vkshaderpath)/lighting.frag.spvc 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 lighting_h = $(vkshaderpath)/lighting.h
composef_src = $(vkshaderpath)/compose.frag composef_src = $(vkshaderpath)/compose.frag
composef_c = $(vkshaderpath)/compose.frag.spvc 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) $(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) $(composef_c): $(composef_src) $(oit_blend) $(oit_h)
@ -504,7 +518,10 @@ vkshader_c = \
$(light_splatv_c) \ $(light_splatv_c) \
$(light_splatf_c) \ $(light_splatf_c) \
$(light_debug_c) \ $(light_debug_c) \
$(lightingf_c) \ $(lighting_cascadef_c) \
$(lighting_cubef_c) \
$(lighting_nonef_c) \
$(lighting_planef_c) \
$(composef_c) \ $(composef_c) \
$(aliasv_c) \ $(aliasv_c) \
$(alias_depth_c) \ $(alias_depth_c) \
@ -591,11 +608,15 @@ EXTRA_DIST += \
$(bsp_skyf_src) \ $(bsp_skyf_src) \
$(bsp_turbf_src) \ $(bsp_turbf_src) \
$(debug_src) \ $(debug_src) \
$(light_attach_h) \
$(light_flat_src) \ $(light_flat_src) \
$(light_splatv_src) \ $(light_splatv_src) \
$(light_splatf_src) \ $(light_splatf_src) \
$(light_debug_src) \ $(light_debug_src) \
$(lightingf_src) \ $(lighting_cascadef_src) \
$(lighting_cubef_src) \
$(lighting_nonef_src) \
$(lighting_planef_src) \
$(lighting_h) \ $(lighting_h) \
$(composef_src) \ $(composef_src) \
$(aliasv_src) \ $(aliasv_src) \

View file

@ -618,51 +618,25 @@ properties = {
name = main; name = main;
module = $builtin/light_splat.frag; module = $builtin/light_splat.frag;
}; };
shadow_specialization = {
mapEntries = (
// ShadowType
{ size = 4; offset = 0; constantID = 0; },
);
};
fragment_none = { fragment_none = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/lighting.frag; module = $builtin/lighting_none.frag;
specializationInfo = {
@inherit = $lighting.shader.shadow_specialization;
// ShadowType
data = "array(0)";
};
}; };
fragment_plane = { fragment_plane = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/lighting.frag; module = $builtin/lighting_plane.frag;
specializationInfo = {
@inherit = $lighting.shader.shadow_specialization;
// ShadowType
data = "array(1)";
};
}; };
fragment_cascade = { fragment_cascade = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/lighting.frag; module = $builtin/lighting_cascade.frag;
specializationInfo = {
@inherit = $lighting.shader.shadow_specialization;
// ShadowType
data = "array(2)";
};
}; };
fragment_cube = { fragment_cube = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/lighting.frag; module = $builtin/lighting_cube.frag;
specializationInfo = {
@inherit = $lighting.shader.shadow_specialization;
// ShadowType
data = "array(3)";
};
}; };
debug_fragment = { debug_fragment = {
stage = fragment; stage = fragment;
@ -698,6 +672,11 @@ properties = {
layout = { layout = {
descriptorSets = (shadowmat_set, lighting_lights, descriptorSets = (shadowmat_set, lighting_lights,
lighting_attach, lighting_shadow); lighting_attach, lighting_shadow);
pushConstants = {
fragment = {
queue = uint;
};
};
}; };
}; };
compose = { compose = {

View file

@ -99,7 +99,13 @@ static
static static
#include "libs/video/renderer/vulkan/shader/light_debug.frag.spvc" #include "libs/video/renderer/vulkan/shader/light_debug.frag.spvc"
static 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 static
#include "libs/video/renderer/vulkan/shader/compose.frag.spvc" #include "libs/video/renderer/vulkan/shader/compose.frag.spvc"
static static
@ -172,7 +178,12 @@ static shaderdata_t builtin_shaders[] = {
{ "light_splat.vert", light_splat_vert, sizeof (light_splat_vert) }, { "light_splat.vert", light_splat_vert, sizeof (light_splat_vert) },
{ "light_splat.frag", light_splat_frag, sizeof (light_splat_frag) }, { "light_splat.frag", light_splat_frag, sizeof (light_splat_frag) },
{ "light_debug.frag", light_debug_frag, sizeof (light_debug_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) }, { "compose.frag", compose_frag, sizeof (compose_frag) },
{ "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias.vert", alias_vert, sizeof (alias_vert) },
{ "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) },

View file

@ -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;

View file

@ -16,7 +16,6 @@ struct LightRender {
}; };
layout (set = 1, binding = 0) buffer LightIds { layout (set = 1, binding = 0) buffer LightIds {
uint lightCount;
uint lightIds[]; uint lightIds[];
}; };
layout (set = 1, binding = 1) buffer Lights { layout (set = 1, binding = 1) buffer Lights {

View file

@ -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"

View file

@ -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"

View file

@ -1,20 +1,11 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
#include "lighting.h" #include "lighting.h"
#include "light_attach.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];
layout (location = 0) out vec4 frag_color; layout (location = 0) out vec4 frag_color;
layout (constant_id = 0) const int ShadowType = ST_NONE; layout (push_constant) uniform PushConstants {
uint queue;
};
float float
spot_cone (LightData light, vec3 incoming) spot_cone (LightData light, vec3 incoming)
@ -32,24 +23,6 @@ diffuse (vec3 incoming, vec3 normal)
return clamp (lightdot, 0, 1); 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 void
main (void) main (void)
{ {
@ -59,8 +32,10 @@ main (void)
vec3 p = subpassLoad (position).rgb; vec3 p = subpassLoad (position).rgb;
vec3 light = vec3 (0); vec3 light = vec3 (0);
//vec3 minLight = vec3 (0); uint start = bitfieldExtract (queue, 0, 16);
for (int i = 0; i < lightCount; i++) { uint count = bitfieldExtract (queue, 16, 16);
for (uint i = start; i < count; i++) {
uint id = lightIds[i]; uint id = lightIds[i];
LightData l = lights[id]; LightData l = lights[id];
vec3 dir = l.position.xyz - l.position.w * p; vec3 dir = l.position.xyz - l.position.w * p;
@ -78,13 +53,8 @@ main (void)
uint mat_id = bitfieldExtract (id_data, 0, 13); uint mat_id = bitfieldExtract (id_data, 0, 13);
uint map_id = bitfieldExtract (id_data, 13, 5); uint map_id = bitfieldExtract (id_data, 13, 5);
uint layer = bitfieldExtract (id_data, 18, 11); uint layer = bitfieldExtract (id_data, 18, 11);
if (ShadowType == ST_CASCADE) {
I *= shadow_cascade (shadowCascade[map_id], layer, mat_id, p); I *= shadow (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);
}
float namb = dot(l.direction.xyz, l.direction.xyz); float namb = dot(l.direction.xyz, l.direction.xyz);
I *= spot_cone (l, incoming) * diffuse (incoming, n); I *= spot_cone (l, incoming) * diffuse (incoming, n);

View file

@ -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"

View file

@ -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"

View file

@ -94,13 +94,13 @@ static int cone_inds[] = {
1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2,
}; };
#define num_cone_inds (sizeof (cone_inds) / sizeof (cone_inds[0])) #define num_cone_inds (sizeof (cone_inds) / sizeof (cone_inds[0]))
#if 0
static const light_t * static const light_t *
get_light (entity_t ent) get_light (entity_t ent)
{ {
return Ent_GetComponent (ent.id, scene_light, ent.reg); return Ent_GetComponent (ent.id, scene_light, ent.reg);
} }
#endif
static uint32_t static uint32_t
get_lightstyle (entity_t ent) get_lightstyle (entity_t ent)
{ {
@ -188,7 +188,7 @@ create_view (vulkan_ctx_t *ctx, light_control_t *renderer)
VkImageViewCreateInfo cInfo = { VkImageViewCreateInfo cInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .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, .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
.format = VK_FORMAT_X8_D24_UNORM_PACK32, .format = VK_FORMAT_X8_D24_UNORM_PACK32,
.subresourceRange = { .subresourceRange = {
@ -252,7 +252,7 @@ lighting_draw_shadow_maps (const exprval_t **params, exprval_t *result,
auto render = shadow->render; auto render = shadow->render;
auto lframe = &lctx->frames.a[ctx->curFrame]; auto lframe = &lctx->frames.a[ctx->curFrame];
if (!lctx->ldata) { if (!lctx->num_maps) {
return; return;
} }
//auto pass = Vulkan_Bsp_GetAuxPass (ctx); //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->ico_count = 0;
lframe->cone_count = 0; lframe->cone_count = 0;
lframe->flat_count = 0; lframe->flat_count = 0;
memset (lframe->light_queue, 0, sizeof (lframe->light_queue));
if (!lctx->scene || !lctx->scene->lights) { if (!lctx->scene || !lctx->scene->lights) {
return; return;
} }
@ -307,11 +308,10 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
QFV_PacketCopyBuffer (packet, lframe->style_buffer, 0, bb); QFV_PacketCopyBuffer (packet, lframe->style_buffer, 0, bb);
QFV_PacketSubmit (packet); QFV_PacketSubmit (packet);
uint32_t ico_ids[MaxLights]; uint32_t ids[4][MaxLights];
uint32_t cone_ids[MaxLights];
uint32_t flat_ids[MaxLights];
uint32_t light_count = 0; uint32_t light_count = 0;
auto queue = lframe->light_queue;
dlight_t *dynamic_lights[MaxLights]; dlight_t *dynamic_lights[MaxLights];
int maxdlight = MaxLights - lctx->dynamic_base; 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); packet = QFV_PacketAcquire (ctx->staging);
light_t *lights = QFV_PacketExtend (packet, sizeof (light_t[ndlight])); light_t *lights = QFV_PacketExtend (packet, sizeof (light_t[ndlight]));
for (int i = 0; i < ndlight; i++) { 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); VectorCopy (dynamic_lights[i]->color, lights[i].color);
// dynamic lights seem a tad faint, so 16x map lights // 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); QFV_PacketSubmit (packet);
} }
auto queue = r_ent_queue; //FIXME fetch from scene auto entqueue = r_ent_queue; //FIXME fetch from scene
for (size_t i = 0; i < queue->ent_queues[mod_light].size; i++) { for (size_t i = 0; i < entqueue->ent_queues[mod_light].size; i++) {
entity_t ent = queue->ent_queues[mod_light].a[i]; entity_t ent = entqueue->ent_queues[mod_light].a[i];
auto l = get_light (ent);
auto ls = get_lightstyle (ent); auto ls = get_lightstyle (ent);
if (!d_lightstylevalue[ls]) { if (!d_lightstylevalue[ls]) {
continue; continue;
@ -366,16 +367,8 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
light_count++; light_count++;
uint32_t id = lctx->light_control.a[get_lightid (ent)].light_id; uint32_t id = lctx->light_control.a[get_lightid (ent)].light_id;
if (l->position[3] && !VectorIsZero (l->direction) int mode = lctx->light_control.a[get_lightid (ent)].mode;
&& l->attenuation[3]) { ids[mode][queue[mode].count++] = id;
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;
}
} }
if (developer & SYS_lighting) { if (developer & SYS_lighting) {
Vulkan_Draw_String (vid.width - 32, 8, Vulkan_Draw_String (vid.width - 32, 8,
@ -383,21 +376,17 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
ctx); ctx);
} }
uint32_t id_count = lframe->ico_count + lframe->cone_count if (light_count) {
+ lframe->flat_count; for (int i = 1; i < 4; i++) {
if (id_count != light_count) { queue[i].start = queue[i - 1].start + queue[i - 1].count;
Sys_Error ("taniwha can't count: %d != %d", id_count, light_count); }
}
if (id_count) {
packet = QFV_PacketAcquire (ctx->staging); packet = QFV_PacketAcquire (ctx->staging);
uint32_t *count = QFV_PacketExtend (packet, sizeof (uint32_t)); uint32_t *lids = QFV_PacketExtend (packet,
*count = id_count; sizeof (uint32_t[light_count]));
uint32_t *ids = QFV_PacketExtend (packet, sizeof (uint32_t[id_count])); for (int i = 0; i < 4; i++) {
memcpy (ids, ico_ids, lframe->ico_count * sizeof (uint32_t)); memcpy (lids + queue[i].start, ids[i],
ids += lframe->ico_count; sizeof (uint32_t[queue[i].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, QFV_PacketCopyBuffer (packet, lframe->id_buffer, 0,
&bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]);
QFV_PacketSubmit (packet); QFV_PacketSubmit (packet);
@ -470,17 +459,25 @@ lighting_bind_descriptors (const exprval_t **params, exprval_t *result,
auto device = ctx->device; auto device = ctx->device;
auto dfunc = device->funcs; auto dfunc = device->funcs;
auto lctx = ctx->lighting_context; auto lctx = ctx->lighting_context;
if (!lctx->num_maps) {
return;
}
auto cmd = taskctx->cmd; auto cmd = taskctx->cmd;
auto layout = taskctx->pipeline->layout; auto layout = taskctx->pipeline->layout;
auto lframe = &lctx->frames.a[ctx->curFrame]; auto lframe = &lctx->frames.a[ctx->curFrame];
auto shadow_type = *(int *) params[0]->value;
VkDescriptorSet sets[] = { VkDescriptorSet sets[] = {
//Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
lframe->shadowmat_set, lframe->shadowmat_set,
lframe->lights_set, lframe->lights_set,
lframe->attach_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, dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, 4, sets, 0, 0); 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 device = ctx->device;
auto dfunc = device->funcs; auto dfunc = device->funcs;
auto lctx = ctx->lighting_context; auto lctx = ctx->lighting_context;
auto layout = taskctx->pipeline->layout;
auto cmd = taskctx->cmd; auto cmd = taskctx->cmd;
auto lframe = &lctx->frames.a[ctx->curFrame]; 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; 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); dfunc->vkCmdDraw (cmd, 3, 1, 0, 0);
} }
@ -661,6 +667,54 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
QFV_Render_AddAttachments (ctx, 1, attachments); 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 static void
make_ico (qfv_packet_t *packet) make_ico (qfv_packet_t *packet)
{ {
@ -732,8 +786,6 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
#endif #endif
DARRAY_INIT (&lctx->light_mats, 16); DARRAY_INIT (&lctx->light_mats, 16);
DARRAY_INIT (&lctx->light_images, 16);
DARRAY_INIT (&lctx->light_views, 16);
DARRAY_INIT (&lctx->light_control, 16); DARRAY_INIT (&lctx->light_control, 16);
auto rctx = ctx->render_context; auto rctx = ctx->render_context;
@ -747,6 +799,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
+ sizeof (qfv_resobj_t) + sizeof (qfv_resobj_t)
// splat indices // splat indices
+ sizeof (qfv_resobj_t) + sizeof (qfv_resobj_t)
// default shadow map and views
+ 3 * sizeof (qfv_resobj_t)
// light ids // light ids
+ sizeof (qfv_resobj_t[frames]) + sizeof (qfv_resobj_t[frames])
// light data // light data
@ -757,20 +811,23 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
+ sizeof (qfv_resobj_t[frames]) + sizeof (qfv_resobj_t[frames])
// light matrices // light matrices
+ sizeof (qfv_resobj_t[frames])); + 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) { lctx->light_resources[0] = (qfv_resource_t) {
.name = "lights", .name = "lights",
.va_ctx = ctx->va_ctx, .va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.num_objects = 2 + 5 * frames, .num_objects = 2 + 3 + 5 * frames,
.objects = splat_verts, .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) { splat_verts[0] = (qfv_resobj_t) {
.name = "splat:vertices", .name = "splat:vertices",
.type = qfv_res_buffer, .type = qfv_res_buffer,
@ -789,6 +846,49 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT, | 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++) { for (size_t i = 0; i < frames; i++) {
light_ids[i] = (qfv_resobj_t) { light_ids[i] = (qfv_resobj_t) {
.name = "ids", .name = "ids",
@ -843,11 +943,17 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
lctx->splat_verts = splat_verts[0].buffer.buffer; lctx->splat_verts = splat_verts[0].buffer.buffer;
lctx->splat_inds = splat_inds[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"); 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, 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"); lctx->shadow_sampler = QFV_Render_Sampler (ctx, "shadow_sampler");
auto attach_mgr = QFV_Render_DSManager (ctx, "lighting_attach"); 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); dfunc->vkUpdateDescriptorSets (device->dev, 5, bufferWrite, 0, 0);
} }
make_default_map (64, lctx->default_map, ctx);
auto packet = QFV_PacketAcquire (ctx->staging); auto packet = QFV_PacketAcquire (ctx->staging);
make_ico (packet); make_ico (packet);
make_cone (packet); make_cone (packet);
@ -953,8 +1061,13 @@ clear_shadows (vulkan_ctx_t *ctx)
free (lctx->shadow_resources); free (lctx->shadow_resources);
lctx->shadow_resources = 0; lctx->shadow_resources = 0;
} }
lctx->light_images.size = 0; free (lctx->map_images);
lctx->light_views.size = 0; 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; 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_mats);
DARRAY_CLEAR (&lctx->light_images);
DARRAY_CLEAR (&lctx->light_views);
DARRAY_CLEAR (&lctx->light_control); DARRAY_CLEAR (&lctx->light_control);
free (lctx->map_images);
free (lctx->map_views);
free (lctx->map_cube);
free (lctx->frames.a); free (lctx->frames.a);
free (lctx); free (lctx);
} }
@ -1129,6 +1243,23 @@ upload_light_data (lightingctx_t *lctx, vulkan_ctx_t *ctx)
lctx->dynamic_count = 0; 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 static int
light_compare (const void *_li2, const void *_li1, void *_lights) 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; 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 static void
build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) 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_device_t *device = ctx->device;
qfv_physdev_t *physDev = device->physDev; qfv_physdev_t *physDev = device->physDev;
@ -1168,12 +1376,9 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
auto light_pool = &reg->comp_pools[scene_light]; auto light_pool = &reg->comp_pools[scene_light];
auto lights = (light_t *) light_pool->data; auto lights = (light_t *) light_pool->data;
int numLights = light_pool->count; int numLights = light_pool->count;
int size = -1;
int numLayers = 0;
int totalLayers = 0; int totalLayers = 0;
int imageMap[numLights]; int imageMap[numLights];
int lightMap[numLights]; int lightMap[numLights];
int numMaps = 0;
mapdesc_t maps[numLights]; mapdesc_t maps[numLights];
for (int i = 0; i < numLights; i++) { 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); DARRAY_RESIZE (&lctx->light_control, numLights);
for (int i = 0; i < numLights; i++) { for (int i = 0; i < numLights; i++) {
int layers = 1;
auto li = lightMap[i]; auto li = lightMap[i];
auto lr = &lctx->light_control.a[li]; 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); set_lightid (light_pool->dense[li], reg, li);
// assume all lights have no shadows
if (!lights[li].position[3]) { imageMap[li] = -1;
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,
};
} }
numLayers = 0; mapctx_t mctx = {
size = 1024; .maps = maps,
for (int i = 0; i < numLights; i++) { .numLights = numLights,
int layers = 4; .lights = lights,
auto li = lightMap[i]; .imageMap = imageMap,
auto lr = &lctx->light_control.a[li]; .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) { lctx->num_maps = mctx.numMaps;
continue; if (mctx.numMaps) {
}
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) {
qfv_resource_t *shad = calloc (1, sizeof (qfv_resource_t) qfv_resource_t *shad = calloc (1, sizeof (qfv_resource_t)
+ sizeof (qfv_resobj_t[numMaps]) + sizeof (qfv_resobj_t[mctx.numMaps])
+ sizeof (qfv_resobj_t[numMaps])); + sizeof (qfv_resobj_t[mctx.numMaps]));
lctx->shadow_resources = shad; lctx->shadow_resources = shad;
*shad = (qfv_resource_t) { *shad = (qfv_resource_t) {
.name = "shadow", .name = "shadow",
.va_ctx = ctx->va_ctx, .va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.num_objects = 2 * numMaps, .num_objects = 2 * mctx.numMaps,
.objects = (qfv_resobj_t *) &shad[1], .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 images = shad->objects;
auto views = &images[numMaps]; auto views = &images[mctx.numMaps];
for (int i = 0; i < numMaps; i++) { for (int i = 0; i < mctx.numMaps; i++) {
int cube = maps[i].layers < 6 ? 0 : maps[i].cube; int cube = maps[i].cube;
lctx->map_cube[i] = cube;
images[i] = (qfv_resobj_t) { images[i] = (qfv_resobj_t) {
.name = va (ctx->va_ctx, "map:image:%d:%d", i, maps[i].size), .name = va (ctx->va_ctx, "map:image:%d:%d", i, maps[i].size),
.type = qfv_res_image, .type = qfv_res_image,
@ -1317,9 +1465,9 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
}; };
} }
QFV_CreateResource (device, shad); QFV_CreateResource (device, shad);
for (int i = 0; i < numMaps; i++) { for (int i = 0; i < mctx.numMaps; i++) {
DARRAY_APPEND (&lctx->light_images, images[i].image.image); lctx->map_images[i] = images[i].image.image;
DARRAY_APPEND (&lctx->light_views, views[i].image_view.view); 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]; lr->map_index = imageMap[li];
} }
Sys_MaskPrintf (SYS_lighting, Sys_MaskPrintf (SYS_lighting,
"shadow maps: %d layers in %zd images: %"PRId64"\n", "shadow maps: %d layers in %d images: %"PRId64"\n",
totalLayers, lctx->light_images.size, totalLayers, lctx->num_maps,
lctx->shadow_resources->size); 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 static void
@ -1359,28 +1549,48 @@ update_shadow_descriptors (lightingctx_t *lctx, vulkan_ctx_t *ctx)
auto device = ctx->device; auto device = ctx->device;
auto dfunc = device->funcs; auto dfunc = device->funcs;
VkDescriptorImageInfo imageInfo[32]; VkDescriptorImageInfo imageInfoCube[32];
VkWriteDescriptorSet imageWrite[1]; VkDescriptorImageInfo imageInfo2d[32];
for (size_t i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
VkImageView view = ctx->default_black->view; VkImageView viewCube = lctx->default_view_cube;
if (i < lctx->light_views.size) { VkImageView view2d = lctx->default_view_2d;
view = lctx->light_views.a[i]; 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, .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, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
}; };
} }
imageWrite[0] = (VkWriteDescriptorSet) { VkWriteDescriptorSet imageWrite[2] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, {
.dstSet = lctx->shadow_set, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstBinding = 0, .dstSet = lctx->shadow_cube_set,
.descriptorCount = 32, .dstBinding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 32,
.pImageInfo = imageInfo, .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 void
@ -1398,6 +1608,7 @@ Vulkan_LoadLights (scene_t *scene, vulkan_ctx_t *ctx)
auto light_pool = &reg->comp_pools[scene_light]; auto light_pool = &reg->comp_pools[scene_light];
if (light_pool->count) { if (light_pool->count) {
build_shadow_maps (lctx, ctx); build_shadow_maps (lctx, ctx);
transition_shadow_maps (lctx, ctx);
update_shadow_descriptors (lctx, ctx); update_shadow_descriptors (lctx, ctx);
create_light_matrices (lctx); create_light_matrices (lctx);
upload_light_matrices (lctx, ctx); upload_light_matrices (lctx, ctx);