mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-14 00:40:55 +00:00
[vulkan] Pass validation for the first frame
The new render system now passes validation for the first frame (but no drawing is done by the various subsystems yet). Something is wrong with how swap chain semaphores are handled thus the second frame fails. Frame buffer attachments can now be defined externally, with "$swapchain" supported for now (in which case, the swap chain defines the size of the frame buffer). Also, render pass render areas and pipeline viewport and scissor rects are updated when necessary.
This commit is contained in:
parent
38453f3d2f
commit
7da8399220
6 changed files with 240 additions and 87 deletions
|
@ -122,6 +122,7 @@ typedef struct qfv_dependencyinfo_s {
|
||||||
|
|
||||||
typedef struct qfv_attachmentinfo_s {
|
typedef struct qfv_attachmentinfo_s {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
int line;
|
||||||
VkAttachmentDescriptionFlags flags;
|
VkAttachmentDescriptionFlags flags;
|
||||||
VkFormat format;
|
VkFormat format;
|
||||||
VkSampleCountFlagBits samples;
|
VkSampleCountFlagBits samples;
|
||||||
|
@ -133,6 +134,7 @@ typedef struct qfv_attachmentinfo_s {
|
||||||
VkImageLayout finalLayout;
|
VkImageLayout finalLayout;
|
||||||
VkClearValue clearValue;
|
VkClearValue clearValue;
|
||||||
qfv_reference_t view;
|
qfv_reference_t view;
|
||||||
|
const char *external;
|
||||||
} qfv_attachmentinfo_t;
|
} qfv_attachmentinfo_t;
|
||||||
|
|
||||||
typedef struct qfv_taskinfo_s {
|
typedef struct qfv_taskinfo_s {
|
||||||
|
@ -225,7 +227,6 @@ typedef struct qfv_renderinfo_s {
|
||||||
|
|
||||||
uint32_t num_renderpasses;
|
uint32_t num_renderpasses;
|
||||||
qfv_renderpassinfo_t *renderpasses;
|
qfv_renderpassinfo_t *renderpasses;
|
||||||
qfv_output_t output;
|
|
||||||
} qfv_renderinfo_t;
|
} qfv_renderinfo_t;
|
||||||
|
|
||||||
typedef struct qfv_processinfo_s {
|
typedef struct qfv_processinfo_s {
|
||||||
|
@ -274,13 +275,6 @@ typedef struct qfv_label_s {
|
||||||
const char *name;
|
const char *name;
|
||||||
} qfv_label_t;
|
} qfv_label_t;
|
||||||
|
|
||||||
typedef struct qfv_bar_s {
|
|
||||||
VkBuffer *buffers;
|
|
||||||
VkDeviceSize *offsets;
|
|
||||||
uint32_t firstBinding;
|
|
||||||
uint32_t bindingCount;
|
|
||||||
} qfv_bar_t;
|
|
||||||
|
|
||||||
typedef struct qfv_pipeline_s {
|
typedef struct qfv_pipeline_s {
|
||||||
qfv_label_t label;
|
qfv_label_t label;
|
||||||
VkPipelineBindPoint bindPoint;
|
VkPipelineBindPoint bindPoint;
|
||||||
|
@ -314,7 +308,6 @@ typedef struct qfv_renderpass_s {
|
||||||
VkSubpassContents subpassContents;
|
VkSubpassContents subpassContents;
|
||||||
|
|
||||||
qfv_framebufferinfo_t *framebufferinfo;
|
qfv_framebufferinfo_t *framebufferinfo;
|
||||||
//qfv_output_t output;
|
|
||||||
|
|
||||||
uint32_t subpass_count;
|
uint32_t subpass_count;
|
||||||
qfv_subpass_t *subpasses;
|
qfv_subpass_t *subpasses;
|
||||||
|
@ -325,6 +318,7 @@ typedef struct qfv_render_s {
|
||||||
qfv_renderpass_t *active;
|
qfv_renderpass_t *active;
|
||||||
qfv_renderpass_t *renderpasses;
|
qfv_renderpass_t *renderpasses;
|
||||||
uint32_t num_renderpasses;
|
uint32_t num_renderpasses;
|
||||||
|
qfv_output_t output;
|
||||||
} qfv_render_t;
|
} qfv_render_t;
|
||||||
|
|
||||||
typedef struct qfv_compute_s {
|
typedef struct qfv_compute_s {
|
||||||
|
@ -386,6 +380,8 @@ void QFV_BuildRender (struct vulkan_ctx_s *ctx);
|
||||||
void QFV_Render_Init (struct vulkan_ctx_s *ctx);
|
void QFV_Render_Init (struct vulkan_ctx_s *ctx);
|
||||||
void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx);
|
void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx);
|
||||||
void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys);
|
void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys);
|
||||||
|
|
||||||
|
qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job);
|
||||||
#endif//__QFCC__
|
#endif//__QFCC__
|
||||||
|
|
||||||
#endif//__QF_Vulkan_render_h
|
#endif//__QF_Vulkan_render_h
|
||||||
|
|
|
@ -44,9 +44,11 @@
|
||||||
#include "QF/Vulkan/command.h"
|
#include "QF/Vulkan/command.h"
|
||||||
#include "QF/Vulkan/debug.h"
|
#include "QF/Vulkan/debug.h"
|
||||||
#include "QF/Vulkan/device.h"
|
#include "QF/Vulkan/device.h"
|
||||||
|
#include "QF/Vulkan/image.h"
|
||||||
|
#include "QF/Vulkan/pipeline.h"
|
||||||
#include "QF/Vulkan/render.h"
|
#include "QF/Vulkan/render.h"
|
||||||
#include "QF/Vulkan/resource.h"
|
#include "QF/Vulkan/resource.h"
|
||||||
#include "QF/Vulkan/pipeline.h"
|
#include "QF/Vulkan/swapchain.h"
|
||||||
#include "vid_vulkan.h"
|
#include "vid_vulkan.h"
|
||||||
|
|
||||||
#include "vkparse.h"
|
#include "vkparse.h"
|
||||||
|
@ -119,7 +121,6 @@ run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *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;
|
||||||
dfunc->vkResetCommandBuffer (cmd, 0);
|
|
||||||
dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo);
|
dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo);
|
||||||
QFV_duCmdBeginLabel (device, cmd, sp->label.name,
|
QFV_duCmdBeginLabel (device, cmd, sp->label.name,
|
||||||
{VEC4_EXP (sp->label.color)});
|
{VEC4_EXP (sp->label.color)});
|
||||||
|
@ -308,7 +309,17 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||||
.layers = fb->layers,
|
.layers = fb->layers,
|
||||||
};
|
};
|
||||||
for (uint32_t i = 0; i < fb->num_attachments; i++) {
|
for (uint32_t i = 0; i < fb->num_attachments; i++) {
|
||||||
attachments[i] = find_imageview (&fb->attachments[i].view, rctx);
|
if (fb->attachments[i].external) {
|
||||||
|
attachments[i] = 0;
|
||||||
|
if (!strcmp (fb->attachments[i].external, "$swapchain")) {
|
||||||
|
auto sc = ctx->swapchain;
|
||||||
|
attachments[i] = sc->imageViews->a[ctx->swapImageIndex];
|
||||||
|
cInfo.width = sc->extent.width;
|
||||||
|
cInfo.height = sc->extent.height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attachments[i] = find_imageview (&fb->attachments[i].view, rctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qfv_device_t *device = ctx->device;
|
qfv_device_t *device = ctx->device;
|
||||||
|
@ -339,36 +350,49 @@ wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||||
dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000);
|
dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
renderpass_update_viewper_sissor (qfv_renderpass_t *rp,
|
||||||
|
const qfv_output_t *output)
|
||||||
|
{
|
||||||
|
rp->beginInfo.renderArea.extent = output->extent;
|
||||||
|
for (uint32_t i = 0; i < rp->subpass_count; i++) {
|
||||||
|
auto sp = &rp->subpasses[i];
|
||||||
|
for (uint32_t j = 0; j < sp->pipeline_count; j++) {
|
||||||
|
auto pl = &sp->pipelines[j];
|
||||||
|
pl->viewport.width = output->extent.width;
|
||||||
|
pl->viewport.height = output->extent.height;
|
||||||
|
pl->scissor.extent = output->extent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_viewport_scissor (qfv_render_t *render, const qfv_output_t *output)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < render->num_renderpasses; i++) {
|
||||||
|
renderpass_update_viewper_sissor (&render->renderpasses[i], output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_framebuffer (const exprval_t **params, exprval_t *result,
|
update_framebuffer (const exprval_t **params, exprval_t *result,
|
||||||
exprctx_t *ectx)
|
exprctx_t *ectx)
|
||||||
{
|
{
|
||||||
auto taskctx = (qfv_taskctx_t *) ectx;
|
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||||
auto ctx = taskctx->ctx;
|
auto ctx = taskctx->ctx;
|
||||||
auto stepref = params[0];
|
auto job = ctx->render_context->job;
|
||||||
|
auto step = QFV_GetStep (params[0], job);
|
||||||
// cache the render step referenced, using the parameter type as a flag
|
|
||||||
// for whether the caching has been performed.
|
|
||||||
if (stepref->type == &cexpr_string) {
|
|
||||||
if (cexpr_string.size != cexpr_voidptr.size) {
|
|
||||||
Sys_Error ("string and voidptr incompatible sizes");
|
|
||||||
}
|
|
||||||
auto name = *(const char **)stepref->value;
|
|
||||||
((exprval_t *) stepref)->type = &cexpr_voidptr;
|
|
||||||
*(void **)stepref->value = 0;
|
|
||||||
auto job = ctx->render_context->job;
|
|
||||||
for (uint32_t i = 0; i < job->num_steps; i++) {
|
|
||||||
auto step = &job->steps[i];
|
|
||||||
if (!strcmp (step->label.name, name)) {
|
|
||||||
*(void **)stepref->value = step;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto step = *(qfv_step_t **)stepref->value;
|
|
||||||
auto render = step->render;
|
auto render = step->render;
|
||||||
auto rp = render->active;
|
auto rp = render->active;
|
||||||
|
|
||||||
|
qfv_output_t output = {};
|
||||||
|
Vulkan_ConfigOutput (ctx, &output);
|
||||||
|
if (output.extent.width != render->output.extent.width
|
||||||
|
|| output.extent.height != render->output.extent.height) {
|
||||||
|
//FIXME framebuffer image creation here
|
||||||
|
update_viewport_scissor (render, &output);
|
||||||
|
}
|
||||||
|
|
||||||
if (!rp->beginInfo.framebuffer) {
|
if (!rp->beginInfo.framebuffer) {
|
||||||
QFV_CreateFramebuffer (ctx, rp);
|
QFV_CreateFramebuffer (ctx, rp);
|
||||||
}
|
}
|
||||||
|
@ -466,3 +490,30 @@ QFV_Render_AddTasks (vulkan_ctx_t *ctx, exprsym_t *task_syms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qfv_step_t *
|
||||||
|
QFV_GetStep (const exprval_t *param, qfv_job_t *job)
|
||||||
|
{
|
||||||
|
// this is a little evil, but need to update the type after resolving
|
||||||
|
// the step name
|
||||||
|
auto stepref = (exprval_t *) param;
|
||||||
|
|
||||||
|
// cache the render step referenced, using the parameter type as a flag
|
||||||
|
// for whether the caching has been performed.
|
||||||
|
if (stepref->type == &cexpr_string) {
|
||||||
|
if (cexpr_string.size != cexpr_voidptr.size) {
|
||||||
|
Sys_Error ("string and voidptr incompatible sizes");
|
||||||
|
}
|
||||||
|
auto name = *(const char **)stepref->value;
|
||||||
|
stepref->type = &cexpr_voidptr;
|
||||||
|
*(void **)stepref->value = 0;
|
||||||
|
for (uint32_t i = 0; i < job->num_steps; i++) {
|
||||||
|
auto step = &job->steps[i];
|
||||||
|
if (!strcmp (step->label.name, name)) {
|
||||||
|
*(void **)stepref->value = step;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *(qfv_step_t **)stepref->value;
|
||||||
|
}
|
||||||
|
|
|
@ -44,9 +44,10 @@
|
||||||
#include "QF/Vulkan/command.h"
|
#include "QF/Vulkan/command.h"
|
||||||
#include "QF/Vulkan/debug.h"
|
#include "QF/Vulkan/debug.h"
|
||||||
#include "QF/Vulkan/device.h"
|
#include "QF/Vulkan/device.h"
|
||||||
|
#include "QF/Vulkan/pipeline.h"
|
||||||
#include "QF/Vulkan/render.h"
|
#include "QF/Vulkan/render.h"
|
||||||
#include "QF/Vulkan/resource.h"
|
#include "QF/Vulkan/resource.h"
|
||||||
#include "QF/Vulkan/pipeline.h"
|
#include "QF/Vulkan/swapchain.h"
|
||||||
#include "vid_vulkan.h"
|
#include "vid_vulkan.h"
|
||||||
|
|
||||||
#include "vkparse.h"
|
#include "vkparse.h"
|
||||||
|
@ -211,13 +212,15 @@ count_stuff (qfv_jobinfo_t *jobinfo, objcount_t *counts)
|
||||||
static void
|
static void
|
||||||
create_resources (vulkan_ctx_t *ctx, objcount_t *counts)
|
create_resources (vulkan_ctx_t *ctx, objcount_t *counts)
|
||||||
{
|
{
|
||||||
__auto_type rctx = ctx->render_context;
|
auto rctx = ctx->render_context;
|
||||||
__auto_type jinfo = rctx->jobinfo;
|
auto jinfo = rctx->jobinfo;
|
||||||
__auto_type job = rctx->job;
|
auto job = rctx->job;
|
||||||
|
|
||||||
job->resources = malloc (sizeof(qfv_resource_t)
|
size_t size = sizeof (qfv_resource_t);
|
||||||
+ counts->num_images * sizeof (qfv_resobj_t)
|
size += sizeof (qfv_resobj_t [counts->num_images]);
|
||||||
+ counts->num_imageviews * sizeof (qfv_resobj_t));
|
size += sizeof (qfv_resobj_t [counts->num_imageviews]);
|
||||||
|
|
||||||
|
job->resources = malloc (size);
|
||||||
job->images = (qfv_resobj_t *) &job->resources[1];
|
job->images = (qfv_resobj_t *) &job->resources[1];
|
||||||
job->image_views = &job->images[counts->num_images];
|
job->image_views = &job->images[counts->num_images];
|
||||||
|
|
||||||
|
@ -646,17 +649,32 @@ init_atCreate (uint32_t index, qfv_attachmentinfo_t *attachments, objstate_t *s)
|
||||||
__auto_type atc = &s->ptr.attach[s->inds.num_attachments];
|
__auto_type atc = &s->ptr.attach[s->inds.num_attachments];
|
||||||
__auto_type cvc = &s->ptr.clear[s->inds.num_attachments];
|
__auto_type cvc = &s->ptr.clear[s->inds.num_attachments];
|
||||||
|
|
||||||
*atc = (VkAttachmentDescription) {
|
if (ati->external) {
|
||||||
.flags = ati->flags,
|
if (!strcmp (ati->external, "$swapchain")) {
|
||||||
.format = ati->format,
|
*atc = (VkAttachmentDescription) {
|
||||||
.samples = ati->samples,
|
.format = s->ctx->swapchain->format,
|
||||||
.loadOp = ati->loadOp,
|
.samples = 1,
|
||||||
.storeOp = ati->storeOp,
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||||
.stencilLoadOp = ati->stencilLoadOp,
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
.stencilStoreOp = ati->stencilStoreOp,
|
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
.initialLayout = ati->initialLayout,
|
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
.finalLayout = ati->finalLayout,
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
};
|
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*atc = (VkAttachmentDescription) {
|
||||||
|
.flags = ati->flags,
|
||||||
|
.format = ati->format,
|
||||||
|
.samples = ati->samples,
|
||||||
|
.loadOp = ati->loadOp,
|
||||||
|
.storeOp = ati->storeOp,
|
||||||
|
.stencilLoadOp = ati->stencilLoadOp,
|
||||||
|
.stencilStoreOp = ati->stencilStoreOp,
|
||||||
|
.initialLayout = ati->initialLayout,
|
||||||
|
.finalLayout = ati->finalLayout,
|
||||||
|
};
|
||||||
|
}
|
||||||
*cvc = ati->clearValue;
|
*cvc = ati->clearValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,7 +955,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s)
|
||||||
for (uint32_t i = 0; i < s.inds.num_layouts; i++) {
|
for (uint32_t i = 0; i < s.inds.num_layouts; i++) {
|
||||||
job->layouts[i] = s.ptr.layouts[i].layout;
|
job->layouts[i] = s.ptr.layouts[i].layout;
|
||||||
}
|
}
|
||||||
memcpy (cv, s.ptr.clear, counts->num_attachments * sizeof (VkClearValue));
|
memcpy (cv, s.ptr.clear, sizeof (VkClearValue [counts->num_attachments ]));
|
||||||
|
|
||||||
uint32_t num_layouts = s.inds.num_layouts;
|
uint32_t num_layouts = s.inds.num_layouts;
|
||||||
s.inds = (objcount_t) {};
|
s.inds = (objcount_t) {};
|
||||||
|
|
|
@ -939,7 +939,7 @@ renderpasses = {
|
||||||
alias:depth = {
|
alias:depth = {
|
||||||
color = $color.alias;
|
color = $color.alias;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "alias_draw"; },
|
{ func = alias_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -964,7 +964,7 @@ renderpasses = {
|
||||||
iqm:depth = {
|
iqm:depth = {
|
||||||
color = $color.iqm;
|
color = $color.iqm;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "iqm_draw"; },
|
{ func = iqm_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -977,7 +977,7 @@ renderpasses = {
|
||||||
sprite:depth = {
|
sprite:depth = {
|
||||||
color = $color.sprite;
|
color = $color.sprite;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "sprite_draw"; },
|
{ func = sprite_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -1121,7 +1121,7 @@ renderpasses = {
|
||||||
alias:gbuffer = {
|
alias:gbuffer = {
|
||||||
color = $color.alias;
|
color = $color.alias;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "alias_draw"; },
|
{ func = alias_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -1135,7 +1135,7 @@ renderpasses = {
|
||||||
iqm:gbuffer = {
|
iqm:gbuffer = {
|
||||||
color = $color.iqm;
|
color = $color.iqm;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "iqm_draw"; },
|
{ func = iqm_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -1149,7 +1149,7 @@ renderpasses = {
|
||||||
sprite:gbuffer = {
|
sprite:gbuffer = {
|
||||||
color = $color.sprite;
|
color = $color.sprite;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "sprite_draw"; },
|
{ func = sprite_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -1189,7 +1189,7 @@ renderpasses = {
|
||||||
|
|
||||||
color = $color.lights;
|
color = $color.lights;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "lights_draw"; },
|
{ func = lights_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -1220,7 +1220,7 @@ renderpasses = {
|
||||||
|
|
||||||
color = $color.compose;
|
color = $color.compose;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "compose_draw"; },
|
{ func = compose_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -1243,18 +1243,9 @@ renderpasses = {
|
||||||
output = {
|
output = {
|
||||||
color = "[0, 1, 1, 1]";
|
color = "[0, 1, 1, 1]";
|
||||||
framebuffer = {
|
framebuffer = {
|
||||||
width = $render_output.extent.width;
|
|
||||||
height = $render_output.extent.height;
|
|
||||||
layers = 1;
|
layers = 1;
|
||||||
attachments = {
|
attachments = {
|
||||||
output = {
|
output = $swapchain;
|
||||||
@inherit = $attachment_base;
|
|
||||||
format = $render_output.format;
|
|
||||||
loadOp = clear;
|
|
||||||
storeOp = store;
|
|
||||||
finalLayout = present_src_khr;
|
|
||||||
view = $render_output.view;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
subpasses = {
|
subpasses = {
|
||||||
|
@ -1271,7 +1262,7 @@ renderpasses = {
|
||||||
|
|
||||||
color = $color.output;
|
color = $color.output;
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "output_draw"; },
|
{ func = output_draw; },
|
||||||
);
|
);
|
||||||
|
|
||||||
stages = (
|
stages = (
|
||||||
|
@ -1289,7 +1280,7 @@ steps = {
|
||||||
wait_on_fence = {
|
wait_on_fence = {
|
||||||
process = {
|
process = {
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "wait_on_fence"; },
|
{ func = wait_on_fence; },
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1300,7 +1291,7 @@ steps = {
|
||||||
part:update = {
|
part:update = {
|
||||||
color = "[0.3, 0.8, 0.9]";
|
color = "[0.3, 0.8, 0.9]";
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "update_particles"; }
|
{ func = update_particles; }
|
||||||
);
|
);
|
||||||
stage = {
|
stage = {
|
||||||
name = main;
|
name = main;
|
||||||
|
@ -1311,7 +1302,7 @@ steps = {
|
||||||
part:physics = {
|
part:physics = {
|
||||||
color = "[0.6, 0.8, 0.9]";
|
color = "[0.6, 0.8, 0.9]";
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "particle_physics"; }
|
{ func = particle_physics; }
|
||||||
);
|
);
|
||||||
stage = {
|
stage = {
|
||||||
name = main;
|
name = main;
|
||||||
|
@ -1330,14 +1321,14 @@ steps = {
|
||||||
dependencies = (wait_on_fence);
|
dependencies = (wait_on_fence);
|
||||||
process = {
|
process = {
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "clear_translucent"; },
|
{ func = clear_translucent; },
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
setup_main = {
|
setup_main = {
|
||||||
process = {
|
process = {
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "update_framebuffer";
|
{ func = update_framebuffer;
|
||||||
params = ("\"main\""); },
|
params = ("\"main\""); },
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1355,8 +1346,11 @@ steps = {
|
||||||
dependencies = (wait_on_fence);
|
dependencies = (wait_on_fence);
|
||||||
process = {
|
process = {
|
||||||
tasks = (
|
tasks = (
|
||||||
{ func = "acquire_output"; },
|
{ func = acquire_output;
|
||||||
{ func = "update_input"; },
|
params = ("\"output\""); },
|
||||||
|
{ func = update_framebuffer;
|
||||||
|
params = ("\"output\""); },
|
||||||
|
{ func = update_input; },
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -624,6 +624,31 @@ parse = {
|
||||||
value = base_pipeline;
|
value = base_pipeline;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
qfv_attachmentinfo_s = {
|
||||||
|
.name = qfv_attachmentinfo_t;
|
||||||
|
.type = (QFString, QFDictionary);
|
||||||
|
.string = {
|
||||||
|
name = $name;
|
||||||
|
line = $item.line;
|
||||||
|
external = $item.string;
|
||||||
|
};
|
||||||
|
.dictionary = {
|
||||||
|
.parse = auto;
|
||||||
|
name = $name;
|
||||||
|
line = $item.line;
|
||||||
|
};
|
||||||
|
flags = auto;
|
||||||
|
format = auto;
|
||||||
|
samples = auto;
|
||||||
|
loadOp = auto;
|
||||||
|
storeOp = auto;
|
||||||
|
stencilLoadOp = auto;
|
||||||
|
stencilStoreOp = auto;
|
||||||
|
initialLayout = auto;
|
||||||
|
finalLayout = auto;
|
||||||
|
clearValue = auto;
|
||||||
|
view = auto;
|
||||||
|
};
|
||||||
qfv_framebufferinfo_s = {
|
qfv_framebufferinfo_s = {
|
||||||
.name = qfv_framebufferinfo_t;
|
.name = qfv_framebufferinfo_t;
|
||||||
width = auto;
|
width = auto;
|
||||||
|
|
|
@ -103,7 +103,7 @@ acquire_image (qfv_renderframe_t *rFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_input (qfv_renderframe_t *rFrame)
|
output_update_input (qfv_renderframe_t *rFrame)
|
||||||
{
|
{
|
||||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||||
qfv_device_t *device = ctx->device;
|
qfv_device_t *device = ctx->device;
|
||||||
|
@ -134,7 +134,7 @@ static void
|
||||||
preoutput_draw (qfv_renderframe_t *rFrame)
|
preoutput_draw (qfv_renderframe_t *rFrame)
|
||||||
{
|
{
|
||||||
acquire_image (rFrame);
|
acquire_image (rFrame);
|
||||||
update_input (rFrame);
|
output_update_input (rFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -212,7 +212,7 @@ process_input (qfv_renderframe_t *rFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
output_draw (qfv_renderframe_t *rFrame)
|
draw_output (qfv_renderframe_t *rFrame)
|
||||||
{
|
{
|
||||||
process_input (rFrame);
|
process_input (rFrame);
|
||||||
Vulkan_FlushText (rFrame);
|
Vulkan_FlushText (rFrame);
|
||||||
|
@ -224,7 +224,7 @@ 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;
|
||||||
|
|
||||||
__auto_type out = QFV_RenderPass_New (ctx, "output", output_draw);
|
__auto_type out = QFV_RenderPass_New (ctx, "output", draw_output);
|
||||||
out->output = (qfv_output_t) {
|
out->output = (qfv_output_t) {
|
||||||
.extent = ctx->swapchain->extent,
|
.extent = ctx->swapchain->extent,
|
||||||
.format = ctx->swapchain->format,
|
.format = ctx->swapchain->format,
|
||||||
|
@ -247,28 +247,97 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||||
static void
|
static void
|
||||||
acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||||
{
|
{
|
||||||
|
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||||
|
auto ctx = taskctx->ctx;
|
||||||
|
auto device = ctx->device;
|
||||||
|
auto dfunc = device->funcs;
|
||||||
|
auto frame = &ctx->frames.a[ctx->curFrame];
|
||||||
|
|
||||||
|
uint32_t imageIndex = 0;
|
||||||
|
while (!QFV_AcquireNextImage (ctx->swapchain,
|
||||||
|
frame->imageAvailableSemaphore,
|
||||||
|
0, &imageIndex)) {
|
||||||
|
QFV_DeviceWaitIdle (device);
|
||||||
|
if (ctx->capture) {
|
||||||
|
QFV_DestroyCapture (ctx->capture);
|
||||||
|
}
|
||||||
|
Vulkan_CreateSwapchain (ctx);
|
||||||
|
Vulkan_CreateCapture (ctx);
|
||||||
|
|
||||||
|
__auto_type out = ctx->output_renderpass;
|
||||||
|
out->output = (qfv_output_t) {
|
||||||
|
.extent = ctx->swapchain->extent,
|
||||||
|
.format = ctx->swapchain->format,
|
||||||
|
.frames = ctx->swapchain->numImages,
|
||||||
|
.view_list = ctx->swapchain->imageViews->a,
|
||||||
|
};
|
||||||
|
out->viewport.width = out->output.extent.width;
|
||||||
|
out->viewport.height = out->output.extent.height;
|
||||||
|
out->scissor.extent = out->output.extent;
|
||||||
|
auto step = QFV_GetStep (params[0], ctx->render_context->job);
|
||||||
|
auto render = step->render;
|
||||||
|
for (uint32_t i = 0; i < render->num_renderpasses; i++) {
|
||||||
|
auto rp = &render->renderpasses[i];
|
||||||
|
if (rp->beginInfo.framebuffer) {
|
||||||
|
dfunc->vkDestroyFramebuffer (device->dev,
|
||||||
|
rp->beginInfo.framebuffer, 0);
|
||||||
|
}
|
||||||
|
rp->beginInfo.framebuffer = 0; // leave for update_framebuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore,
|
||||||
|
0);
|
||||||
|
frame->imageAvailableSemaphore = QFV_CreateSemaphore (device);
|
||||||
|
}
|
||||||
|
ctx->swapImageIndex = imageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||||
{
|
{
|
||||||
|
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||||
|
auto ctx = taskctx->ctx;
|
||||||
|
auto device = ctx->device;
|
||||||
|
auto dfunc = device->funcs;
|
||||||
|
auto octx = ctx->output_context;
|
||||||
|
auto oframe = &octx->frames.a[ctx->curFrame];
|
||||||
|
|
||||||
|
if (oframe->input == octx->input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
oframe->input = octx->input;
|
||||||
|
|
||||||
|
VkDescriptorImageInfo imageInfo = {
|
||||||
|
octx->sampler, oframe->input,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
};
|
||||||
|
VkWriteDescriptorSet write[] = {
|
||||||
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||||
|
oframe->set, 0, 0, 1,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
&imageInfo, 0, 0 }
|
||||||
|
};
|
||||||
|
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static exprtype_t *stepref_param[] = {
|
||||||
|
&cexpr_string,
|
||||||
|
};
|
||||||
static exprfunc_t acquire_output_func[] = {
|
static exprfunc_t acquire_output_func[] = {
|
||||||
{ .func = acquire_output },
|
{ .func = acquire_output, .num_params = 1, stepref_param },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
static exprfunc_t update_input_func[] = {
|
static exprfunc_t update_input_func[] = {
|
||||||
{ .func = _update_input },
|
{ .func = update_input, .num_params = 1, stepref_param },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
static exprfunc_t output_draw_func[] = {
|
static exprfunc_t output_draw_func[] = {
|
||||||
{ .func = _output_draw },
|
{ .func = output_draw },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
static exprsym_t output_task_syms[] = {
|
static exprsym_t output_task_syms[] = {
|
||||||
|
|
Loading…
Reference in a new issue