[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 { typedef struct outputframe_s {
VkCommandBuffer cmd; VkCommandBuffer cmd;
VkImageView view; VkImageView input;
VkDescriptorSet set; VkDescriptorSet set;
} outputframe_t; } outputframe_t;
@ -48,7 +48,7 @@ typedef struct outputctx_s {
VkPipeline pipeline; VkPipeline pipeline;
VkPipelineLayout layout; VkPipelineLayout layout;
VkSampler sampler; VkSampler sampler;
qfv_output_t output; VkImageView input;
} outputctx_t; } outputctx_t;
struct vulkan_ctx_s; struct vulkan_ctx_s;
@ -56,6 +56,6 @@ struct vulkan_ctx_s;
void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); void Vulkan_Output_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_Output_CreateRenderPasses (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 #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 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 { typedef struct qfv_renderpass_s {
struct vulkan_ctx_s *vulkan_ctx;
vec4f_t color; // for debugging vec4f_t color; // for debugging
const char *name; // for debugging const char *name; // for debugging
struct plitem_s *renderpassDef; struct plitem_s *renderpassDef;
@ -47,9 +58,11 @@ typedef struct qfv_renderpass_s {
VkDeviceMemory attachmentMemory; VkDeviceMemory attachmentMemory;
size_t attachmentMemory_size; size_t attachmentMemory_size;
qfv_output_t output;
qfv_framebufferset_t *framebuffers; qfv_framebufferset_t *framebuffers;
VkViewport viewport; VkViewport viewport;
VkRect2D scissor; VkRect2D scissor;
VkRect2D renderArea;
int order; int order;
int primary_commands; int primary_commands;
size_t subpassCount; size_t subpassCount;
@ -59,17 +72,12 @@ typedef struct qfv_renderpass_s {
qfv_draw_t draw; qfv_draw_t draw;
} qfv_renderpass_t; } qfv_renderpass_t;
struct qfv_output_s; qfv_renderpass_t *QFV_RenderPass_New (struct vulkan_ctx_s *ctx,
qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx, const char *name, qfv_draw_t draw);
const char *name, void QFV_RenderPass_Delete (qfv_renderpass_t *renderpass);
struct qfv_output_s *output, void QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass);
qfv_draw_t draw); void QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass);
qfv_renderpass_t *Vulkan_CreateFunctionPass (struct vulkan_ctx_s *ctx, void QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass);
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);
#endif//__QF_Vulkan_renderpass_h #endif//__QF_Vulkan_renderpass_h

View file

@ -67,15 +67,6 @@ enum {
QFV_attachSwapchain, 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; struct vulkan_ctx_s;
void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx);
void Vulkan_CreateFrames (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 VkCommandBufferBeginInfo beginInfo
= { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; = { 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); __auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4);
DARRAY_APPEND (&cmdBufs, frame->cmdBuffer); DARRAY_APPEND (&cmdBufs, frame->cmdBuffer);
@ -393,10 +388,14 @@ vulkan_end_frame (void)
QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color); QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color);
if (rpFrame->renderpass && rp->renderpass) { if (rpFrame->renderpass && rp->renderpass) {
renderPassInfo.framebuffer = rp->framebuffers->a[imageIndex]; VkRenderPassBeginInfo renderPassInfo = {
renderPassInfo.renderPass = rp->renderpass; .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
renderPassInfo.clearValueCount = rp->clearValues->size; .renderPass = rp->renderpass,
renderPassInfo.pClearValues = rp->clearValues->a; .framebuffer = rp->framebuffers->a[imageIndex],
.renderArea = rp->renderArea,
.clearValueCount = rp->clearValues->size,
.pClearValues = rp->clearValues->a,
};
dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo,
rpFrame->subpassContents); rpFrame->subpassContents);

View file

@ -98,6 +98,20 @@
format = $properties.images.translucent.format; 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 = { framebuffer = {
renderPass = deferred; renderPass = deferred;
attachments = (depth, color, emission, normal, position, opaque, attachments = (depth, color, emission, normal, position, opaque,
@ -175,7 +189,7 @@
format = $output.format; format = $output.format;
loadOp = clear; loadOp = clear;
storeOp = store; storeOp = store;
finalLayout = shader_read_only_optimal; finalLayout = $output.finalLayout;
}, },
); );
subpasses = ( subpasses = (
@ -289,14 +303,14 @@
dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dstAccessMask = input_attachment_read|depth_stencil_attachment_read;
dependencyFlags = by_region; dependencyFlags = by_region;
}, },
{ /*{
srcSubpass = ~0u; // external srcSubpass = ~0u; // external
dstSubpass = 1; // translucent dstSubpass = 1; // translucent
srcStageMask = compute_shader; srcStageMask = compute_shader;
dstStageMask = vertex_input|draw_indirect; dstStageMask = vertex_input|draw_indirect;
srcAccessMask = shader_write; srcAccessMask = shader_write;
dstAccessMask = vertex_attribute_read|indirect_command_read; dstAccessMask = vertex_attribute_read|indirect_command_read;
}, },*/
{ {
srcSubpass = 0; // depth srcSubpass = 0; // depth
dstSubpass = 2; // g-buffer 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 = { framebuffer = {
renderPass = output; renderPass = output;
attachments = ($output.view); 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); sc->imageViews = DARRAY_ALLOCFIXED (qfv_imageviewset_t, numImages, malloc);
dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, sc->images->a); dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, sc->images->a);
for (uint32_t i = 0; i < numImages; i++) { 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] sc->imageViews->a[i]
= QFV_CreateImageView (ctx->device, sc->images->a[i], = QFV_CreateImageView (ctx->device, sc->images->a[i],
VK_IMAGE_VIEW_TYPE_2D, sc->format, VK_IMAGE_VIEW_TYPE_2D, sc->format,
VK_IMAGE_ASPECT_COLOR_BIT); 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; return sc;
} }

