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;
|
VkRenderPassBeginInfo beginInfo;
|
||||||
VkSubpassContents subpassContents;
|
VkSubpassContents subpassContents;
|
||||||
|
|
||||||
//struct qfv_imageset_s *attachment_images;
|
qfv_framebufferinfo_t *framebufferinfo;
|
||||||
//struct qfv_imageviewset_s *attachment_views;
|
|
||||||
//VkDeviceMemory attachmentMemory;
|
|
||||||
//size_t attachmentMemory_size;
|
|
||||||
//qfv_output_t output;
|
//qfv_output_t output;
|
||||||
|
|
||||||
uint32_t subpass_count;
|
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_RunRenderJob (struct vulkan_ctx_s *ctx);
|
||||||
void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx);
|
void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx);
|
||||||
void QFV_BuildRender (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_Init (struct vulkan_ctx_s *ctx);
|
||||||
void QFV_Render_Shutdown (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);
|
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_LoadRenderInfo (vulkan_ctx);
|
||||||
QFV_BuildRender (vulkan_ctx);
|
QFV_BuildRender (vulkan_ctx);
|
||||||
QFV_CreateFramebuffer (vulkan_ctx);
|
|
||||||
|
|
||||||
Skin_Init ();
|
Skin_Init ();
|
||||||
|
|
||||||
|
|
|
@ -252,10 +252,10 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void
|
void
|
||||||
QFV_DestroyFramebuffer (vulkan_ctx_t *ctx)
|
QFV_DestroyFramebuffer (vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
qfv_device_t *device = ctx->device;
|
qfv_device_t *device = ctx->device;
|
||||||
qfv_devfuncs_t *dfunc = device->funcs;
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
__auto_type rctx = ctx->render_context;
|
__auto_type rctx = ctx->render_context;
|
||||||
|
@ -267,31 +267,48 @@ QFV_DestroyFramebuffer (vulkan_ctx_t *ctx)
|
||||||
rp->beginInfo.framebuffer = 0;
|
rp->beginInfo.framebuffer = 0;
|
||||||
dfunc->vkDestroyFramebuffer (device->dev, framebuffer, 0);
|
dfunc->vkDestroyFramebuffer (device->dev, framebuffer, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
QFV_CreateFramebuffer (vulkan_ctx_t *ctx)
|
QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
__auto_type rctx = ctx->render_context;
|
__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];
|
|
||||||
|
|
||||||
VkImageView attachments[rpInfo->num_attachments];
|
auto fb = rp->framebufferinfo;
|
||||||
|
VkImageView attachments[fb->num_attachments];
|
||||||
VkFramebufferCreateInfo cInfo = {
|
VkFramebufferCreateInfo cInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
.attachmentCount = rpInfo->num_attachments,
|
.attachmentCount = fb->num_attachments,
|
||||||
.pAttachments = attachments,
|
.pAttachments = attachments,
|
||||||
.renderPass = rp->beginInfo.renderPass,
|
.renderPass = rp->beginInfo.renderPass,
|
||||||
.width = rpInfo->framebuffer.width,
|
.width = fb->width,
|
||||||
.height = rpInfo->framebuffer.height,
|
.height = fb->height,
|
||||||
.layers = rpInfo->framebuffer.layers,
|
.layers = fb->layers,
|
||||||
};
|
};
|
||||||
for (uint32_t i = 0; i < rpInfo->num_attachments; i++) {
|
for (uint32_t i = 0; i < fb->num_attachments; i++) {
|
||||||
attachments[i] = find_imageview (&rpInfo->attachments[i].view, rctx);
|
attachments[i] = find_imageview (&fb->attachments[i].view, rctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
qfv_device_t *device = ctx->device;
|
qfv_device_t *device = ctx->device;
|
||||||
|
@ -299,16 +316,82 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx)
|
||||||
VkFramebuffer framebuffer;
|
VkFramebuffer framebuffer;
|
||||||
dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer);
|
dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer);
|
||||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_FRAMEBUFFER, 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;
|
rp->beginInfo.framebuffer = framebuffer;
|
||||||
for (uint32_t i = 0; i < rp->subpass_count; i++) {
|
for (uint32_t i = 0; i < rp->subpass_count; i++) {
|
||||||
__auto_type sp = &rp->subpasses[i];
|
__auto_type sp = &rp->subpasses[i];
|
||||||
sp->inherit.framebuffer = framebuffer;
|
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
|
void
|
||||||
QFV_Render_Init (vulkan_ctx_t *ctx)
|
QFV_Render_Init (vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
|
@ -320,6 +403,8 @@ QFV_Render_Init (vulkan_ctx_t *ctx)
|
||||||
rctx->task_functions.symbols = syms;
|
rctx->task_functions.symbols = syms;
|
||||||
cexpr_init_symtab (&rctx->task_functions, &ectx);
|
cexpr_init_symtab (&rctx->task_functions, &ectx);
|
||||||
rctx->task_functions.symbols = 0;
|
rctx->task_functions.symbols = 0;
|
||||||
|
|
||||||
|
QFV_Render_AddTasks (ctx, render_task_syms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -330,7 +415,7 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx)
|
||||||
__auto_type rctx = ctx->render_context;
|
__auto_type rctx = ctx->render_context;
|
||||||
if (rctx->job) {
|
if (rctx->job) {
|
||||||
__auto_type job = 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++) {
|
for (uint32_t i = 0; i < job->num_renderpasses; i++) {
|
||||||
dfunc->vkDestroyRenderPass (device->dev, job->renderpasses[i], 0);
|
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,
|
.vulkan_ctx = s->ctx,
|
||||||
.label.name = rpinfo->name,
|
.label.name = rpinfo->name,
|
||||||
.label.color = rpinfo->color,
|
.label.color = rpinfo->color,
|
||||||
.subpass_count = rpinfo->num_subpasses,
|
|
||||||
.subpasses = &jp->subpasses[s->inds.num_subpasses],
|
|
||||||
.beginInfo = (VkRenderPassBeginInfo) {
|
.beginInfo = (VkRenderPassBeginInfo) {
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
.renderPass = s->ptr.rp[s->inds.num_renderpasses],
|
.renderPass = s->ptr.rp[s->inds.num_renderpasses],
|
||||||
.clearValueCount = rpinfo->framebuffer.num_attachments,
|
.clearValueCount = rpinfo->framebuffer.num_attachments,
|
||||||
.pClearValues = &jp->clearvalues[s->inds.num_attachments],
|
.pClearValues = &jp->clearvalues[s->inds.num_attachments],
|
||||||
},
|
},
|
||||||
|
.framebufferinfo = &rpinfo->framebuffer,
|
||||||
.subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
|
.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;
|
s->inds.num_attachments += rpinfo->framebuffer.num_attachments;
|
||||||
for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) {
|
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_objects (ctx, &counts);
|
||||||
create_resources (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;
|
loadOp = clear;
|
||||||
finalLayout = depth_stencil_attachment_optimal;
|
finalLayout = depth_stencil_attachment_optimal;
|
||||||
clearValue = { depthStencil = { depth = 1; stencil = 0; }; };
|
clearValue = { depthStencil = { depth = 1; stencil = 0; }; };
|
||||||
view = $imageviews.depth;
|
view = depth;
|
||||||
};
|
};
|
||||||
color = {
|
color = {
|
||||||
@inherit = $attachment_base;
|
@inherit = $attachment_base;
|
||||||
format = $images.color.format;
|
format = $images.color.format;
|
||||||
loadOp = clear;
|
loadOp = clear;
|
||||||
view = $imageviews.color;
|
view = color;
|
||||||
};
|
};
|
||||||
emission = {
|
emission = {
|
||||||
@inherit = $attachment_base;
|
@inherit = $attachment_base;
|
||||||
format = $images.emission.format;
|
format = $images.emission.format;
|
||||||
loadOp = clear;
|
loadOp = clear;
|
||||||
view = $imageviews.emission;
|
view = emission;
|
||||||
};
|
};
|
||||||
normal = {
|
normal = {
|
||||||
@inherit = $attachment_base;
|
@inherit = $attachment_base;
|
||||||
format = $images.normal.format;
|
format = $images.normal.format;
|
||||||
view = $imageviews.normal;
|
view = normal;
|
||||||
};
|
};
|
||||||
position = {
|
position = {
|
||||||
@inherit = $attachment_base;
|
@inherit = $attachment_base;
|
||||||
format = $images.position.format;
|
format = $images.position.format;
|
||||||
view = $imageviews.position;
|
view = position;
|
||||||
};
|
};
|
||||||
opaque = {
|
opaque = {
|
||||||
@inherit = $attachment_base;
|
@inherit = $attachment_base;
|
||||||
format = $images.opaque.format;
|
format = $images.opaque.format;
|
||||||
view = $imageviews.opaque;
|
view = opaque;
|
||||||
};
|
};
|
||||||
output = {
|
output = {
|
||||||
@inherit = $attachment_base;
|
@inherit = $attachment_base;
|
||||||
|
@ -892,7 +892,7 @@ renderpasses = {
|
||||||
loadOp = clear;
|
loadOp = clear;
|
||||||
storeOp = store;
|
storeOp = store;
|
||||||
finalLayout = $render_output.finalLayout;
|
finalLayout = $render_output.finalLayout;
|
||||||
view = $imageviews.output;
|
view = output;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1334,8 +1334,16 @@ steps = {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
setup_main = {
|
||||||
|
process = {
|
||||||
|
tasks = (
|
||||||
|
{ func = "update_framebuffer";
|
||||||
|
params = ("\"main\""); },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
main = {
|
main = {
|
||||||
dependencies = (particles, shadow, translucent);
|
dependencies = (setup_main, particles, shadow, translucent);
|
||||||
render = {
|
render = {
|
||||||
renderpasses = {
|
renderpasses = {
|
||||||
deferred = $renderpasses.deferred;
|
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[] = {
|
static exprfunc_t acquire_output_func[] = {
|
||||||
{ .func = acquire_output },
|
{ .func = acquire_output },
|
||||||
{}
|
{}
|
||||||
|
@ -285,15 +271,10 @@ static exprfunc_t output_draw_func[] = {
|
||||||
{ .func = _output_draw },
|
{ .func = _output_draw },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
static exprfunc_t wait_on_fence_func[] = {
|
|
||||||
{ .func = wait_on_fence },
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
static exprsym_t output_task_syms[] = {
|
static exprsym_t output_task_syms[] = {
|
||||||
{ "acquire_output", &cexpr_function, acquire_output_func },
|
{ "acquire_output", &cexpr_function, acquire_output_func },
|
||||||
{ "update_input", &cexpr_function, update_input_func },
|
{ "update_input", &cexpr_function, update_input_func },
|
||||||
{ "output_draw", &cexpr_function, output_draw_func },
|
{ "output_draw", &cexpr_function, output_draw_func },
|
||||||
{ "wait_on_fence", &cexpr_function, wait_on_fence_func },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue