[vulkan] Support creating render passes with no render pass

Sounds odd, but it's part of the problem with calling two different
things with essentially the same name. The "high level" render pass in
question may be a compute pass, or a complex series of (Vulkan) render
passes and so won't create a Vulkan render pass for the "high level"
render pass (I do need to come up with a better name for it).
This commit is contained in:
Bill Currie 2022-05-31 10:56:00 +09:00
parent 3058a5103f
commit 71813af090
3 changed files with 49 additions and 22 deletions

View file

@ -49,7 +49,7 @@ typedef struct qfv_renderpass_s {
VkViewport viewport;
VkRect2D scissor;
int order;
int primary_commands;
size_t subpassCount;
qfv_subpassset_t *subpass_info;
qfv_renderframeset_t frames;

View file

@ -29,6 +29,7 @@
#endif
#include <stdlib.h>
#include <string.h>
#include "QF/cvar.h"
#include "QF/darray.h"
@ -111,6 +112,7 @@ vulkan_R_Init (void)
static void
vulkan_R_ClearState (void)
{
QFV_DeviceWaitIdle (vulkan_ctx->device);
r_refdef.worldmodel = 0;
R_ClearEfrags ();
R_ClearDlights ();
@ -287,7 +289,9 @@ vulkan_render_view (void)
for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) {
__auto_type rp = vulkan_ctx->renderPasses.a[i];
__auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame];
frame->framebuffer = rp->framebuffers->a[imageIndex];
if (rp->framebuffers) {
frame->framebuffer = rp->framebuffers->a[imageIndex];
}
rp->draw (rpFrame);
}
}
@ -339,13 +343,27 @@ vulkan_end_frame (void)
.renderArea = { {0, 0}, vulkan_ctx->swapchain->extent },
};
__auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4);
DARRAY_APPEND (&cmdBufs, frame->cmdBuffer);
dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo);
for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) {
__auto_type rp = vulkan_ctx->renderPasses.a[i];
__auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame];
if (rp->primary_commands) {
for (int j = 0; j < rpFrame->subpassCount; j++) {
__auto_type cmdSet = &rpFrame->subpassCmdSets[j];
size_t base = cmdBufs.size;
DARRAY_RESIZE (&cmdBufs, base + cmdSet->size);
memcpy (&cmdBufs.a[base], cmdSet->a,
cmdSet->size * sizeof (VkCommandBuffer));
}
continue;
}
QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color);
if (rpFrame->renderpass) {
if (rpFrame->renderpass && rp->renderpass) {
renderPassInfo.framebuffer = frame->framebuffer,
renderPassInfo.renderPass = rp->renderpass;
renderPassInfo.clearValueCount = rp->clearValues->size;
@ -403,12 +421,14 @@ vulkan_end_frame (void)
VkSubmitInfo submitInfo = {
VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
1, &frame->imageAvailableSemaphore, &waitStage,
1, &frame->cmdBuffer,
cmdBufs.size, cmdBufs.a,
1, &frame->renderDoneSemaphore,
};
dfunc->vkResetFences (dev, 1, &frame->fence);
dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence);
DARRAY_CLEAR (&cmdBufs);
if (vulkan_ctx->capture_callback) {
//FIXME look into "threading" this rather than waiting here
dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE,

View file

@ -51,9 +51,9 @@ get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name)
}
plitem_t *item = rp->renderpassDef;
if (!item || !(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading %s\n", name);
} else {
if (!item) {
Sys_Printf ("error loading %s\n", rp->name);
} else if ((item = PL_ObjectForKey (item, name))) {
Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name);
}
return item;
@ -201,31 +201,38 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name,
rp->name = name;
plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass");
hashtab_t *tab = ctx->renderpasses;
const char *path;
path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name);
__auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path);
if (renderpass) {
rp->renderpass = renderpass;
} else {
ctx->output = *output;
rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, rp->renderpassDef);
QFV_AddHandle (tab, path, (uint64_t) rp->renderpass);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS,
rp->renderpass, va (ctx->va_ctx, "renderpass:%s",
name));
if (rp_cfg) {
hashtab_t *tab = ctx->renderpasses;
const char *path;
path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name);
__auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path);
if (renderpass) {
rp->renderpass = renderpass;
} else {
ctx->output = *output;
rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg,
rp->renderpassDef);
QFV_AddHandle (tab, path, (uint64_t) rp->renderpass);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS,
rp->renderpass, va (ctx->va_ctx,
"renderpass:%s", name));
}
rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg,
"subpasses"));
}
rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, "subpasses"));
plitem_t *rp_info = get_rp_item (ctx, rp, "info");
if (rp_info) {
plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info");
if (subpass_info) {
rp->subpass_info = QFV_ParseSubpasses (ctx, subpass_info,
rp->renderpassDef);
if (rp->subpass_info->size > rp->subpassCount) {
if (rp->subpass_info->size < rp->subpassCount) {
Sys_Printf ("warning:%s:%d: insufficient entries in "
"subpass_info\n", name, PL_Line (subpass_info));
}
if (!rp->subpassCount) {
rp->subpassCount = rp->subpass_info->size;
}
}
plitem_t *color = PL_ObjectForKey (rp_info, "color");