mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[vulkan] Add a step and task to create a framebuffer
I don't like the current name (update_framebuffer), but if the referenced render pass doesn't have a framebuffer, one is created. The renderpass is referenced via the active renderpass of the named render step. Unfortunately, this has uncovered a bug in the setup of renderpass objects: main.deferred has output's renderpass, and main.deferred_cube and output have bogus renderpass objects.
This commit is contained in:
parent
8e25fb13d1
commit
2cadf040d3
6 changed files with 123 additions and 75 deletions
|
@ -313,10 +313,7 @@ typedef struct qfv_renderpass_s {
|
|||
VkRenderPassBeginInfo beginInfo;
|
||||
VkSubpassContents subpassContents;
|
||||
|
||||
//struct qfv_imageset_s *attachment_images;
|
||||
//struct qfv_imageviewset_s *attachment_views;
|
||||
//VkDeviceMemory attachmentMemory;
|
||||
//size_t attachmentMemory_size;
|
||||
qfv_framebufferinfo_t *framebufferinfo;
|
||||
//qfv_output_t output;
|
||||
|
||||
uint32_t subpass_count;
|
||||
|
@ -386,8 +383,6 @@ void QFV_AppendCmdBuffer (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd);
|
|||
void QFV_RunRenderJob (struct vulkan_ctx_s *ctx);
|
||||
void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx);
|
||||
void QFV_BuildRender (struct vulkan_ctx_s *ctx);
|
||||
void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx);
|
||||
void QFV_DestroyFramebuffer (struct vulkan_ctx_s *ctx);
|
||||
void QFV_Render_Init (struct vulkan_ctx_s *ctx);
|
||||
void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys);
|
||||
|
|
|
@ -118,7 +118,6 @@ vulkan_R_Init (void)
|
|||
|
||||
QFV_LoadRenderInfo (vulkan_ctx);
|
||||
QFV_BuildRender (vulkan_ctx);
|
||||
QFV_CreateFramebuffer (vulkan_ctx);
|
||||
|
||||
Skin_Init ();
|
||||
|
||||
|
|
|
@ -252,10 +252,10 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
QFV_DestroyFramebuffer (vulkan_ctx_t *ctx)
|
||||
{
|
||||
#if 0
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
__auto_type rctx = ctx->render_context;
|
||||
|
@ -267,31 +267,48 @@ QFV_DestroyFramebuffer (vulkan_ctx_t *ctx)
|
|||
rp->beginInfo.framebuffer = 0;
|
||||
dfunc->vkDestroyFramebuffer (device->dev, framebuffer, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static VkImageView __attribute__((pure))
|
||||
find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx)
|
||||
{
|
||||
__auto_type jinfo = rctx->jobinfo;
|
||||
__auto_type job = rctx->job;
|
||||
const char *name = ref->name;
|
||||
|
||||
if (strncmp (name, "$imageviews.", 7) == 0) {
|
||||
name += 7;
|
||||
}
|
||||
|
||||
void
|
||||
QFV_CreateFramebuffer (vulkan_ctx_t *ctx)
|
||||
{
|
||||
#if 0
|
||||
__auto_type rctx = ctx->render_context;
|
||||
__auto_type rinfo = rctx->renderinfo;
|
||||
__auto_type job = rctx->job;
|
||||
__auto_type rpInfo = &rinfo->renderpasses[0];
|
||||
__auto_type rp = &job->renderpasses[0];
|
||||
for (uint32_t i = 0; i < jinfo->num_imageviews; i++) {
|
||||
__auto_type vi = &jinfo->imageviews[i];
|
||||
__auto_type vo = &job->image_views[i];
|
||||
if (strcmp (name, vi->name) == 0) {
|
||||
return vo->image_view.view;
|
||||
}
|
||||
}
|
||||
Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name);
|
||||
}
|
||||
|
||||
VkImageView attachments[rpInfo->num_attachments];
|
||||
static void
|
||||
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];
|
||||
VkFramebufferCreateInfo cInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.attachmentCount = rpInfo->num_attachments,
|
||||
.attachmentCount = fb->num_attachments,
|
||||
.pAttachments = attachments,
|
||||
.renderPass = rp->beginInfo.renderPass,
|
||||
.width = rpInfo->framebuffer.width,
|
||||
.height = rpInfo->framebuffer.height,
|
||||
.layers = rpInfo->framebuffer.layers,
|
||||
.width = fb->width,
|
||||
.height = fb->height,
|
||||
.layers = fb->layers,
|
||||
};
|
||||
for (uint32_t i = 0; i < rpInfo->num_attachments; i++) {
|
||||
attachments[i] = find_imageview (&rpInfo->attachments[i].view, rctx);
|
||||
for (uint32_t i = 0; i < fb->num_attachments; i++) {
|
||||
attachments[i] = find_imageview (&fb->attachments[i].view, rctx);
|
||||
}
|
||||
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
@ -299,16 +316,82 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx)
|
|||
VkFramebuffer framebuffer;
|
||||
dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_FRAMEBUFFER, framebuffer,
|
||||
va (ctx->va_ctx, "framebuffer:%s", rpInfo->name));
|
||||
va (ctx->va_ctx, "framebuffer:%s", rp->label.name));
|
||||
|
||||
rp->beginInfo.framebuffer = framebuffer;
|
||||
for (uint32_t i = 0; i < rp->subpass_count; i++) {
|
||||
__auto_type sp = &rp->subpasses[i];
|
||||
sp->inherit.framebuffer = framebuffer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||
{
|
||||
__auto_type taskctx = (qfv_taskctx_t *) ectx;
|
||||
vulkan_ctx_t *ctx = taskctx->ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
VkDevice dev = device->dev;
|
||||
|
||||
__auto_type frame = &ctx->frames.a[ctx->curFrame];
|
||||
|
||||
dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000);
|
||||
}
|
||||
|
||||
static void
|
||||
update_framebuffer (const exprval_t **params, exprval_t *result,
|
||||
exprctx_t *ectx)
|
||||
{
|
||||
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||
auto ctx = taskctx->ctx;
|
||||
auto stepref = params[0];
|
||||
|
||||
// cache the render step referenced, using the parameter type as a flag
|
||||
// for whether the caching has been performed.
|
||||
if (stepref->type == &cexpr_string) {
|
||||
if (cexpr_string.size != cexpr_voidptr.size) {
|
||||
Sys_Error ("string and voidptr incompatible sizes");
|
||||
}
|
||||
auto name = *(const char **)stepref->value;
|
||||
((exprval_t *) stepref)->type = &cexpr_voidptr;
|
||||
*(void **)stepref->value = 0;
|
||||
auto job = ctx->render_context->job;
|
||||
for (uint32_t i = 0; i < job->num_steps; i++) {
|
||||
auto step = &job->steps[i];
|
||||
if (!strcmp (step->label.name, name)) {
|
||||
*(void **)stepref->value = step;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto step = *(qfv_step_t **)stepref->value;
|
||||
auto render = step->render;
|
||||
auto rp = render->active;
|
||||
|
||||
if (!rp->beginInfo.framebuffer) {
|
||||
QFV_CreateFramebuffer (ctx, rp);
|
||||
}
|
||||
}
|
||||
|
||||
static exprfunc_t wait_on_fence_func[] = {
|
||||
{ .func = wait_on_fence },
|
||||
{}
|
||||
};
|
||||
|
||||
static exprtype_t *update_framebuffer_params[] = {
|
||||
&cexpr_string,
|
||||
};
|
||||
static exprfunc_t update_framebuffer_func[] = {
|
||||
{ .func = update_framebuffer, .num_params = 1, update_framebuffer_params },
|
||||
{}
|
||||
};
|
||||
static exprsym_t render_task_syms[] = {
|
||||
{ "wait_on_fence", &cexpr_function, wait_on_fence_func },
|
||||
{ "update_framebuffer", &cexpr_function, update_framebuffer_func },
|
||||
{}
|
||||
};
|
||||
|
||||
void
|
||||
QFV_Render_Init (vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -320,6 +403,8 @@ QFV_Render_Init (vulkan_ctx_t *ctx)
|
|||
rctx->task_functions.symbols = syms;
|
||||
cexpr_init_symtab (&rctx->task_functions, &ectx);
|
||||
rctx->task_functions.symbols = 0;
|
||||
|
||||
QFV_Render_AddTasks (ctx, render_task_syms);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -330,7 +415,7 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx)
|
|||
__auto_type rctx = ctx->render_context;
|
||||
if (rctx->job) {
|
||||
__auto_type job = rctx->job;
|
||||
QFV_DestroyFramebuffer (ctx); //FIXME do properly
|
||||
//QFV_DestroyFramebuffer (ctx); //FIXME do properly
|
||||
for (uint32_t i = 0; i < job->num_renderpasses; i++) {
|
||||
dfunc->vkDestroyRenderPass (device->dev, job->renderpasses[i], 0);
|
||||
}
|
||||
|
|
|
@ -772,15 +772,16 @@ init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo,
|
|||
.vulkan_ctx = s->ctx,
|
||||
.label.name = rpinfo->name,
|
||||
.label.color = rpinfo->color,
|
||||
.subpass_count = rpinfo->num_subpasses,
|
||||
.subpasses = &jp->subpasses[s->inds.num_subpasses],
|
||||
.beginInfo = (VkRenderPassBeginInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = s->ptr.rp[s->inds.num_renderpasses],
|
||||
.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],
|
||||
};
|
||||
s->inds.num_attachments += rpinfo->framebuffer.num_attachments;
|
||||
for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) {
|
||||
|
@ -1127,24 +1128,3 @@ QFV_BuildRender (vulkan_ctx_t *ctx)
|
|||
create_objects (ctx, &counts);
|
||||
create_resources (ctx, &counts);
|
||||
}
|
||||
|
||||
static VkImageView __attribute__((pure, used))
|
||||
find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx)
|
||||
{
|
||||
__auto_type jinfo = rctx->jobinfo;
|
||||
__auto_type job = rctx->job;
|
||||
const char *name = ref->name;
|
||||
|
||||
if (strncmp (name, "$imageviews.", 7) == 0) {
|
||||
name += 7;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < jinfo->num_imageviews; i++) {
|
||||
__auto_type vi = &jinfo->imageviews[i];
|
||||
__auto_type vo = &job->image_views[i];
|
||||
if (strcmp (name, vi->name) == 0) {
|
||||
return vo->image_view.view;
|
||||
}
|
||||
}
|
||||
Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name);
|
||||
}
|
||||
|
|
|
@ -857,34 +857,34 @@ renderpasses = {
|
|||
loadOp = clear;
|
||||
finalLayout = depth_stencil_attachment_optimal;
|
||||
clearValue = { depthStencil = { depth = 1; stencil = 0; }; };
|
||||
view = $imageviews.depth;
|
||||
view = depth;
|
||||
};
|
||||
color = {
|
||||
@inherit = $attachment_base;
|
||||
format = $images.color.format;
|
||||
loadOp = clear;
|
||||
view = $imageviews.color;
|
||||
view = color;
|
||||
};
|
||||
emission = {
|
||||
@inherit = $attachment_base;
|
||||
format = $images.emission.format;
|
||||
loadOp = clear;
|
||||
view = $imageviews.emission;
|
||||
view = emission;
|
||||
};
|
||||
normal = {
|
||||
@inherit = $attachment_base;
|
||||
format = $images.normal.format;
|
||||
view = $imageviews.normal;
|
||||
view = normal;
|
||||
};
|
||||
position = {
|
||||
@inherit = $attachment_base;
|
||||
format = $images.position.format;
|
||||
view = $imageviews.position;
|
||||
view = position;
|
||||
};
|
||||
opaque = {
|
||||
@inherit = $attachment_base;
|
||||
format = $images.opaque.format;
|
||||
view = $imageviews.opaque;
|
||||
view = opaque;
|
||||
};
|
||||
output = {
|
||||
@inherit = $attachment_base;
|
||||
|
@ -892,7 +892,7 @@ renderpasses = {
|
|||
loadOp = clear;
|
||||
storeOp = store;
|
||||
finalLayout = $render_output.finalLayout;
|
||||
view = $imageviews.output;
|
||||
view = output;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1334,8 +1334,16 @@ steps = {
|
|||
);
|
||||
};
|
||||
};
|
||||
setup_main = {
|
||||
process = {
|
||||
tasks = (
|
||||
{ func = "update_framebuffer";
|
||||
params = ("\"main\""); },
|
||||
);
|
||||
};
|
||||
};
|
||||
main = {
|
||||
dependencies = (particles, shadow, translucent);
|
||||
dependencies = (setup_main, particles, shadow, translucent);
|
||||
render = {
|
||||
renderpasses = {
|
||||
deferred = $renderpasses.deferred;
|
||||
|
|
|
@ -259,20 +259,6 @@ _output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||
{
|
||||
__auto_type taskctx = (qfv_taskctx_t *) ectx;
|
||||
vulkan_ctx_t *ctx = taskctx->ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
VkDevice dev = device->dev;
|
||||
|
||||
__auto_type frame = &ctx->frames.a[ctx->curFrame];
|
||||
|
||||
dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000);
|
||||
}
|
||||
|
||||
static exprfunc_t acquire_output_func[] = {
|
||||
{ .func = acquire_output },
|
||||
{}
|
||||
|
@ -285,15 +271,10 @@ static exprfunc_t output_draw_func[] = {
|
|||
{ .func = _output_draw },
|
||||
{}
|
||||
};
|
||||
static exprfunc_t wait_on_fence_func[] = {
|
||||
{ .func = wait_on_fence },
|
||||
{}
|
||||
};
|
||||
static exprsym_t output_task_syms[] = {
|
||||
{ "acquire_output", &cexpr_function, acquire_output_func },
|
||||
{ "update_input", &cexpr_function, update_input_func },
|
||||
{ "output_draw", &cexpr_function, output_draw_func },
|
||||
{ "wait_on_fence", &cexpr_function, wait_on_fence_func },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue