[vulkan] Get window resize working again

The biggest change was splitting up the job resources into
per-render-pass resources, allowing individual render passes to
reallocate their resources without affecting any others. After that, it
was just getting translucency and capture working after a window resize.
This commit is contained in:
Bill Currie 2023-07-03 20:05:27 +09:00
parent 45e09673c7
commit cd4791c5d3
11 changed files with 439 additions and 290 deletions

View file

@ -14,7 +14,7 @@ struct tex_s;
typedef void (*capfunc_t) (struct tex_s *screencap, void *data);
typedef struct qfv_capture_frame_s {
VkBuffer buffer;
struct qfv_resobj_s *buffer;
byte *data;
bool initiated;
@ -27,12 +27,10 @@ typedef struct qfv_capture_frame_set_s
typedef struct qfv_capturectx_s {
qfv_capture_frame_set_t frames;
struct qfv_device_s *device;
VkExtent2D extent;
size_t imgsize;
size_t memsize;
byte *data;
VkDeviceMemory memory;
struct qfv_resource_s *resources;
} qfv_capturectx_t;
struct vulkan_ctx_s;

View file

@ -21,9 +21,12 @@ typedef struct qfv_transtate_s {
typedef struct translucentframe_s {
VkDescriptorSet flat;
VkDescriptorSet cube;
VkImage heads;
VkImage cube_heads;
VkBuffer state;
struct qfv_resobj_s *heads;
struct qfv_resobj_s *cube_heads;
struct qfv_resobj_s *heads_view;
struct qfv_resobj_s *cube_heads_view;
struct qfv_resobj_s *state;
struct qfv_resobj_s *frags;
} translucentframe_t;
typedef struct translucentframeset_s
@ -32,6 +35,7 @@ typedef struct translucentframeset_s
typedef struct translucentctx_s {
translucentframeset_t frames;
struct qfv_resource_s *resources;
VkExtent2D extent;
int maxFragments;
} translucentctx_t;
@ -43,7 +47,5 @@ void Vulkan_Translucent_Setup (struct vulkan_ctx_s *ctx);
void Vulkan_Translucent_Shutdown (struct vulkan_ctx_s *ctx);
VkDescriptorSet Vulkan_Translucent_Descriptors (struct vulkan_ctx_s *ctx,
int frame)__attribute__((pure));
void Vulkan_Translucent_CreateBuffers (struct vulkan_ctx_s *ctx,
VkExtent2D extent);
#endif//__QF_Vulkan_qf_translucent_h

View file

@ -81,6 +81,7 @@ typedef struct qfv_imageinfo_s {
VkImageTiling tiling;
VkImageUsageFlags usage;
VkImageLayout initialLayout;
struct qfv_resobj_s *object;
} qfv_imageinfo_t;
typedef struct qfv_imageviewinfo_s {
@ -91,6 +92,7 @@ typedef struct qfv_imageviewinfo_s {
VkFormat format;
VkComponentMapping components;
VkImageSubresourceRange subresourceRange;
struct qfv_resobj_s *object;
} qfv_imageviewinfo_t;
typedef struct qfv_bufferinfo_s {
@ -355,6 +357,8 @@ typedef struct qfv_renderpass_s {
qfv_framebufferinfo_t *framebufferinfo;
VkImageView output;
qfv_reference_t outputref;
struct qfv_resource_s *resources;
} qfv_renderpass_t;
typedef struct qfv_render_s {
@ -386,9 +390,6 @@ typedef struct qfv_step_s {
typedef struct qfv_job_s {
qfv_label_t label;
struct qfv_resource_s *resources;
struct qfv_resobj_s *images;
struct qfv_resobj_s *image_views;
uint32_t num_renderpasses;
uint32_t num_pipelines;
@ -440,7 +441,9 @@ void QFV_Render_Init (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_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp);
void QFV_DestroyFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp);
void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp,
VkExtent2D extent);
struct qfv_dsmanager_s *
QFV_Render_DSManager (struct vulkan_ctx_s *ctx,

View file

@ -29,6 +29,8 @@
#endif
#include "QF/cexpr.h"
#include "QF/va.h"
#include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/capture.h"
#include "QF/Vulkan/command.h"
@ -36,6 +38,7 @@
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/instance.h"
#include "QF/Vulkan/render.h"
#include "QF/Vulkan/resource.h"
#include "QF/Vulkan/swapchain.h"
#include "QF/plugin/vid_render.h"
@ -66,13 +69,14 @@ capture_initiate (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
auto sc = ctx->swapchain;
auto scImage = sc->images->a[ctx->swapImageIndex];
auto buffer = frame->buffer->buffer.buffer;
VkBufferMemoryBarrier start_buffer_barriers[] = {
{
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.buffer = frame->buffer,
.buffer = buffer,
.offset = 0,
.size = VK_WHOLE_SIZE,
},
@ -93,7 +97,7 @@ capture_initiate (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.buffer = frame->buffer,
.buffer = buffer,
.offset = 0,
.size = VK_WHOLE_SIZE,
},
@ -127,7 +131,7 @@ capture_initiate (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
};
dfunc->vkCmdCopyImageToBuffer (cmd, scImage,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
frame->buffer, 1, &copy);
buffer, 1, &copy);
dfunc->vkCmdPipelineBarrier (cmd,
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -172,7 +176,7 @@ capture_finalize (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
VkMappedMemoryRange range = {
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.memory = cap->memory,
.memory = cap->resources->memory,
.offset = frame->data - cap->data,
.size = cap->imgsize,
};
@ -233,7 +237,6 @@ QFV_Capture_Init (vulkan_ctx_t *ctx)
auto device = ctx->device;
auto ifunc = device->physDev->instance->funcs;
auto dfunc = device->funcs;
ctx->capture_context = calloc (1, sizeof (qfv_capturectx_t));
auto cap = ctx->capture_context;
@ -248,7 +251,6 @@ QFV_Capture_Init (vulkan_ctx_t *ctx)
return;
}
cap->device = device;
cap->extent = swapchain->extent;
auto rctx = ctx->render_context;
@ -257,44 +259,62 @@ QFV_Capture_Init (vulkan_ctx_t *ctx)
DARRAY_RESIZE (&cap->frames, frames);
cap->frames.grow = 0;
//FIXME assumes the swapchain is 32bpp
cap->imgsize = swapchain->extent.width * swapchain->extent.height * 4;
cap->resources = calloc (1, sizeof (qfv_resource_t)
+ sizeof (qfv_resobj_t[frames]));
auto buffers = (qfv_resobj_t *) &cap->resources[1];
cap->resources[0] = (qfv_resource_t) {
.name = "capture",
.va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
.num_objects = frames,
.objects = buffers,
};
for (size_t i = 0; i < frames; i++) {
buffers[i] = (qfv_resobj_t) {
.name = va (ctx->va_ctx, "capture:%zd", i),
.type = qfv_res_buffer,
.buffer = {
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
},
};
auto frame = &cap->frames.a[i];
*frame = (qfv_capture_frame_t) {
.buffer = QFV_CreateBuffer (device, cap->imgsize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
.buffer = &buffers[i],
};
}
VkMemoryRequirements req;
dfunc->vkGetBufferMemoryRequirements (device->dev,
cap->frames.a[0].buffer,
&req);
cap->imgsize = QFV_NextOffset (cap->imgsize, &req);
cap->memsize = frames * cap->imgsize;
cap->memory = QFV_AllocBufferMemory (device,
cap->frames.a[0].buffer,
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
cap->memsize, 0);
dfunc->vkMapMemory (device->dev, cap->memory, 0, cap->memsize, 0,
(void **) &cap->data);
for (size_t i = 0; i < frames; i++) {
auto frame = &cap->frames.a[i];
frame->data = cap->data + i * cap->imgsize;
QFV_BindBufferMemory (device, frame->buffer, cap->memory,
i * cap->imgsize);
}
qfvPopDebug (ctx);
}
int shut_up_gcc = 1;
void
QFV_Capture_Renew (vulkan_ctx_t *ctx)
{
if (shut_up_gcc) {
Sys_Error ("QFV_Capture_Renew not implemented");
auto device = ctx->device;
auto dfunc = device->funcs;
auto swapchain = ctx->swapchain;
auto cap = ctx->capture_context;
if (!cap->resources) {
return;
}
if (cap->resources->memory) {
dfunc->vkUnmapMemory (device->dev, cap->resources->memory);
QFV_DestroyResource (device, cap->resources);
}
cap->extent = swapchain->extent;
//FIXME assumes the swapchain is 32bpp
cap->imgsize = swapchain->extent.width * swapchain->extent.height * 4;
for (uint32_t i = 0; i < cap->resources->num_objects; i++) {
auto obj = &cap->resources->objects[i];
obj->buffer.size = cap->imgsize;
}
QFV_CreateResource (device, cap->resources);
dfunc->vkMapMemory (device->dev, cap->resources->memory, 0,
cap->resources->size, 0, (void **) &cap->data);
for (size_t i = 0; i < cap->frames.size; i++) {
auto frame = &cap->frames.a[i];
frame->data = cap->data + i * cap->imgsize;
}
}
@ -305,12 +325,11 @@ QFV_Capture_Shutdown (vulkan_ctx_t *ctx)
auto dfunc = device->funcs;
auto cap = ctx->capture_context;
for (size_t i = 0; i < cap->frames.size; i++) {
auto frame = &cap->frames.a[i];
dfunc->vkDestroyBuffer (device->dev, frame->buffer, 0);
if (cap->resources->memory) {
dfunc->vkUnmapMemory (device->dev, cap->resources->memory);
QFV_DestroyResource (device, cap->resources);
}
dfunc->vkUnmapMemory (device->dev, cap->memory);
dfunc->vkFreeMemory (device->dev, cap->memory, 0);
free (cap->resources);
DARRAY_CLEAR (&cap->frames);
free (cap);
}
@ -319,11 +338,14 @@ void
QFV_Capture_Screen (vulkan_ctx_t *ctx, capfunc_t callback, void *data)
{
auto cap = ctx->capture_context;
if (!cap->data) {
if (!cap->resources) {
Sys_Printf ("Capture not supported\n");
callback (0, data);
return;
}
if (!cap->resources->memory) {
QFV_Capture_Renew (ctx);
}
auto frame = &cap->frames.a[ctx->curFrame];
frame->callback = callback;
frame->callback_data = data;

View file

@ -265,11 +265,11 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx)
}
}
static VkImageView __attribute__((pure))
find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx)
static qfv_imageviewinfo_t * __attribute__((pure))
find_imageview (qfv_reference_t *ref, qfv_renderpass_t *rp,
qfv_renderctx_t *rctx)
{
__auto_type jinfo = rctx->jobinfo;
__auto_type job = rctx->job;
auto jinfo = rctx->jobinfo;
const char *name = ref->name;
if (strncmp (name, "$imageviews.", 7) == 0) {
@ -277,19 +277,45 @@ find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx)
}
for (uint32_t i = 0; i < jinfo->num_imageviews; i++) {
__auto_type vi = &jinfo->imageviews[i];
__auto_type vo = &job->image_views[i];
if (strcmp (name, vi->name) == 0) {
return vo->image_view.view;
auto viewinfo = &jinfo->imageviews[i];
if (strcmp (name, viewinfo->name) == 0) {
return viewinfo;
}
}
Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name);
}
void
QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
QFV_DestroyFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
{
__auto_type rctx = ctx->render_context;
if (rp->beginInfo.framebuffer) {
auto device = ctx->device;
auto dfunc = device->funcs;
auto bi = &rp->beginInfo;
dfunc->vkDestroyFramebuffer (device->dev, bi->framebuffer, 0);
bi->framebuffer = 0;
}
if (rp->resources && rp->resources->memory) {
QFV_DestroyResource (ctx->device, rp->resources);
}
}
void
QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp,
VkExtent2D extent)
{
auto rctx = ctx->render_context;
if (rp->resources && !rp->resources->memory) {
for (uint32_t i = 0; i < rp->resources->num_objects; i++) {
auto obj = &rp->resources->objects[i];
if (obj->type == qfv_res_image) {
obj->image.extent.width = extent.width;
obj->image.extent.height = extent.height;
}
}
QFV_CreateResource (ctx->device, rp->resources);
}
auto fb = rp->framebufferinfo;
auto attachments = rp->framebuffer.views;
@ -298,8 +324,8 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
.attachmentCount = fb->num_attachments,
.pAttachments = attachments,
.renderPass = rp->beginInfo.renderPass,
.width = fb->width,
.height = fb->height,
.width = extent.width,
.height = extent.height,
.layers = fb->layers,
};
for (uint32_t i = 0; i < fb->num_attachments; i++) {
@ -312,9 +338,11 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
cInfo.height = sc->extent.height;
}
} else {
attachments[i] = find_imageview (&fb->attachments[i].view, rctx);
auto viewinfo = find_imageview (&fb->attachments[i].view, rp, rctx);
attachments[i] = viewinfo->object->image_view.view;
if (rp->outputref.name) {
rp->output = find_imageview (&rp->outputref, rctx);
viewinfo = find_imageview (&rp->outputref, rp, rctx);
rp->output = viewinfo->object->image_view.view;
}
}
}
@ -352,8 +380,8 @@ wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
}
static void
renderpass_update_viewper_sissor (qfv_renderpass_t *rp,
const qfv_output_t *output)
renderpass_update_viewport_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++) {
@ -375,7 +403,7 @@ 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);
renderpass_update_viewport_sissor (&render->renderpasses[i], output);
}
}
@ -394,12 +422,13 @@ update_framebuffer (const exprval_t **params, exprval_t *result,
Vulkan_ConfigOutput (ctx, &output);
if (output.extent.width != render->output.extent.width
|| output.extent.height != render->output.extent.height) {
//FIXME framebuffer image creation here
QFV_DestroyFramebuffer (ctx, rp);
update_viewport_scissor (render, &output);
render->output.extent = output.extent;
}
if (!rp->beginInfo.framebuffer) {
QFV_CreateFramebuffer (ctx, rp);
QFV_CreateFramebuffer (ctx, rp, render->output.extent);
}
}
@ -469,15 +498,16 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx)
for (uint32_t i = 0; i < job->num_layouts; i++) {
dfunc->vkDestroyPipelineLayout (device->dev, job->layouts[i], 0);
}
if (job->resources) {
QFV_DestroyResource (ctx->device, job->resources);
free (job->resources);
}
for (uint32_t i = 0; i < job->num_steps; i++) {
if (job->steps[i].render) {
auto render = job->steps[i].render;
for (uint32_t j = 0; j < render->num_renderpasses; j++) {
auto bi = &render->renderpasses[j].beginInfo;
auto rp = &render->renderpasses[j];
if (rp->resources && rp->resources->memory) {
QFV_DestroyResource (ctx->device, rp->resources);
}
free (rp->resources);
auto bi = &rp->beginInfo;
if (bi->framebuffer) {
dfunc->vkDestroyFramebuffer (device->dev,
bi->framebuffer, 0);

View file

@ -220,31 +220,86 @@ count_stuff (qfv_jobinfo_t *jobinfo, objcount_t *counts)
}
}
static qfv_imageinfo_t * __attribute__((pure))
find_imageinfo (qfv_jobinfo_t *jobinfo, const qfv_reference_t *ref)
{
if (strcmp (ref->name, "$output.image") == 0) {
//auto image = jinfo->output.image;
//job->image_views[i].image_view.external_image = image;
//job->image_views[i].image_view.image = -1;
} else {
for (uint32_t i = 0; i <= jobinfo->num_images; i++) {
auto img = &jobinfo->images[i];
if (strcmp (ref->name, img->name) == 0) {
return img;
}
}
}
Sys_Printf ("%d: unknown image reference: %s\n", ref->line, ref->name);
return 0;
}
static qfv_imageviewinfo_t * __attribute__((pure))
find_imageviewinfo (qfv_jobinfo_t *jobinfo, const qfv_reference_t *ref)
{
for (uint32_t i = 0; i <= jobinfo->num_imageviews; i++) {
auto imgview = &jobinfo->imageviews[i];
if (strcmp (ref->name, imgview->name) == 0) {
return imgview;
}
}
Sys_Printf ("%d: unknown image view reference: %s\n", ref->line, ref->name);
return 0;
}
static void
create_resources (vulkan_ctx_t *ctx, objcount_t *counts)
create_resources (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
{
auto rctx = ctx->render_context;
auto jinfo = rctx->jobinfo;
auto job = rctx->job;
auto fbi = rp->framebufferinfo;
uint32_t num_attachments = 0;
for (uint32_t i = 0; i < fbi->num_attachments; i++) {
auto attach = &fbi->attachments[i];
if (!attach->external) {
num_attachments++;
}
}
if (!num_attachments) {
rp->resources = 0;
return;
}
size_t size = sizeof (qfv_resource_t);
size += sizeof (qfv_resobj_t [counts->num_images]);
size += sizeof (qfv_resobj_t [counts->num_imageviews]);
size += sizeof (qfv_resobj_t [num_attachments]);
size += sizeof (qfv_resobj_t [num_attachments]);
job->resources = malloc (size);
job->images = (qfv_resobj_t *) &job->resources[1];
job->image_views = &job->images[counts->num_images];
rp->resources = calloc (1, size);
auto images = (qfv_resobj_t *) &rp->resources[1];
auto image_views = &images[num_attachments];
job->resources[0] = (qfv_resource_t) {
.name = "render",
rp->resources[0] = (qfv_resource_t) {
.name = rp->label.name,
.va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.num_objects = counts->num_images + counts->num_imageviews,
.objects = job->images,
.num_objects = 2 * num_attachments,
.objects = images,
};
for (uint32_t i = 0; i < counts->num_images; i++) {
__auto_type img = &jinfo->images[i];
job->images[i] = (qfv_resobj_t) {
int error = 0;
for (uint32_t i = 0; i < num_attachments; i++) {
auto attach = &fbi->attachments[i];
auto imgview = find_imageviewinfo (jinfo, &attach->view);
if (!imgview) {
error = 1;
continue;
}
auto img = find_imageinfo (jinfo, &imgview->image);
if (!img) {
error = 1;
continue;
}
images[i] = (qfv_resobj_t) {
.name = img->name,
.type = qfv_res_image,
.image = {
@ -260,52 +315,30 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts)
.initialLayout = img->initialLayout,
},
};
}
int error = 0;
for (uint32_t i = 0; i < counts->num_imageviews; i++) {
__auto_type view = &jinfo->imageviews[i];
job->image_views[i] = (qfv_resobj_t) {
.name = view->name,
img->object = &images[i];
image_views[i] = (qfv_resobj_t) {
.name = imgview->name,
.type = qfv_res_image_view,
.image_view = {
.flags = view->flags,
.type = view->viewType,
.format = view->format,
.components = view->components,
.subresourceRange = view->subresourceRange,
.image = img->object - rp->resources->objects,
.flags = imgview->flags,
.type = imgview->viewType,
.format = imgview->format,
.components = imgview->components,
.subresourceRange = imgview->subresourceRange,
},
};
if (strcmp (view->image.name, "$output.image") == 0) {
//__auto_type image = jinfo->output.image;
//job->image_views[i].image_view.external_image = image;
//job->image_views[i].image_view.image = -1;
} else {
qfv_resobj_t *img = 0;
for (uint32_t j = 0; j < jinfo->num_images; j++) {
if (strcmp (view->image.name, jinfo->images[j].name) == 0) {
img = &job->images[j];
}
}
if (img) {
uint32_t ind = img - job->resources->objects;
job->image_views[i].image_view.image = ind;
// fall back to the image's format if not overriden
if (!job->image_views[i].image_view.format) {
job->image_views[i].image_view.format = img->image.format;
}
} else {
Sys_Printf ("%d: unknown image reference: %s\n",
view->image.line, view->image.name);
error = 1;
}
if (!image_views[i].image_view.format) {
image_views[i].image_view.format = img->object->image.format;
}
imgview->object = &image_views[i];
}
if (error) {
free (job->resources);
job->resources = 0;
free (rp->resources);
rp->resources = 0;
return;
}
QFV_CreateResource (ctx->device, job->resources);
}
typedef struct {
@ -831,6 +864,7 @@ init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo,
.framebufferinfo = &rpinfo->framebuffer,
.outputref = rpinfo->output,
};
create_resources (s->ctx, rp);
s->inds.num_attachments += rpinfo->framebuffer.num_attachments;
for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) {
init_subpass (&rp->subpasses[i], &rpinfo->subpasses[i], jp, s);
@ -1178,5 +1212,4 @@ QFV_BuildRender (vulkan_ctx_t *ctx)
count_stuff (rctx->jobinfo, &counts);
create_objects (ctx, &counts);
create_resources (ctx, &counts);
}

View file

@ -291,12 +291,14 @@ QFV_DestroyResource (qfv_device_t *device, qfv_resource_t *resource)
{
__auto_type buffview = &obj->buffer_view;
dfunc->vkDestroyBufferView (device->dev, buffview->view, 0);
buffview->view = 0;
}
break;
case qfv_res_image_view:
{
__auto_type imgview = &obj->image_view;
dfunc->vkDestroyImageView (device->dev, imgview->view, 0);
imgview->view = 0;
}
break;
}
@ -308,12 +310,14 @@ QFV_DestroyResource (qfv_device_t *device, qfv_resource_t *resource)
{
__auto_type buffer = &obj->buffer;
dfunc->vkDestroyBuffer (device->dev, buffer->buffer, 0);
buffer->buffer = 0;
}
break;
case qfv_res_image:
{
__auto_type image = &obj->image;
dfunc->vkDestroyImage (device->dev, image->image, 0);
image->image = 0;
}
break;
case qfv_res_buffer_view:
@ -322,6 +326,7 @@ QFV_DestroyResource (qfv_device_t *device, qfv_resource_t *resource)
}
}
dfunc->vkFreeMemory (device->dev, resource->memory, 0);
resource->memory = 0;
}
void

View file

@ -1744,14 +1744,6 @@ steps = {
);
};
};
translucent = {
dependencies = (wait_on_fence);
process = {
tasks = (
{ func = clear_translucent; },
);
};
};
setup_main = {
dependencies = (wait_on_fence);
process = {
@ -1760,12 +1752,14 @@ steps = {
params = ("\"main\""); },
{ func = update_framebuffer;
params = ("\"main\""); },
{ func = clear_translucent;
params = ("\"main\""); },
{ func = particle_wait_physics; },
);
};
};
main = {
dependencies = (setup_main, particles, shadow, world, translucent);
dependencies = (setup_main, particles, shadow, world);
render = {
renderpasses = {
deferred = $renderpasses.deferred;

View file

@ -486,6 +486,28 @@ parse = {
values = bindings;
};
};
qfv_imageinfo_s = {
.name = qfv_imageinfo_t;
flags = auto;
imageType = auto;
format = auto;
extent = auto;
mipLevels = auto;
arrayLayers = auto;
samples = auto;
tiling = auto;
usage = auto;
initialLayout = auto;
};
qfv_imageviewinfo_s = {
.name = qfv_imageviewinfo_t;
flags = auto;
image = auto;
viewType = auto;
format = auto;
components = auto;
subresourceRange = auto;
};
qfv_bufferviewinfo_s = {
.name = qfv_bufferviewinfo_t;
buffer = auto;

View file

@ -106,7 +106,7 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
rp->beginInfo.framebuffer = 0;
//FIXME come up with a better mechanism
ctx->swapImageIndex = i;
QFV_CreateFramebuffer (ctx, rp);
QFV_CreateFramebuffer (ctx, rp, sc->extent);
octx->framebuffers[i] = rp->beginInfo.framebuffer;
QFV_duSetObjectName (device, VK_OBJECT_TYPE_FRAMEBUFFER,
octx->framebuffers[i],

View file

@ -61,20 +61,92 @@
#include "r_internal.h"
#include "vid_vulkan.h"
static const char * __attribute__((used)) translucent_pass_names[] = {
"clear",
"blend",
};
static void
trans_create_buffers (vulkan_ctx_t *ctx)
{
auto device = ctx->device;
auto dfunc = device->funcs;
auto tctx = ctx->translucent_context;
size_t frames = tctx->frames.size;
if (tctx->resources->memory) {
QFV_DestroyResource (device, tctx->resources);
}
for (uint32_t i = 0; i < tctx->resources->num_objects; i++) {
auto obj = &tctx->resources->objects[i];
if (obj->type == qfv_res_image) {
auto img = &obj->image;
if (img->num_layers == 6) {
auto e = min (tctx->extent.width, tctx->extent.height);
img->extent.width = e;
img->extent.height = e;
} else {
img->extent.width = tctx->extent.width;
img->extent.height = tctx->extent.height;
}
}
}
QFV_CreateResource (device, tctx->resources);
for (size_t i = 0; i < frames; i++) {
auto tframe = &tctx->frames.a[i];
auto heads_view = tframe->heads_view->image_view.view;
auto cube_heads_view = tframe->cube_heads_view->image_view.view;
auto state = tframe->state->buffer.buffer;
auto frags = tframe->frags->buffer.buffer;
VkDescriptorImageInfo flat_imageInfo[] = {
{ 0, heads_view, VK_IMAGE_LAYOUT_GENERAL },
};
VkDescriptorImageInfo cube_imageInfo[] = {
{ 0, cube_heads_view, VK_IMAGE_LAYOUT_GENERAL },
};
VkDescriptorBufferInfo bufferInfo[] = {
{ state, 0, VK_WHOLE_SIZE },
{ frags, 0, VK_WHOLE_SIZE },
};
VkWriteDescriptorSet write[] = {
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->flat, 2, 0, 1,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = flat_imageInfo },
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->flat, 0, 0, 2,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = bufferInfo },
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->cube, 2, 0, 1,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = cube_imageInfo },
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->cube, 0, 0, 2,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = bufferInfo },
};
dfunc->vkUpdateDescriptorSets (device->dev, 4, write, 0, 0);
}
}
static void
clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
{
__auto_type taskctx = (qfv_taskctx_t *) ectx;
vulkan_ctx_t *ctx = taskctx->ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
translucentctx_t *tctx = ctx->translucent_context;
__auto_type tframe = &tctx->frames.a[ctx->curFrame];
auto taskctx = (qfv_taskctx_t *) ectx;
auto ctx = taskctx->ctx;
auto device = ctx->device;
auto dfunc = device->funcs;
auto tctx = ctx->translucent_context;
auto tframe = &tctx->frames.a[ctx->curFrame];
auto job = ctx->render_context->job;
auto step = QFV_GetStep (params[0], job);
auto render = step->render;
if (tctx->extent.width != render->output.extent.width
|| tctx->extent.height != render->output.extent.height) {
tctx->extent = render->output.extent;
trans_create_buffers (ctx);
}
VkCommandBuffer cmd = QFV_GetCmdBuffer (ctx, false);
@ -84,7 +156,8 @@ clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
};
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
auto image = scr_fisheye ? tframe->cube_heads : tframe->heads;
auto img = scr_fisheye ? tframe->cube_heads : tframe->heads;
auto image = img->image.image;
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
ib.barrier.image = image;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
@ -113,13 +186,16 @@ clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
qfv_transtate_t *state = QFV_PacketExtend (packet, 2 * sizeof (*state));
*state = (qfv_transtate_t) { 0, tctx->maxFragments };
__auto_type bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW];
QFV_PacketCopyBuffer (packet, tframe->state, 0, bb);
auto bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW];
QFV_PacketCopyBuffer (packet, tframe->state->buffer.buffer, 0, bb);
QFV_PacketSubmit (packet);
}
static exprtype_t *clear_translucent_params[] = {
&cexpr_string,
};
static exprfunc_t clear_translucent_func[] = {
{ .func = clear_translucent },
{ .func = clear_translucent, .num_params = 1, clear_translucent_params },
{}
};
static exprsym_t translucent_task_syms[] = {
@ -136,6 +212,100 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx)
ctx->translucent_context = tctx;
}
static void
trans_create_resources (vulkan_ctx_t *ctx)
{
auto tctx = ctx->translucent_context;
size_t frames = tctx->frames.size;
tctx->resources = calloc (1, sizeof (qfv_resource_t)
// heads images (flat + cube)
+ sizeof (qfv_resobj_t[frames]) * 2
// heads image views (flat + cube)
+ sizeof (qfv_resobj_t[frames]) * 2
// fragment buffer
+ sizeof (qfv_resobj_t[frames])
// fragment count
+ sizeof (qfv_resobj_t[frames]));
auto heads_objs = (qfv_resobj_t *) &tctx->resources[1];
auto cube_heads_objs = &heads_objs[frames];
auto head_views_objs = &cube_heads_objs[frames];
auto cube_head_views_objs = &head_views_objs[frames];
auto buffer_objs = &cube_head_views_objs[frames];
auto count_objs = &buffer_objs[frames];
tctx->resources[0] = (qfv_resource_t) {
.name = "oit",
.va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.num_objects = 6 * frames,
.objects = heads_objs,
};
for (size_t i = 0; i < frames; i++) {
heads_objs[i] = (qfv_resobj_t) {
.name = nva ("heads:%zd", i),
.type = qfv_res_image,
.image = {
.type = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_R32_SINT,
.extent = { 0, 0, 1 },
.num_mipmaps = 1,
.num_layers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.usage = VK_IMAGE_USAGE_STORAGE_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT,
},
};
cube_heads_objs[i] = heads_objs[i];
cube_heads_objs[i].name = nva ("cube_heads:%zd", i);
cube_heads_objs[i].image.extent = (VkExtent3D) { 0, 0, 1 };
cube_heads_objs[i].image.num_layers = 6;
head_views_objs[i] = (qfv_resobj_t) {
.name = strdup (heads_objs[i].name),
.type = qfv_res_image_view,
.image_view = {
.image = i,
.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
.format = VK_FORMAT_R32_SINT,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = VK_REMAINING_MIP_LEVELS,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
},
};
cube_head_views_objs[i] = head_views_objs[i];
cube_head_views_objs[i].name = strdup (cube_heads_objs[i].name);
cube_head_views_objs[i].image_view.image = i + frames;
buffer_objs[i] = (qfv_resobj_t) {
.name = nva ("frags:%zd", i),
.type = qfv_res_buffer,
.buffer = {
.size = sizeof (qfv_transfrag_t) * tctx->maxFragments,
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
},
};
count_objs[i] = (qfv_resobj_t) {
.name = nva ("count:%zd", i),
.type = qfv_res_buffer,
.buffer = {
.size = 2 * sizeof (qfv_transtate_t),
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
},
};
}
for (size_t i = 0; i < frames; i++) {
auto tframe = &tctx->frames.a[i];
tframe->heads = &heads_objs[i];
tframe->cube_heads = &cube_heads_objs[i];
tframe->heads_view = &head_views_objs[i];
tframe->cube_heads_view = &cube_head_views_objs[i];
tframe->state = &count_objs[i];
tframe->frags = &buffer_objs[i];
}
}
void
Vulkan_Translucent_Setup (vulkan_ctx_t *ctx)
{
@ -158,7 +328,7 @@ Vulkan_Translucent_Setup (vulkan_ctx_t *ctx)
.cube = QFV_DSManager_AllocSet (dsmanager),
};
}
Vulkan_Translucent_CreateBuffers (ctx, ctx->swapchain->extent);//FIXME
trans_create_resources (ctx);
qfvPopDebug (ctx);
}
@ -169,11 +339,15 @@ Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx)
translucentctx_t *tctx = ctx->translucent_context;
if (tctx->resources) {
QFV_DestroyResource (device, tctx->resources);
free (tctx->resources);
tctx->resources = 0;
if (tctx->resources->memory) {
QFV_DestroyResource (device, tctx->resources);
}
for (uint32_t i = 0; i < tctx->resources->num_objects; i++) {
auto obj = &tctx->resources->objects[i];
free ((char *) obj->name);
}
}
free (tctx->resources);
free (tctx->frames.a);
free (tctx);
}
@ -185,137 +359,3 @@ Vulkan_Translucent_Descriptors (vulkan_ctx_t *ctx, int frame)
auto tframe = &tctx->frames.a[frame];
return scr_fisheye ? tframe->cube : tframe->flat;
}
void
Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent)
{
if (!ctx->translucent_context) {//FIXME
Vulkan_Translucent_Init (ctx);
}
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
__auto_type tctx = ctx->translucent_context;
size_t frames = tctx->frames.size;
if (tctx->resources) {
QFV_DestroyResource (device, tctx->resources);
free (tctx->resources);
tctx->resources = 0;
}
tctx->resources = malloc (sizeof (qfv_resource_t)
// heads images (flat + cube)
+ sizeof (qfv_resobj_t[frames]) * 2
// heads image views (flat + cube)
+ sizeof (qfv_resobj_t[frames]) * 2
// fragment buffer
+ sizeof (qfv_resobj_t[frames])
// fragment count
+ sizeof (qfv_resobj_t[frames]));
auto heads_objs = (qfv_resobj_t *) &tctx->resources[1];
auto cube_heads_objs = &heads_objs[frames];
auto head_views_objs = &cube_heads_objs[frames];
auto cube_head_views_objs = &head_views_objs[frames];
auto buffer_objs = &cube_head_views_objs[frames];
auto count_objs = &buffer_objs[frames];
tctx->resources[0] = (qfv_resource_t) {
.name = "oit",
.va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.num_objects = 6 * frames,
.objects = heads_objs,
};
for (size_t i = 0; i < frames; i++) {
heads_objs[i] = (qfv_resobj_t) {
.name = va (ctx->va_ctx, "heads:%zd", i),
.type = qfv_res_image,
.image = {
.type = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_R32_SINT,
.extent = { extent.width, extent.height, 1 },
.num_mipmaps = 1,
.num_layers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.usage = VK_IMAGE_USAGE_STORAGE_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT,
},
};
auto e = min (extent.width, extent.height);
cube_heads_objs[i] = heads_objs[i];
cube_heads_objs[i].name = va (ctx->va_ctx, "cube_heads:%zd", i);
cube_heads_objs[i].image.extent = (VkExtent3D) { e, e, 1 };
cube_heads_objs[i].image.num_layers = 6;
head_views_objs[i] = (qfv_resobj_t) {
.name = heads_objs[i].name,
.type = qfv_res_image_view,
.image_view = {
.image = i,
.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
.format = VK_FORMAT_R32_SINT,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = VK_REMAINING_MIP_LEVELS,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
},
};
cube_head_views_objs[i] = head_views_objs[i];
cube_head_views_objs[i].name = cube_heads_objs[i].name;
cube_head_views_objs[i].image_view.image = i + frames;
buffer_objs[i] = (qfv_resobj_t) {
.name = va (ctx->va_ctx, "frags:%zd", i),
.type = qfv_res_buffer,
.buffer = {
.size = sizeof (qfv_transfrag_t) * tctx->maxFragments,
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
},
};
count_objs[i] = (qfv_resobj_t) {
.name = va (ctx->va_ctx, "count:%zd", i),
.type = qfv_res_buffer,
.buffer = {
.size = 2 * sizeof (qfv_transtate_t),
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
},
};
}
QFV_CreateResource (device, tctx->resources);
for (size_t i = 0; i < frames; i++) {
__auto_type tframe = &tctx->frames.a[i];
tframe->heads = heads_objs[i].image.image;
tframe->cube_heads = cube_heads_objs[i].image.image;
tframe->state = count_objs[i].buffer.buffer;
VkDescriptorImageInfo flat_imageInfo[] = {
{ 0, head_views_objs[i].image_view.view, VK_IMAGE_LAYOUT_GENERAL },
};
VkDescriptorImageInfo cube_imageInfo[] = {
{ 0, cube_head_views_objs[i].image_view.view,
VK_IMAGE_LAYOUT_GENERAL },
};
VkDescriptorBufferInfo bufferInfo[] = {
{ count_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE },
{ buffer_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE },
};
VkWriteDescriptorSet write[] = {
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->flat, 2, 0, 1,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = flat_imageInfo },
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->flat, 0, 0, 2,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = bufferInfo },
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->cube, 2, 0, 1,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = cube_imageInfo },
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
tframe->cube, 0, 0, 2,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.pBufferInfo = bufferInfo },
};
dfunc->vkUpdateDescriptorSets (device->dev, 4, write, 0, 0);
}
}