mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-20 07:50:45 +00:00
[vulkan] Upload light matrices for shadow maps
This involved rewriting the descriptor update code too, but that now feels cleaner. The matrices are loaded into a storage buffer as it can get quite big at 6 matrices per light (and the current max lights is 768).
This commit is contained in:
parent
aac6fca2c5
commit
aed1e7e077
3 changed files with 148 additions and 90 deletions
|
@ -65,24 +65,17 @@ typedef struct qfv_framebufferset_s
|
|||
DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t;
|
||||
|
||||
typedef struct lightingframe_s {
|
||||
VkBuffer data_buffer;
|
||||
VkDescriptorSet shadowmat_set;
|
||||
VkDescriptorSet lights_set;
|
||||
VkDescriptorSet attach_set;
|
||||
|
||||
VkBuffer shadowmat_buffer;
|
||||
VkBuffer light_buffer;
|
||||
VkBuffer id_buffer;
|
||||
uint32_t ico_count;
|
||||
uint32_t cone_count;
|
||||
uint32_t flat_count;
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS];
|
||||
VkDescriptorImageInfo attachInfo[LIGHTING_ATTACH_INFOS];
|
||||
VkDescriptorImageInfo shadowInfo[LIGHTING_SHADOW_INFOS];
|
||||
union {
|
||||
VkWriteDescriptorSet descriptors[LIGHTING_DESCRIPTORS];
|
||||
struct {
|
||||
VkWriteDescriptorSet bufferWrite[LIGHTING_BUFFER_INFOS];
|
||||
VkWriteDescriptorSet attachWrite[LIGHTING_ATTACH_INFOS];
|
||||
VkWriteDescriptorSet shadowWrite;
|
||||
};
|
||||
};
|
||||
|
||||
qfv_imageviewset_t views;
|
||||
qfv_framebufferset_t framebuffers;
|
||||
} lightingframe_t;
|
||||
|
|
|
@ -759,6 +759,16 @@ descriptorSetLayouts = {
|
|||
},
|
||||
);
|
||||
};
|
||||
shadowmat_set = {
|
||||
bindings = (
|
||||
{
|
||||
binding = 0;
|
||||
descriptorType = storage_buffer;
|
||||
descriptorCount = 1;
|
||||
stageFlags = vertex|fragment;
|
||||
},
|
||||
);
|
||||
};
|
||||
quad_data_set = {
|
||||
bindings = (
|
||||
{
|
||||
|
|
|
@ -361,7 +361,7 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
ctx);
|
||||
}
|
||||
|
||||
QFV_PacketCopyBuffer (packet, lframe->data_buffer, 0,
|
||||
QFV_PacketCopyBuffer (packet, lframe->light_buffer, 0,
|
||||
&bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]);
|
||||
QFV_PacketSubmit (packet);
|
||||
uint32_t id_count = lframe->ico_count + lframe->cone_count
|
||||
|
@ -380,31 +380,6 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
}
|
||||
}
|
||||
|
||||
static VkDescriptorBufferInfo base_buffer_info = {
|
||||
0, 0, VK_WHOLE_SIZE
|
||||
};
|
||||
static VkDescriptorImageInfo base_image_info = {
|
||||
0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
};
|
||||
static VkWriteDescriptorSet base_buffer_write = {
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
|
||||
0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
0, 0, 0
|
||||
};
|
||||
static VkWriteDescriptorSet base_attachment_write = {
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
|
||||
0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
|
||||
0, 0, 0
|
||||
};
|
||||
static VkWriteDescriptorSet base_image_write = {
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
|
||||
0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
static void
|
||||
lighting_update_descriptors (const exprval_t **params, exprval_t *result,
|
||||
exprctx_t *ectx)
|
||||
|
@ -418,15 +393,54 @@ lighting_update_descriptors (const exprval_t **params, exprval_t *result,
|
|||
auto lframe = &lctx->frames.a[ctx->curFrame];
|
||||
|
||||
auto fb = &taskctx->renderpass->framebuffer;
|
||||
lframe->bufferInfo[0].buffer = lframe->data_buffer;
|
||||
lframe->attachInfo[0].imageView = fb->views[QFV_attachDepth];
|
||||
lframe->attachInfo[1].imageView = fb->views[QFV_attachColor];
|
||||
lframe->attachInfo[2].imageView = fb->views[QFV_attachEmission];
|
||||
lframe->attachInfo[3].imageView = fb->views[QFV_attachNormal];
|
||||
lframe->attachInfo[4].imageView = fb->views[QFV_attachPosition];
|
||||
VkDescriptorImageInfo attachInfo[] = {
|
||||
{ .imageView = fb->views[QFV_attachDepth],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
{ .imageView = fb->views[QFV_attachColor],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
{ .imageView = fb->views[QFV_attachEmission],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
{ .imageView = fb->views[QFV_attachNormal],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
{ .imageView = fb->views[QFV_attachPosition],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
};
|
||||
VkWriteDescriptorSet attachWrite[] = {
|
||||
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = lframe->attach_set,
|
||||
.dstBinding = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
|
||||
.pImageInfo = &attachInfo[0], },
|
||||
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = lframe->attach_set,
|
||||
.dstBinding = 1,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
|
||||
.pImageInfo = &attachInfo[1], },
|
||||
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = lframe->attach_set,
|
||||
.dstBinding = 2,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
|
||||
.pImageInfo = &attachInfo[2], },
|
||||
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = lframe->attach_set,
|
||||
.dstBinding = 3,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
|
||||
.pImageInfo = &attachInfo[3], },
|
||||
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = lframe->attach_set,
|
||||
.dstBinding = 4,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
|
||||
.pImageInfo = &attachInfo[4], },
|
||||
};
|
||||
//lframe->bufferInfo[0].buffer = lframe->light_buffer;
|
||||
dfunc->vkUpdateDescriptorSets (device->dev,
|
||||
LIGHTING_DESCRIPTORS,
|
||||
lframe->descriptors, 0, 0);
|
||||
LIGHTING_ATTACH_INFOS, attachWrite,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -445,9 +459,8 @@ lighting_bind_descriptors (const exprval_t **params, exprval_t *result,
|
|||
|
||||
VkDescriptorSet sets[] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
lframe->bufferWrite[0].dstSet,
|
||||
lframe->attachWrite[0].dstSet,
|
||||
lframe->shadowWrite.dstSet,
|
||||
lframe->lights_set,
|
||||
lframe->attach_set,
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 3, sets, 0, 0);
|
||||
|
@ -653,6 +666,7 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
qfvPushDebug (ctx, "lighting init");
|
||||
|
||||
auto device = ctx->device;
|
||||
auto dfunc = device->funcs;
|
||||
auto lctx = ctx->lighting_context;
|
||||
|
||||
lctx->sampler = QFV_Render_Sampler (ctx, "shadow_sampler");
|
||||
|
@ -684,19 +698,25 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
+ sizeof (qfv_resobj_t)
|
||||
// splat indices
|
||||
+ sizeof (qfv_resobj_t)
|
||||
// light ids
|
||||
+ sizeof (qfv_resobj_t[frames])
|
||||
// light data
|
||||
+ sizeof (qfv_resobj_t[frames])
|
||||
// light indices
|
||||
// light matrix ids
|
||||
+ 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_data = &splat_inds[1];
|
||||
auto light_ids = &light_data[frames];
|
||||
auto light_ids = &splat_inds[1];
|
||||
auto light_data = &light_ids[frames];
|
||||
auto light_matids = &light_data[frames];
|
||||
auto light_mats = &light_matids[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 + 2 * frames,
|
||||
.num_objects = 2 + 4 * frames,
|
||||
.objects = splat_verts,
|
||||
};
|
||||
splat_verts[0] = (qfv_resobj_t) {
|
||||
|
@ -719,7 +739,7 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
};
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
light_data[i] = (qfv_resobj_t) {
|
||||
.name = "data",
|
||||
.name = "lights",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = sizeof (qfv_light_buffer_t),
|
||||
|
@ -727,6 +747,25 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
},
|
||||
};
|
||||
light_matids[i] = (qfv_resobj_t) {
|
||||
.name = "matrixids",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = sizeof (uint32_t[MaxLights]),
|
||||
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
},
|
||||
};
|
||||
light_mats[i] = (qfv_resobj_t) {
|
||||
.name = "matrices",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
// never need more than 6 matrices per light
|
||||
.size = sizeof (mat4f_t[MaxLights * 6]),
|
||||
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
},
|
||||
};
|
||||
light_ids[i] = (qfv_resobj_t) {
|
||||
.name = "ids",
|
||||
.type = qfv_res_buffer,
|
||||
|
@ -745,52 +784,52 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
|
||||
auto attach_mgr = QFV_Render_DSManager (ctx, "lighting_attach");
|
||||
auto lights_mgr = QFV_Render_DSManager (ctx, "lighting_lights");
|
||||
auto shadow_mgr = QFV_Render_DSManager (ctx, "lighting_shadow");
|
||||
auto shadowmat_mgr = QFV_Render_DSManager (ctx, "shadowmat_set");
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
auto lframe = &lctx->frames.a[i];
|
||||
*lframe = (lightingframe_t) {
|
||||
.data_buffer = light_data[i].buffer.buffer,
|
||||
.shadowmat_set = QFV_DSManager_AllocSet (shadowmat_mgr),
|
||||
.lights_set = QFV_DSManager_AllocSet (lights_mgr),
|
||||
.attach_set = QFV_DSManager_AllocSet (attach_mgr),
|
||||
.shadowmat_buffer = light_mats[i].buffer.buffer,
|
||||
.light_buffer = light_data[i].buffer.buffer,
|
||||
.id_buffer = light_ids[i].buffer.buffer,
|
||||
};
|
||||
|
||||
auto attach = QFV_DSManager_AllocSet (attach_mgr);
|
||||
auto lights = QFV_DSManager_AllocSet (lights_mgr);
|
||||
auto shadow = QFV_DSManager_AllocSet (shadow_mgr);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, attach,
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET,
|
||||
lframe->attach_set,
|
||||
va (ctx->va_ctx, "lighting:attach_set:%zd", i));
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, lights,
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET,
|
||||
lframe->lights_set,
|
||||
va (ctx->va_ctx, "lighting:lights_set:%zd", i));
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, shadow,
|
||||
va (ctx->va_ctx, "lighting:shadow_set:%zd", i));
|
||||
|
||||
for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) {
|
||||
lframe->bufferInfo[j] = base_buffer_info;
|
||||
lframe->bufferWrite[j] = base_buffer_write;
|
||||
lframe->bufferWrite[j].dstSet = lights;
|
||||
lframe->bufferWrite[j].dstBinding = j;
|
||||
lframe->bufferWrite[j].pBufferInfo = &lframe->bufferInfo[j];
|
||||
}
|
||||
for (int j = 0; j < LIGHTING_ATTACH_INFOS; j++) {
|
||||
lframe->attachInfo[j] = base_image_info;
|
||||
lframe->attachInfo[j].sampler = 0;
|
||||
lframe->attachWrite[j] = base_attachment_write;
|
||||
lframe->attachWrite[j].dstSet = attach;
|
||||
lframe->attachWrite[j].dstBinding = j;
|
||||
lframe->attachWrite[j].pImageInfo = &lframe->attachInfo[j];
|
||||
}
|
||||
for (int j = 0; j < LIGHTING_SHADOW_INFOS; j++) {
|
||||
lframe->shadowInfo[j] = base_image_info;
|
||||
lframe->shadowInfo[j].sampler = lctx->sampler;
|
||||
lframe->shadowInfo[j].imageView = ctx->default_black->view;
|
||||
}
|
||||
lframe->shadowWrite = base_image_write;
|
||||
lframe->shadowWrite.dstSet = shadow;
|
||||
lframe->shadowWrite.dstBinding = 0;
|
||||
lframe->shadowWrite.descriptorCount = LIGHTING_SHADOW_INFOS;
|
||||
lframe->shadowWrite.pImageInfo = lframe->shadowInfo;
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET,
|
||||
lframe->shadowmat_set,
|
||||
va (ctx->va_ctx, "lighting:shadowmat_set:%zd", i));
|
||||
|
||||
lframe->views = (qfv_imageviewset_t) DARRAY_STATIC_INIT (16);
|
||||
lframe->framebuffers = (qfv_framebufferset_t) DARRAY_STATIC_INIT (16);
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo[] = {
|
||||
{ .buffer = lframe->light_buffer,
|
||||
.offset = 0, .range = VK_WHOLE_SIZE, },
|
||||
{ .buffer = lframe->shadowmat_buffer,
|
||||
.offset = 0, .range = VK_WHOLE_SIZE, },
|
||||
};
|
||||
VkWriteDescriptorSet bufferWrite[] = {
|
||||
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = lframe->lights_set,
|
||||
.dstBinding = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pBufferInfo = &bufferInfo[0], },
|
||||
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = lframe->shadowmat_set,
|
||||
.dstBinding = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.pBufferInfo = &bufferInfo[1], },
|
||||
};
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 2, bufferWrite, 0, 0);
|
||||
}
|
||||
|
||||
auto packet = QFV_PacketAcquire (ctx->staging);
|
||||
|
@ -911,6 +950,21 @@ create_light_matrices (lightingctx_t *lctx)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
upload_light_matrices (lightingctx_t *lctx, vulkan_ctx_t *ctx)
|
||||
{
|
||||
auto packet = QFV_PacketAcquire (ctx->staging);
|
||||
size_t mat_size = sizeof (mat4f_t[lctx->light_mats.size]);
|
||||
void *mat_data = QFV_PacketExtend (packet, mat_size);
|
||||
memcpy (mat_data, lctx->light_mats.a, mat_size);
|
||||
auto bb = &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead];
|
||||
for (size_t i = 0; i < lctx->frames.size; i++) {
|
||||
auto lframe = &lctx->frames.a[i];
|
||||
QFV_PacketCopyBuffer (packet, lframe->shadowmat_buffer, 0, bb);
|
||||
}
|
||||
QFV_PacketSubmit (packet);
|
||||
}
|
||||
|
||||
static int
|
||||
light_compare (const void *_li2, const void *_li1, void *_lights)
|
||||
{
|
||||
|
@ -1129,6 +1183,7 @@ Vulkan_LoadLights (scene_t *scene, vulkan_ctx_t *ctx)
|
|||
if (light_pool->count) {
|
||||
build_shadow_maps (lctx, ctx);
|
||||
create_light_matrices (lctx);
|
||||
upload_light_matrices (lctx, ctx);
|
||||
}
|
||||
lctx->ldata = scene->lights;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue