[vulkan] Rework render pass setup

This splits up render pass creation so that the creation of the various
resources can be tailored to the needs of the actual render pass
sub-system. In addition, it gets window resizing mostly working (just
some problems with incorrect rendering).
This commit is contained in:
Bill Currie 2022-11-26 22:23:59 +09:00
parent 2cb3083f97
commit 3360578875
12 changed files with 228 additions and 205 deletions

View File

@ -36,7 +36,7 @@
typedef struct outputframe_s {
VkCommandBuffer cmd;
VkImageView view;
VkImageView input;
VkDescriptorSet set;
} outputframe_t;
@ -48,7 +48,7 @@ typedef struct outputctx_s {
VkPipeline pipeline;
VkPipelineLayout layout;
VkSampler sampler;
qfv_output_t output;
VkImageView input;
} outputctx_t;
struct vulkan_ctx_s;
@ -56,6 +56,6 @@ struct vulkan_ctx_s;
void Vulkan_Output_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_Output_CreateRenderPasses (struct vulkan_ctx_s *ctx);
qfv_output_t *Vulkan_Output_Get (struct vulkan_ctx_s *ctx)__attribute__((pure));
void Vulkan_Output_SetInput (struct vulkan_ctx_s *ctx, VkImageView input);
#endif//__QF_Vulkan_qf_output_h

View File

@ -36,7 +36,18 @@ typedef struct clearvalueset_s
typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame);
typedef struct qfv_output_s {
VkExtent2D extent;
VkImage image; // only if owned
VkImageView view;
VkFormat format;
uint32_t frames;
VkImageView *view_list; // per frame
VkImageLayout finalLayout;
} qfv_output_t;
typedef struct qfv_renderpass_s {
struct vulkan_ctx_s *vulkan_ctx;
vec4f_t color; // for debugging
const char *name; // for debugging
struct plitem_s *renderpassDef;
@ -47,9 +58,11 @@ typedef struct qfv_renderpass_s {
VkDeviceMemory attachmentMemory;
size_t attachmentMemory_size;
qfv_output_t output;
qfv_framebufferset_t *framebuffers;
VkViewport viewport;
VkRect2D scissor;
VkRect2D renderArea;
int order;
int primary_commands;
size_t subpassCount;
@ -59,17 +72,12 @@ typedef struct qfv_renderpass_s {
qfv_draw_t draw;
} qfv_renderpass_t;
struct qfv_output_s;
qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx,
const char *name,
struct qfv_output_s *output,
qfv_draw_t draw);
qfv_renderpass_t *Vulkan_CreateFunctionPass (struct vulkan_ctx_s *ctx,
const char *name,
qfv_draw_t function);
void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx,
qfv_renderpass_t *renderpass);
void Vulkan_CreateAttachments (struct vulkan_ctx_s *ctx,
qfv_renderpass_t *renderpass);
qfv_renderpass_t *QFV_RenderPass_New (struct vulkan_ctx_s *ctx,
const char *name, qfv_draw_t draw);
void QFV_RenderPass_Delete (qfv_renderpass_t *renderpass);
void QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass);
void QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass);
void QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass);
#endif//__QF_Vulkan_renderpass_h

View File

@ -67,15 +67,6 @@ enum {
QFV_attachSwapchain,
};
//FIXME name
typedef struct qfv_output_s {
VkExtent2D extent;
VkImageView view;
VkFormat format;
uint32_t frames;
VkImageView *view_list; // per frame
} qfv_output_t;
struct vulkan_ctx_s;
void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx);
void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx);

View File

@ -367,11 +367,6 @@ vulkan_end_frame (void)
VkCommandBufferBeginInfo beginInfo
= { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
VkRenderPassBeginInfo renderPassInfo = {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderArea = { {0, 0}, vulkan_ctx->swapchain->extent },
};
__auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4);
DARRAY_APPEND (&cmdBufs, frame->cmdBuffer);
@ -393,10 +388,14 @@ vulkan_end_frame (void)
QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color);
if (rpFrame->renderpass && rp->renderpass) {
renderPassInfo.framebuffer = rp->framebuffers->a[imageIndex];
renderPassInfo.renderPass = rp->renderpass;
renderPassInfo.clearValueCount = rp->clearValues->size;
renderPassInfo.pClearValues = rp->clearValues->a;
VkRenderPassBeginInfo renderPassInfo = {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = rp->renderpass,
.framebuffer = rp->framebuffers->a[imageIndex],
.renderArea = rp->renderArea,
.clearValueCount = rp->clearValues->size,
.pClearValues = rp->clearValues->a,
};
dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo,
rpFrame->subpassContents);

