mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-11 07:42:18 +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 {
|
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue