[vulkan] Get lighting mostly working

Lights seem to be good in renderdoc, but still need to get the compose
subpass working.
This commit is contained in:
Bill Currie 2023-06-22 21:36:14 +09:00
parent 2122d923d9
commit 942b503486
6 changed files with 72 additions and 94 deletions

View file

@ -122,7 +122,6 @@ struct qfv_orenderframe_s;
void Vulkan_Lighting_CreateRenderPasses (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Draw (struct qfv_orenderframe_s *rFrame);
void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_lighting_h

View file

@ -300,6 +300,14 @@ typedef struct qfv_subpass_s {
qfv_pipeline_t *pipelines;
} qfv_subpass_t;
typedef struct qfv_framebuffer_s {
uint32_t width;
uint32_t height;
uint32_t layers;
uint32_t num_attachments;
VkImageView *views;
} qfv_framebuffer_t;
typedef struct qfv_renderpass_s {
struct vulkan_ctx_s *vulkan_ctx;
qfv_label_t label; // for debugging
@ -307,10 +315,11 @@ typedef struct qfv_renderpass_s {
VkRenderPassBeginInfo beginInfo;
VkSubpassContents subpassContents;
qfv_framebufferinfo_t *framebufferinfo;
uint32_t subpass_count;
qfv_subpass_t *subpasses;
qfv_framebuffer_t framebuffer;
qfv_framebufferinfo_t *framebufferinfo;
} qfv_renderpass_t;
typedef struct qfv_render_s {
@ -378,6 +387,7 @@ typedef struct qfv_renderctx_s {
typedef struct qfv_taskctx_s {
struct vulkan_ctx_s *ctx;
qfv_pipeline_t *pipeline;
qfv_renderpass_t *renderpass;
VkCommandBuffer cmd;
} qfv_taskctx_t;

View file

@ -78,20 +78,17 @@ run_tasks (uint32_t task_count, qfv_taskinfo_t *tasks, qfv_taskctx_t *ctx)
}
static void
run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx)
run_pipeline (qfv_pipeline_t *pipeline, qfv_taskctx_t *taskctx)
{
qfv_device_t *device = ctx->device;
qfv_device_t *device = taskctx->ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
auto cmd = taskctx->cmd;
dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline);
dfunc->vkCmdSetViewport (cmd, 0, 1, &pipeline->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &pipeline->scissor);
qfv_taskctx_t taskctx = {
.ctx = ctx,
.pipeline = pipeline,
.cmd = cmd,
};
run_tasks (pipeline->task_count, pipeline->tasks, &taskctx);
taskctx->pipeline = pipeline;
run_tasks (pipeline->task_count, pipeline->tasks, taskctx);
if (pipeline->num_descriptorsets) {
dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint,
@ -105,18 +102,18 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx)
// https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/
static void
run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx)
run_subpass (qfv_subpass_t *sp, qfv_taskctx_t *taskctx)
{
qfv_device_t *device = ctx->device;
qfv_device_t *device = taskctx->ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo);
dfunc->vkBeginCommandBuffer (taskctx->cmd, &sp->beginInfo);
for (uint32_t i = 0; i < sp->pipeline_count; i++) {
__auto_type pipeline = &sp->pipelines[i];
run_pipeline (pipeline, cmd, ctx);
run_pipeline (pipeline, taskctx);
}
dfunc->vkEndCommandBuffer (cmd);
dfunc->vkEndCommandBuffer (taskctx->cmd);
}
static void
@ -139,11 +136,15 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx)
dfunc->vkCmdBeginRenderPass (cmd, &rp->beginInfo, rp->subpassContents);
for (uint32_t i = 0; i < rp->subpass_count; i++) {
__auto_type sp = &rp->subpasses[i];
VkCommandBuffer subcmd = QFV_GetCmdBuffer (ctx, true);
QFV_duCmdBeginLabel (device, cmd, sp->label.name,
{VEC4_EXP (sp->label.color)});
run_subpass (sp, subcmd, ctx);
dfunc->vkCmdExecuteCommands (cmd, 1, &subcmd);
qfv_taskctx_t taskctx = {
.ctx = ctx,
.renderpass = rp,
.cmd = QFV_GetCmdBuffer (ctx, true),
};
run_subpass (sp, &taskctx);
dfunc->vkCmdExecuteCommands (cmd, 1, &taskctx.cmd);
QFV_duCmdEndLabel (device, cmd);
//FIXME comment is a bit off as exactly one buffer is always submitted
//
@ -295,7 +296,7 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
__auto_type rctx = ctx->render_context;
auto fb = rp->framebufferinfo;
VkImageView attachments[fb->num_attachments];
auto attachments = rp->framebuffer.views;
VkFramebufferCreateInfo cInfo = {
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.attachmentCount = fb->num_attachments,

View file

@ -723,6 +723,7 @@ typedef struct {
qfv_pipeline_t *pipelines;
qfv_taskinfo_t *tasks;
VkDescriptorSet *descriptorsets;
VkImageView *attachment_views;
} jobptr_t;
static void
@ -796,10 +797,11 @@ init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo,
.clearValueCount = rpinfo->framebuffer.num_attachments,
.pClearValues = &jp->clearvalues[s->inds.num_attachments],
},
.framebufferinfo = &rpinfo->framebuffer,
.subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
.subpass_count = rpinfo->num_subpasses,
.subpasses = &jp->subpasses[s->inds.num_subpasses],
.framebuffer.views = &jp->attachment_views[s->inds.num_attachments],
.framebufferinfo = &rpinfo->framebuffer,
};
s->inds.num_attachments += rpinfo->framebuffer.num_attachments;
for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) {
@ -908,6 +910,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s)
size += sizeof (VkPipeline [counts->num_comp_pipelines]);
size += sizeof (VkPipelineLayout [s.inds.num_layouts]);
size += sizeof (VkDescriptorSet [counts->num_descriptorsets]);
size += sizeof (VkImageView [counts->num_attachments]);
rctx->job = malloc (size);
auto job = rctx->job;
@ -933,6 +936,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s)
job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses];
job->layouts = (VkPipelineLayout *) &job->pipelines[job->num_pipelines];
auto ds = (VkDescriptorSet *) &job->layouts[job->num_layouts];
auto av = (VkImageView *) &ds[counts->num_descriptorsets];
jobptr_t jp = {
.steps = job->steps,
.renders = rn,
@ -944,6 +948,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s)
.pipelines = pl,
.tasks = ti,
.descriptorsets = ds,
.attachment_views = av,
};
for (uint32_t i = 0; i < job->num_renderpasses; i++) {

View file

@ -147,78 +147,6 @@ update_lights (vulkan_ctx_t *ctx)
QFV_PacketSubmit (packet);
}
void
Vulkan_Lighting_Draw (qfv_orenderframe_t *rFrame)
{
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
qfv_orenderpass_t *renderpass = rFrame->renderpass;
lightingctx_t *lctx = ctx->lighting_context;
if (!lctx->scene) {
return;
}
if (lctx->scene->lights) {
update_lights (ctx);
}
lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = lframe->cmd;
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passLighting], cmd);
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
renderpass->renderpass, QFV_passLighting,
rFrame->framebuffer,
0, 0, 0,
};
VkCommandBufferBeginInfo beginInfo = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit,
};
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
QFV_duCmdBeginLabel (device, cmd, "lighting", { 0.6, 0.5, 0.6, 1});
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
lctx->pipeline);
lframe->bufferInfo[0].buffer = lframe->light_buffer;
lframe->attachInfo[0].imageView
= renderpass->attachment_views->a[QFV_attachDepth];
lframe->attachInfo[1].imageView
= renderpass->attachment_views->a[QFV_attachColor];
lframe->attachInfo[2].imageView
= renderpass->attachment_views->a[QFV_attachEmission];
lframe->attachInfo[3].imageView
= renderpass->attachment_views->a[QFV_attachNormal];
lframe->attachInfo[4].imageView
= renderpass->attachment_views->a[QFV_attachPosition];
dfunc->vkUpdateDescriptorSets (device->dev,
LIGHTING_DESCRIPTORS,
lframe->descriptors, 0, 0);
VkDescriptorSet sets[] = {
lframe->attachWrite[0].dstSet,
lframe->bufferWrite[0].dstSet,
lframe->shadowWrite.dstSet,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
lctx->layout, 0, 3, sets, 0, 0);
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
dfunc->vkCmdDraw (cmd, 3, 1, 0, 0);
QFV_duCmdEndLabel (device, cmd);
dfunc->vkEndCommandBuffer (cmd);
}
static void
lighting_draw_maps (qfv_orenderframe_t *rFrame)
{
@ -321,6 +249,42 @@ static VkWriteDescriptorSet base_image_write = {
static void
lights_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
{
auto taskctx = (qfv_taskctx_t *) ectx;
auto ctx = taskctx->ctx;
auto device = ctx->device;
auto dfunc = device->funcs;
auto lctx = ctx->lighting_context;
auto cmd = taskctx->cmd;
if (!lctx->scene) {
return;
}
if (lctx->scene->lights) {
update_lights (ctx);
}
lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame];
auto fb = &taskctx->renderpass->framebuffer;
lframe->bufferInfo[0].buffer = lframe->light_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];
dfunc->vkUpdateDescriptorSets (device->dev,
LIGHTING_DESCRIPTORS,
lframe->descriptors, 0, 0);
VkDescriptorSet sets[] = {
lframe->attachWrite[0].dstSet,
lframe->bufferWrite[0].dstSet,
lframe->shadowWrite.dstSet,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
lctx->layout, 0, 3, sets, 0, 0);
dfunc->vkCmdDraw (cmd, 3, 1, 0, 0);
}
static exprfunc_t lights_draw_func[] = {

View file

@ -158,7 +158,6 @@ static void
main_draw (qfv_orenderframe_t *rFrame)
{
Vulkan_RenderView (rFrame);
Vulkan_Lighting_Draw (rFrame);
Vulkan_Compose_Draw (rFrame);
}