View file

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

View file

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

View file

@ -45,9 +45,7 @@
static plitem_t * static plitem_t *
get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) 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; plitem_t *item = rp->renderpassDef;
if (!item) { if (!item) {
@ -87,20 +85,21 @@ destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
} }
void 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_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
__auto_type rp = renderpass; __auto_type rp = renderpass;
scriptctx_t *sctx = ctx->script_context;
plitem_t *item = get_rp_item (ctx, rp, "images"); if (rp->output.image) {
if (!item) { // if output has an image, then the view is owned by the renderpass
return; dfunc->vkDestroyImageView (device->dev, rp->output.view, 0);
} dfunc->vkDestroyImage (device->dev, rp->output.image, 0);
free (rp->output.view_list);
if (renderpass->framebuffers) { rp->output.view_list = 0;
destroy_framebuffers (ctx, renderpass); rp->output.view = 0;
rp->output.image = 0;
} }
if (rp->attachment_views) { if (rp->attachment_views) {
for (size_t i = 0; i < rp->attachment_views->size; i++) { 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; rp->attachment_images = 0;
} }
__auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); plitem_t *output_def = get_rp_item (ctx, rp, "output");
rp->attachment_images = images; 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; size_t memSize = 0;
for (size_t i = 0; i < images->size; i++) { VkImage ref_image = 0;
memSize += get_image_size (images->a[i], device); 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; VkDeviceMemory mem = rp->attachmentMemory;
if (memSize > rp->attachmentMemory_size) { 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); dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0);
} }
rp->attachmentMemory_size = memSize; rp->attachmentMemory_size = memSize;
mem = QFV_AllocImageMemory (device, images->a[0], mem = QFV_AllocImageMemory (device, ref_image,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
memSize, 0); memSize, 0);
rp->attachmentMemory = mem; rp->attachmentMemory = mem;
@ -138,40 +161,110 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
mem, "memory:framebuffers"); mem, "memory:framebuffers");
} }
size_t offset = 0; size_t offset = 0;
for (size_t i = 0; i < images->size; i++) { if (rp->output.image) {
QFV_BindImageMemory (device, images->a[i], mem, offset); QFV_BindImageMemory (device, rp->output.image, mem, offset);
offset += get_image_size (images->a[i], device); 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 (views_def) {
if (!item) { __auto_type views = QFV_ParseImageViewSet (ctx, views_def, rp_def);
return; 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"); plitem_t *item = get_rp_item (ctx, rp, "clearValues");
if (!item) { rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef);
return; }
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); plitem_t *fb_def = get_rp_item (ctx, rp, "framebuffer");
for (size_t i = 0; i < rp->framebuffers->size; i++) { plitem_t *rp_def = rp->renderpassDef;
sctx->output.view = sctx->output.view_list[i]; if (fb_def) {
rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, rp->framebuffers = QFV_AllocFrameBuffers (rp->output.frames, malloc);
rp->renderpassDef); 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 static void
init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp,
qfv_renderframe_t *rFrame) qfv_renderframe_t *rFrame)
{ {
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
rFrame->vulkan_ctx = ctx; rFrame->vulkan_ctx = ctx;
rFrame->renderpass = rp; rFrame->renderpass = rp;
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
rFrame->framebuffer = 0;
rFrame->subpassCount = rp->subpassCount; rFrame->subpassCount = rp->subpassCount;
rFrame->subpassInfo = 0;
if (rp->subpass_info) { if (rp->subpass_info) {
rFrame->subpassInfo = rp->subpass_info->a; 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_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; 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) { if (rp->attachment_views) {
for (size_t i = 0; i < rp->attachment_views->size; i++) { for (size_t i = 0; i < rp->attachment_views->size; i++) {
dfunc->vkDestroyImageView (device->dev, dfunc->vkDestroyImageView (device->dev,
@ -218,35 +320,14 @@ destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
} }
qfv_renderpass_t * qfv_renderpass_t *
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function)
qfv_output_t *output, qfv_draw_t draw)
{ {
plitem_t *item;
qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t));
rp->vulkan_ctx = ctx;
rp->name = name; 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"); plitem_t *rp_info = get_rp_item (ctx, rp, "info");
if (rp_info) { if (rp_info) {
plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_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); rp->renderpassDef);
if (rp->subpass_info->size < rp->subpassCount) { if (rp->subpass_info->size < rp->subpassCount) {
Sys_Printf ("warning:%s:%d: insufficient entries in " 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) { if (!rp->subpassCount) {
rp->subpassCount = rp->subpass_info->size; 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_INIT (&rp->frames, 4);
DARRAY_RESIZE (&rp->frames, ctx->frames.size); DARRAY_RESIZE (&rp->frames, ctx->frames.size);
for (size_t i = 0; i < rp->frames.size; i++) { for (size_t i = 0; i < rp->frames.size; i++) {
@ -306,8 +358,9 @@ Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name,
} }
void 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_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;

View file

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