View File

@ -98,6 +98,20 @@
format = $properties.images.translucent.format;
};
};
output = {
image = {
@inherit = $properties.flat_color_image_template;
usage = color_attachment|input_attachment|sampled;
format = $output.format;
};
view = {
@inherit = $properties.flat_color_view_template;
image = $output.image;
format = $output.format;
};
format = r16g16b16a16_sfloat;
finalLayout = shader_read_only_optimal;
};
framebuffer = {
renderPass = deferred;
attachments = (depth, color, emission, normal, position, opaque,
@ -175,7 +189,7 @@
format = $output.format;
loadOp = clear;
storeOp = store;
finalLayout = shader_read_only_optimal;
finalLayout = $output.finalLayout;
},
);
subpasses = (
@ -289,14 +303,14 @@
dstAccessMask = input_attachment_read|depth_stencil_attachment_read;
dependencyFlags = by_region;
},
{
/*{
srcSubpass = ~0u; // external
dstSubpass = 1; // translucent
srcStageMask = compute_shader;
dstStageMask = vertex_input|draw_indirect;
srcAccessMask = shader_write;
dstAccessMask = vertex_attribute_read|indirect_command_read;
},
},*/
{
srcSubpass = 0; // depth
dstSubpass = 2; // g-buffer

View File

@ -1,45 +1,4 @@
{
flat_color_image_template = {
imageType = `2d;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|sampled;
initialLayout = undefined;
};
images = {
ocolor = {
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
};
};
flat_color_view_template = {
viewType = VK_IMAGE_VIEW_TYPE_2D;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
imageViews = {
ocolor = {
@inherit = $properties.flat_color_view_template;
image = ocolor;
format = $properties.images.ocolor.format;
};
};
framebuffer = {
renderPass = output;
attachments = ($output.view);

View File

@ -148,10 +148,16 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain)
sc->imageViews = DARRAY_ALLOCFIXED (qfv_imageviewset_t, numImages, malloc);
dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, sc->images->a);
for (uint32_t i = 0; i < numImages; i++) {
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE,
sc->images->a[i],
va (ctx->va_ctx, "image:swapchain:%d", i));
sc->imageViews->a[i]
= QFV_CreateImageView (ctx->device, sc->images->a[i],
VK_IMAGE_VIEW_TYPE_2D, sc->format,
VK_IMAGE_ASPECT_COLOR_BIT);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW,
sc->imageViews->a[i],
va (ctx->va_ctx, "iview:swapchain:%d", i));
}
return sc;
}

View File

@ -283,9 +283,8 @@ Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx)
// extents are dynamic and filled in for each light
// frame buffers are highly dynamic
qfv_output_t output = {};
__auto_type rp = Vulkan_CreateRenderPass (ctx, "shadow",
&output, lighting_draw_maps);
__auto_type rp = QFV_RenderPass_New (ctx, "shadow", lighting_draw_maps);
QFV_RenderPass_CreateRenderPass (rp);
rp->primary_commands = 1;
rp->order = QFV_rp_shadowmap;
DARRAY_APPEND (&ctx->renderPasses, rp);

View File

@ -176,9 +176,16 @@ main_draw (qfv_renderframe_t *rFrame)
void
Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx)
{
qfv_output_t *output = Vulkan_Output_Get (ctx);
__auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred",
output, main_draw);
__auto_type rp = QFV_RenderPass_New (ctx, "deferred", main_draw);
rp->output = (qfv_output_t) {
.extent = ctx->swapchain->extent,
.frames = ctx->swapchain->numImages,
};
QFV_RenderPass_CreateAttachments (rp);
QFV_RenderPass_CreateRenderPass (rp);
QFV_RenderPass_CreateFramebuffer (rp);
rp->order = QFV_rp_main;
DARRAY_APPEND (&ctx->renderPasses, rp);
Vulkan_Output_SetInput (ctx, rp->output.view);
}

View File

@ -80,18 +80,17 @@ acquire_image (qfv_renderframe_t *rFrame)
Vulkan_CreateSwapchain (ctx);
Vulkan_CreateCapture (ctx);
//FIXME
qfv_output_t output = {
__auto_type out = ctx->output_renderpass;
out->output = (qfv_output_t) {
.extent = ctx->swapchain->extent,
.view = ctx->swapchain->imageViews->a[0],
.format = ctx->swapchain->format,
.frames = ctx->swapchain->numImages,
.view_list = ctx->swapchain->imageViews->a,
};
ctx->output_renderpass->viewport.width = output.extent.width;
ctx->output_renderpass->viewport.height = output.extent.height;
ctx->output_renderpass->scissor.extent = output.extent;
Vulkan_Script_SetOutput (ctx, &output);
Vulkan_CreateAttachments (ctx, ctx->output_renderpass);
out->viewport.width = out->output.extent.width;
out->viewport.height = out->output.extent.height;
out->scissor.extent = out->output.extent;
QFV_RenderPass_CreateFramebuffer (out);
dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore,
0);
@ -109,15 +108,14 @@ update_input (qfv_renderframe_t *rFrame)
outputctx_t *octx = ctx->output_context;
uint32_t curFrame = ctx->curFrame;
outputframe_t *oframe = &octx->frames.a[curFrame];
qfv_renderpass_t *rp = ctx->output_renderpass;
if (rp->attachment_views->a[0] == oframe->view) {
if (oframe->input == octx->input) {
return;
}
oframe->view = rp->attachment_views->a[0];
oframe->input = octx->input;
VkDescriptorImageInfo imageInfo = {
octx->sampler, oframe->view,
octx->sampler, oframe->input,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkWriteDescriptorSet write[] = {
@ -189,33 +187,22 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx)
outputctx_t *octx = calloc (1, sizeof (outputctx_t));
ctx->output_context = octx;
qfv_output_t output = {
__auto_type out = QFV_RenderPass_New (ctx, "output", output_draw);
out->output = (qfv_output_t) {
.extent = ctx->swapchain->extent,
.view = ctx->swapchain->imageViews->a[0],
.format = ctx->swapchain->format,
.frames = ctx->swapchain->numImages,
.view_list = ctx->swapchain->imageViews->a,
};
__auto_type out = Vulkan_CreateRenderPass (ctx, "output",
&output, output_draw);
QFV_RenderPass_CreateRenderPass (out);
QFV_RenderPass_CreateFramebuffer (out);
ctx->output_renderpass = out;
out->order = QFV_rp_output;
octx->output = (qfv_output_t) {
.extent = ctx->swapchain->extent,
.view = out->attachment_views->a[0],
.format = VK_FORMAT_R16G16B16A16_SFLOAT,//FIXME
.frames = ctx->swapchain->numImages,
.view_list = malloc (sizeof (VkImageView) * ctx->swapchain->numImages),
};
for (int i = 0; i < ctx->swapchain->numImages; i++) {
octx->output.view_list[i] = octx->output.view;
}
DARRAY_APPEND (&ctx->renderPasses, out);
__auto_type pre = Vulkan_CreateFunctionPass (ctx, "preoutput",
preoutput_draw);
__auto_type pre = QFV_RenderPass_New (ctx, "preoutput", preoutput_draw);
pre->order = QFV_rp_preoutput;
DARRAY_APPEND (&ctx->renderPasses, pre);
}
@ -279,9 +266,9 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx)
free (octx);
}
qfv_output_t *
Vulkan_Output_Get (vulkan_ctx_t *ctx)
void
Vulkan_Output_SetInput (vulkan_ctx_t *ctx, VkImageView input)
{
outputctx_t *octx = ctx->output_context;
return &octx->output;
octx->input = input;
}

View File

@ -45,9 +45,7 @@
static plitem_t *
get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name)
{
if (!rp->renderpassDef) {
rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name);
}
rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name);
plitem_t *item = rp->renderpassDef;
if (!item) {
@ -87,20 +85,21 @@ destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
}
void
Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass)
{
vulkan_ctx_t *ctx = renderpass->vulkan_ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
__auto_type rp = renderpass;
scriptctx_t *sctx = ctx->script_context;
plitem_t *item = get_rp_item (ctx, rp, "images");
if (!item) {
return;
}
if (renderpass->framebuffers) {
destroy_framebuffers (ctx, renderpass);
if (rp->output.image) {
// if output has an image, then the view is owned by the renderpass
dfunc->vkDestroyImageView (device->dev, rp->output.view, 0);
dfunc->vkDestroyImage (device->dev, rp->output.image, 0);
free (rp->output.view_list);
rp->output.view_list = 0;
rp->output.view = 0;
rp->output.image = 0;
}
if (rp->attachment_views) {
for (size_t i = 0; i < rp->attachment_views->size; i++) {
@ -118,11 +117,35 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
rp->attachment_images = 0;
}
__auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef);
rp->attachment_images = images;
plitem_t *output_def = get_rp_item (ctx, rp, "output");
plitem_t *images_def = get_rp_item (ctx, rp, "images");
plitem_t *views_def = get_rp_item (ctx, rp, "imageViews");
plitem_t *rp_def = rp->renderpassDef;
size_t memSize = 0;
for (size_t i = 0; i < images->size; i++) {
memSize += get_image_size (images->a[i], device);
VkImage ref_image = 0;
if (output_def) {
// QFV_ParseOutput clears the structure, but extent and frames need to
// be preserved
qfv_output_t output = rp->output;
QFV_ParseOutput (ctx, &output, output_def, rp_def);
rp->output.format = output.format;
rp->output.finalLayout = output.finalLayout;
plitem_t *image = PL_ObjectForKey (output_def, "image");
Vulkan_Script_SetOutput (ctx, &rp->output);
rp->output.image = QFV_ParseImage (ctx, image, rp_def);
memSize += get_image_size (rp->output.image, device);
ref_image = rp->output.image;
}
if (images_def) {
__auto_type images = QFV_ParseImageSet (ctx, images_def, rp_def);
rp->attachment_images = images;
ref_image = images->a[0];
for (size_t i = 0; i < images->size; i++) {
memSize += get_image_size (images->a[i], device);
}
}
VkDeviceMemory mem = rp->attachmentMemory;
if (memSize > rp->attachmentMemory_size) {
@ -130,7 +153,7 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0);
}
rp->attachmentMemory_size = memSize;
mem = QFV_AllocImageMemory (device, images->a[0],
mem = QFV_AllocImageMemory (device, ref_image,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
memSize, 0);
rp->attachmentMemory = mem;
@ -138,40 +161,110 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
mem, "memory:framebuffers");
}
size_t offset = 0;
for (size_t i = 0; i < images->size; i++) {
QFV_BindImageMemory (device, images->a[i], mem, offset);
offset += get_image_size (images->a[i], device);
if (rp->output.image) {
QFV_BindImageMemory (device, rp->output.image, mem, offset);
offset += get_image_size (rp->output.image, device);
plitem_t *view = PL_ObjectForKey (output_def, "view");
Vulkan_Script_SetOutput (ctx, &rp->output);
rp->output.view = QFV_ParseImageView (ctx, view, rp_def);
rp->output.view_list = malloc (rp->output.frames
* sizeof (VkImageView));
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE,
rp->output.image,
va (ctx->va_ctx, "image:%s:output", rp->name));
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW,
rp->output.view,
va (ctx->va_ctx, "iview:%s:output", rp->name));
for (uint32_t i = 0; i < rp->output.frames; i++) {
rp->output.view_list[i] = rp->output.view;
}
}
if (rp->attachment_images) {
__auto_type images = rp->attachment_images;
for (size_t i = 0; i < images->size; i++) {
QFV_BindImageMemory (device, images->a[i], mem, offset);
offset += get_image_size (images->a[i], device);
}
}
item = get_rp_item (ctx, rp, "imageViews");
if (!item) {
return;
if (views_def) {
__auto_type views = QFV_ParseImageViewSet (ctx, views_def, rp_def);
rp->attachment_views = views;
}
}
void
QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass)
{
vulkan_ctx_t *ctx = renderpass->vulkan_ctx;
__auto_type rp = renderpass;
plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass");
if (rp_cfg) {
hashtab_t *tab = ctx->script_context->renderpasses;
const char *path;
path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", rp->name);
__auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path);
if (renderpass) {
rp->renderpass = renderpass;
} else {
Vulkan_Script_SetOutput (ctx, &rp->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",
rp->name));
}
rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg,
"subpasses"));
}
__auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef);
rp->attachment_views = views;
item = get_rp_item (ctx, rp, "framebuffer");
if (!item) {
return;
plitem_t *item = get_rp_item (ctx, rp, "clearValues");
rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef);
}
void
QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass)
{
vulkan_ctx_t *ctx = renderpass->vulkan_ctx;
__auto_type rp = renderpass;
if (renderpass->framebuffers) {
destroy_framebuffers (ctx, renderpass);
}
rp->framebuffers = QFV_AllocFrameBuffers (sctx->output.frames, malloc);
for (size_t i = 0; i < rp->framebuffers->size; i++) {
sctx->output.view = sctx->output.view_list[i];
rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item,
rp->renderpassDef);
plitem_t *fb_def = get_rp_item (ctx, rp, "framebuffer");
plitem_t *rp_def = rp->renderpassDef;
if (fb_def) {
rp->framebuffers = QFV_AllocFrameBuffers (rp->output.frames, malloc);
for (size_t i = 0; i < rp->framebuffers->size; i++) {
rp->output.view = rp->output.view_list[i];
Vulkan_Script_SetOutput (ctx, &rp->output);
rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, fb_def, rp_def);
}
}
int width = rp->output.extent.width;
int height = rp->output.extent.height;
rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 };
rp->scissor = (VkRect2D) { {0, 0}, {width, height} };
rp->renderArea = (VkRect2D) { {0, 0}, {width, height} };
}
static void
init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp,
qfv_renderframe_t *rFrame)
{
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
rFrame->vulkan_ctx = ctx;
rFrame->renderpass = rp;
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
rFrame->framebuffer = 0;
rFrame->subpassCount = rp->subpassCount;
rFrame->subpassInfo = 0;
if (rp->subpass_info) {
rFrame->subpassInfo = rp->subpass_info->a;
}
@ -188,6 +281,15 @@ destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
if (rp->output.image) {
// if output has an image, then the view is owned by the renderpass
dfunc->vkDestroyImageView (device->dev, rp->output.view, 0);
dfunc->vkDestroyImage (device->dev, rp->output.image, 0);
free (rp->output.view_list);
rp->output.view_list = 0;
rp->output.view = 0;
rp->output.image = 0;
}
if (rp->attachment_views) {
for (size_t i = 0; i < rp->attachment_views->size; i++) {
dfunc->vkDestroyImageView (device->dev,
@ -218,35 +320,14 @@ destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
}
qfv_renderpass_t *
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name,
qfv_output_t *output, qfv_draw_t draw)
QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function)
{
plitem_t *item;
qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t));
rp->vulkan_ctx = ctx;
rp->name = name;
rp->draw = function;
rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name);
plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass");
if (rp_cfg) {
hashtab_t *tab = ctx->script_context->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 {
Vulkan_Script_SetOutput (ctx, 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"));
}
plitem_t *rp_info = get_rp_item (ctx, rp, "info");
if (rp_info) {
plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info");
@ -255,7 +336,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name,
rp->renderpassDef);
if (rp->subpass_info->size < rp->subpassCount) {
Sys_Printf ("warning:%s:%d: insufficient entries in "
"subpass_info\n", name, PL_Line (subpass_info));
"subpass_info\n", rp->name, PL_Line (subpass_info));
}
if (!rp->subpassCount) {
rp->subpassCount = rp->subpass_info->size;
@ -268,35 +349,6 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name,
}
}
int width = output->extent.width;
int height = output->extent.height;
rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 };
rp->scissor = (VkRect2D) { {0, 0}, {width, height} };
DARRAY_INIT (&rp->frames, 4);
DARRAY_RESIZE (&rp->frames, ctx->frames.size);
for (size_t i = 0; i < rp->frames.size; i++) {
init_renderframe (ctx, rp, &rp->frames.a[i]);
}
item = get_rp_item (ctx, rp, "clearValues");
rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef);
rp->draw = draw;
Vulkan_CreateAttachments (ctx, rp);
return rp;
}
qfv_renderpass_t *
Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name,
qfv_draw_t function)
{
qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t));
rp->name = name;
rp->draw = function;
DARRAY_INIT (&rp->frames, 4);
DARRAY_RESIZE (&rp->frames, ctx->frames.size);
for (size_t i = 0; i < rp->frames.size; i++) {
@ -306,8 +358,9 @@ Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name,
}
void
Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
QFV_RenderPass_Delete (qfv_renderpass_t *renderpass)
{
vulkan_ctx_t *ctx = renderpass->vulkan_ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;

View File

@ -176,7 +176,7 @@ void
Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx)
{
for (size_t i = 0; i < ctx->renderPasses.size; i++) {
Vulkan_DestroyRenderPass (ctx, ctx->renderPasses.a[i]);
QFV_RenderPass_Delete (ctx->renderPasses.a[i]);
}
}