[vulkan] Add a level of indirection to shadow matrices

Batching shadow map rendering needs be able to reference matrices for
multiple lights in a single batch, but the only input is the view index,
so use that to look up the matrix index rather than using it to index
the matrices directly (modulo the base index that's still there).
This commit is contained in:
Bill Currie 2023-12-14 10:01:27 +09:00
parent 3a31fa111d
commit 72ef0662f5
5 changed files with 64 additions and 13 deletions

View file

@ -85,6 +85,7 @@ typedef struct lightingframe_s {
VkDescriptorSet attach_set;
VkBuffer shadowmat_buffer;
VkBuffer shadowmat_id_buffer;
VkBuffer light_buffer;
VkBuffer render_buffer;
VkBuffer style_buffer;

View file

@ -6,6 +6,10 @@ layout (set = 0, binding = 0) buffer ShadowView {
mat4x4 shadowView[];
};
layout (set = 0, binding = 1) buffer ShadowId {
uint shadowId[];
};
layout (push_constant) uniform PushConstants {
mat4 Model;
float blend;
@ -21,5 +25,6 @@ void
main (void)
{
vec4 pos = mix (vertexa, vertexb, blend);
gl_Position = shadowView[MatrixBase + gl_ViewIndex] * (Model * pos);
uint matid = shadowId[MatrixBase + gl_ViewIndex];
gl_Position = shadowView[matid] * (Model * pos);
}

View file

@ -6,6 +6,10 @@ layout (set = 0, binding = 0) buffer ShadowView {
mat4x4 shadowView[];
};
layout (set = 0, binding = 1) buffer ShadowId {
uint shadowId[];
};
layout (push_constant) uniform PushConstants {
uint MatrixBase;
};
@ -25,5 +29,6 @@ void
main (void)
{
vec4 pos = vec4 (vertex * entities[entid].transform, 1);
gl_Position = shadowView[MatrixBase + gl_ViewIndex] * pos;
uint matid = shadowId[MatrixBase + gl_ViewIndex];
gl_Position = shadowView[matid] * pos;
}

View file

@ -13,6 +13,10 @@ layout (set = 1, binding = 0) buffer ShadowView {
mat4x4 shadowView[];
};
layout (set = 1, binding = 1) buffer ShadowId {
uint shadowId[];
};
layout (set = 3, binding = 0) buffer Bones {
// NOTE these are transposed, so v * m
mat3x4 bones[];
@ -49,7 +53,8 @@ main (void)
m += mat3x4(1,0,0,0,0,1,0,0,0,0,1,0) * (1 - dot(vweights, vec4(1,1,1,1)));
vec4 pos = Model * vec4 (vec4(vposition, 1) * m, 1);
if (IQMShadow) {
gl_Position = shadowView[MatrixBase + gl_ViewIndex] * pos;
uint matid = shadowId[MatrixBase + gl_ViewIndex];
gl_Position = shadowView[matid] * pos;
} else {
gl_Position = Projection3d * (View[gl_ViewIndex] * pos);
}

View file

@ -1090,6 +1090,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
+ 3 * sizeof (qfv_resobj_t)
// light matrices
+ sizeof (qfv_resobj_t[frames])
// light matrix ids
+ sizeof (qfv_resobj_t[frames])
// light ids
+ sizeof (qfv_resobj_t[frames])
// light data
@ -1104,7 +1106,7 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
.name = "lights",
.va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.num_objects = 2 + 3 + 6 * frames,
.num_objects = 2 + 3 + 7 * frames,
.objects = (qfv_resobj_t *) &lctx->light_resources[1],
};
auto splat_verts = lctx->light_resources->objects;
@ -1113,7 +1115,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
auto default_view_cube = &default_map[1];
auto default_view_2d = &default_view_cube[1];
auto light_mats = &default_view_2d[1];
auto light_ids = &light_mats[frames];
auto light_mat_ids = &light_mats[frames];
auto light_ids = &light_mat_ids[frames];
auto light_data = &light_ids[frames];
auto light_render = &light_data[frames];
auto light_styles = &light_render[frames];
@ -1237,6 +1240,16 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
},
};
light_mat_ids[i] = (qfv_resobj_t) {
.name = va (ctx->va_ctx, "matrix ids:%zd", i),
.type = qfv_res_buffer,
.buffer = {
// never need more than 6 matrices per light
.size = sizeof (uint32_t[MaxLights * 6]),
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
},
};
}
QFV_CreateResource (device, lctx->light_resources);
@ -1266,6 +1279,7 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
.lights_set = QFV_DSManager_AllocSet (lights_mgr),
.attach_set = QFV_DSManager_AllocSet (attach_mgr),
.shadowmat_buffer = light_mats[i].buffer.buffer,
.shadowmat_id_buffer = light_mat_ids[i].buffer.buffer,
.light_buffer = light_data[i].buffer.buffer,
.render_buffer = light_render[i].buffer.buffer,
.style_buffer = light_styles[i].buffer.buffer,
@ -1289,6 +1303,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
VkDescriptorBufferInfo bufferInfo[] = {
{ .buffer = lframe->shadowmat_buffer,
.offset = 0, .range = VK_WHOLE_SIZE, },
{ .buffer = lframe->shadowmat_id_buffer,
.offset = 0, .range = VK_WHOLE_SIZE, },
{ .buffer = lframe->id_buffer,
.offset = 0, .range = VK_WHOLE_SIZE, },
{ .buffer = lframe->light_buffer,
@ -1307,39 +1323,45 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &bufferInfo[0], },
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = lframe->shadowmat_set,
.dstBinding = 1,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &bufferInfo[1], },
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = lframe->lights_set,
.dstBinding = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &bufferInfo[1], },
.pBufferInfo = &bufferInfo[2], },
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = lframe->lights_set,
.dstBinding = 1,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &bufferInfo[2], },
.pBufferInfo = &bufferInfo[3], },
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = lframe->lights_set,
.dstBinding = 2,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &bufferInfo[3], },
.pBufferInfo = &bufferInfo[4], },
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = lframe->lights_set,
.dstBinding = 3,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &bufferInfo[4], },
.pBufferInfo = &bufferInfo[5], },
{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = lframe->lights_set,
.dstBinding = 4,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = &bufferInfo[5], },
.pBufferInfo = &bufferInfo[6], },
};
dfunc->vkUpdateDescriptorSets (device->dev, 6, bufferWrite, 0, 0);
dfunc->vkUpdateDescriptorSets (device->dev, 7, bufferWrite, 0, 0);
}
make_default_map (64, lctx->default_map, ctx);
@ -1501,6 +1523,19 @@ upload_light_matrices (lightingctx_t *lctx, vulkan_ctx_t *ctx)
QFV_PacketCopyBuffer (packet, lframe->shadowmat_buffer, 0, bb);
}
QFV_PacketSubmit (packet);
// FIXME temporary until batched shadow rendering is implemented
packet = QFV_PacketAcquire (ctx->staging);
size_t id_size = sizeof (uint32_t[MaxLights * 6]);
uint32_t *id_data = QFV_PacketExtend (packet, id_size);
for (int i = 0; i < MaxLights * 6; i++) {
id_data[i] = i;
}
for (size_t i = 0; i < lctx->frames.size; i++) {
auto lframe = &lctx->frames.a[i];
QFV_PacketCopyBuffer (packet, lframe->shadowmat_id_buffer, 0, bb);
}
QFV_PacketSubmit (packet);
}
static void
@ -1839,10 +1874,10 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
switch (lr->numLayers) {
case 6:
lr->renderpass_index = 2;
lr->renderpass_index = 6 - 1;
break;
case num_cascade:
lr->renderpass_index = 1;
lr->renderpass_index = num_cascade - 1;
break;
case 1:
lr->renderpass_index = 0;