mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
[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:
parent
2cb3083f97
commit
3360578875
12 changed files with 228 additions and 205 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue