mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
[vulkan] Make Vulkan_CreateRenderPass more generally useful
It now lives in vulkan_renderpass.c and takes most of its parameters from plist configs (just the name (which is used to find the config), output spec, and draw function from C). Even the debug colors and names are taken from the config.
This commit is contained in:
parent
e14e8050dc
commit
3603fa75cd
12 changed files with 374 additions and 229 deletions
|
@ -15,6 +15,9 @@ typedef struct qfv_subpass_s {
|
|||
const char *name;
|
||||
} qfv_subpass_t;
|
||||
|
||||
typedef struct qfv_subpassset_s
|
||||
DARRAY_TYPE (qfv_subpass_t) qfv_subpassset_t;
|
||||
|
||||
typedef struct qfv_renderframe_s {
|
||||
struct vulkan_ctx_s *vulkan_ctx;
|
||||
struct qfv_renderpass_s *renderpass;
|
||||
|
@ -30,6 +33,8 @@ typedef struct qfv_renderframeset_s
|
|||
typedef struct clearvalueset_s
|
||||
DARRAY_TYPE (VkClearValue) clearvalueset_t;
|
||||
|
||||
typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame);
|
||||
|
||||
typedef struct qfv_renderpass_s {
|
||||
vec4f_t color; // for debugging
|
||||
const char *name; // for debugging
|
||||
|
@ -44,9 +49,19 @@ typedef struct qfv_renderpass_s {
|
|||
VkViewport viewport;
|
||||
VkRect2D scissor;
|
||||
|
||||
size_t subpassCount;
|
||||
qfv_subpassset_t *subpass_info;
|
||||
qfv_renderframeset_t frames;
|
||||
|
||||
void (*draw) (qfv_renderframe_t *rFrame);
|
||||
qfv_draw_t draw;
|
||||
} qfv_renderpass_t;
|
||||
|
||||
struct qfv_output_s;
|
||||
qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx,
|
||||
const char *name,
|
||||
struct qfv_output_s *output,
|
||||
qfv_draw_t draw);
|
||||
void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx,
|
||||
qfv_renderpass_t *renderpass);
|
||||
|
||||
#endif//__QF_Vulkan_renderpass_h
|
||||
|
|
|
@ -61,7 +61,7 @@ struct vulkan_ctx_s;
|
|||
void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateRenderPasses (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_DestroyRenderPasses (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx);
|
||||
|
@ -85,4 +85,6 @@ struct entity_s;
|
|||
void Vulkan_BeginEntityLabel (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd,
|
||||
struct entity_s *ent);
|
||||
|
||||
struct plitem_s *Vulkan_GetConfig (struct vulkan_ctx_s *ctx, const char *name);
|
||||
|
||||
#endif // __QF_Vulkan_vid_h
|
||||
|
|
|
@ -98,7 +98,7 @@ typedef struct vulkan_ctx_s {
|
|||
int window_width;
|
||||
int window_height;
|
||||
|
||||
//FIXME not sure I like it being here (also, type name)
|
||||
//FIXME this is for the parser
|
||||
qfv_output_t output;
|
||||
|
||||
#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname;
|
||||
|
|
|
@ -89,7 +89,7 @@ vulkan_R_Init (void)
|
|||
Vulkan_CreateSwapchain (vulkan_ctx);
|
||||
Vulkan_CreateFrames (vulkan_ctx);
|
||||
Vulkan_CreateCapture (vulkan_ctx);
|
||||
Vulkan_CreateRenderPass (vulkan_ctx);
|
||||
Vulkan_CreateRenderPasses (vulkan_ctx);
|
||||
Vulkan_Texture_Init (vulkan_ctx);
|
||||
|
||||
Vulkan_Matrix_Init (vulkan_ctx);
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
};
|
||||
};
|
||||
framebuffer = {
|
||||
renderPass = $properties.renderpass;
|
||||
renderPass = deferred;
|
||||
attachments = (depth, color, emission, normal, position, opaque,
|
||||
translucent, $output.view);
|
||||
width = $output.extent.width;
|
||||
|
@ -125,6 +125,16 @@
|
|||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
};
|
||||
info = {
|
||||
color = "[0, 1, 0, 1]";
|
||||
subpass_info = (
|
||||
{ name = depth; color = "[ 0.5, 0.5, 0.5, 1]" },
|
||||
{ name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" },
|
||||
{ name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" },
|
||||
{ name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" },
|
||||
{ name = compose; color = "[ 0.7, 0.3, 0.3, 1]" },
|
||||
);
|
||||
};
|
||||
renderpass = {
|
||||
attachments = (
|
||||
{
|
||||
|
|
|
@ -672,7 +672,7 @@
|
|||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
renderPass = renderpass;
|
||||
renderPass = deferred;
|
||||
};
|
||||
depth_base = {
|
||||
@inherit = $properties.pipelines.base;
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
#define __x86_64__
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
|
||||
//FIXME copy of qfv_subpass_t in qf_renderpass.h
|
||||
//except it doesn't really matter because a custom spec is used
|
||||
typedef struct qfv_subpass_s {
|
||||
vec4 color;
|
||||
string name;
|
||||
} qfv_subpass_t;
|
||||
|
|
|
@ -531,7 +531,7 @@ parse_VkRenderPass (const plitem_t *item, void **data,
|
|||
|
||||
// path not guaranteed to survive cexpr_eval_string due to va
|
||||
path = resource_path (ctx, 0, name);
|
||||
QFV_AddHandle (ctx->setLayouts, path, (uint64_t) setLayout);
|
||||
QFV_AddHandle (ctx->renderpasses, path, (uint64_t) setLayout);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1516,3 +1516,65 @@ QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
|
|||
delete_memsuper (memsuper);
|
||||
return cv;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_subpassset (const plfield_t *field, const plitem_t *item, void *data,
|
||||
plitem_t *messages, void *context)
|
||||
{
|
||||
plelement_t element = {
|
||||
QFDictionary,
|
||||
sizeof (qfv_subpass_t),
|
||||
vkparse_alloc,
|
||||
parse_qfv_subpass_t,
|
||||
0,
|
||||
};
|
||||
plfield_t f = { 0, 0, 0, 0, &element };
|
||||
|
||||
if (!PL_ParseArray (&f, item, data, messages, context)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
qfv_subpassset_t *
|
||||
QFV_ParseSubpasses (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
|
||||
{
|
||||
qfv_subpassset_t *sp = 0;
|
||||
memsuper_t *memsuper = new_memsuper ();
|
||||
qfv_subpassset_t *subpasses = 0;
|
||||
|
||||
if (parse_object (ctx, memsuper, plist, parse_subpassset, &subpasses,
|
||||
properties)) {
|
||||
sp = DARRAY_ALLOCFIXED (qfv_subpassset_t, subpasses->size, malloc);
|
||||
memcpy (sp->a, subpasses->a, sp->size * sizeof (sp->a[0]));
|
||||
// the name is in memsuper which is about to be freed
|
||||
for (size_t i = 0; i < sp->size; i++) {
|
||||
sp->a[i].name = strdup (sp->a[i].name);
|
||||
}
|
||||
}
|
||||
delete_memsuper (memsuper);
|
||||
return sp;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_rgba (const plfield_t *field, const plitem_t *item, void *data,
|
||||
plitem_t *messages, void *context)
|
||||
{
|
||||
return parse_RGBA (item, &data, messages, context);
|
||||
}
|
||||
|
||||
int
|
||||
QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist,
|
||||
plitem_t *properties)
|
||||
{
|
||||
memsuper_t *memsuper = new_memsuper ();
|
||||
int ret = 0;
|
||||
vec4f_t color;
|
||||
|
||||
if (parse_object (ctx, memsuper, plist, parse_rgba, &color, properties)) {
|
||||
memcpy (rgba, &color, sizeof (color));
|
||||
ret = 1;
|
||||
}
|
||||
delete_memsuper (memsuper);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -49,5 +49,9 @@ struct clearvalueset_s *QFV_ParseClearValues (vulkan_ctx_t *ctx,
|
|||
plitem_t *plist,
|
||||
plitem_t *properties);
|
||||
|
||||
|
||||
struct qfv_subpassset_s *QFV_ParseSubpasses (vulkan_ctx_t *ctx,
|
||||
plitem_t *plist,
|
||||
plitem_t *properties);
|
||||
int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist,
|
||||
plitem_t *properties);
|
||||
#endif//__vkparse_h
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
VkPhysicalDeviceLimits,
|
||||
VkRenderPassCreateInfo,
|
||||
VkRenderPassMultiviewCreateInfo,
|
||||
|
||||
qfv_subpass_t,
|
||||
);
|
||||
parse = {
|
||||
VkSubpassDescription = {
|
||||
|
@ -377,6 +379,18 @@
|
|||
size = correlationMaskCount;
|
||||
values = pCorrelationMasks;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
qfv_subpass_s = {
|
||||
.name = qfv_subpass_t;
|
||||
color = {
|
||||
type = (custom, QFString, parse_RGBA);
|
||||
fields = (color);
|
||||
};
|
||||
name = {
|
||||
type = string;
|
||||
string = name;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,7 +29,245 @@
|
|||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/plist.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
|
||||
#include "vid_vulkan.h"
|
||||
#include "vkparse.h"
|
||||
|
||||
static plitem_t *
|
||||
get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name)
|
||||
{
|
||||
if (!rp->renderpassDef) {
|
||||
rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name);
|
||||
}
|
||||
|
||||
plitem_t *item = rp->renderpassDef;
|
||||
if (!item || !(item = PL_ObjectForKey (item, name))) {
|
||||
Sys_Printf ("error loading %s\n", name);
|
||||
} else {
|
||||
Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_image_size (VkImage image, qfv_device_t *device)
|
||||
{
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
size_t size;
|
||||
size_t align;
|
||||
|
||||
VkMemoryRequirements requirements;
|
||||
dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements);
|
||||
size = requirements.size;
|
||||
align = requirements.alignment - 1;
|
||||
size = (size + align) & ~(align);
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
||||
plitem_t *item = get_rp_item (ctx, rp, "images");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_images = images;
|
||||
size_t memSize = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
memSize += get_image_size (images->a[i], device);
|
||||
}
|
||||
VkDeviceMemory mem;
|
||||
mem = QFV_AllocImageMemory (device, images->a[0],
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
memSize, 0);
|
||||
rp->attachmentMemory = mem;
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
mem, "memory:framebuffers");
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
QFV_BindImageMemory (device, images->a[i], mem, offset);
|
||||
offset += get_image_size (images->a[i], device);
|
||||
}
|
||||
|
||||
item = get_rp_item (ctx, rp, "imageViews");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_views = views;
|
||||
|
||||
item = get_rp_item (ctx, rp, "framebuffer");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages,
|
||||
malloc);
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
ctx->output = (qfv_output_t) {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.view = ctx->swapchain->imageViews->a[i],
|
||||
.format = ctx->swapchain->format,
|
||||
};
|
||||
rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item,
|
||||
rp->renderpassDef);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp,
|
||||
qfv_renderframe_t *rFrame)
|
||||
{
|
||||
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
|
||||
rFrame->vulkan_ctx = ctx;
|
||||
rFrame->renderpass = rp;
|
||||
rFrame->subpassCount = rp->subpassCount;
|
||||
if (rp->subpass_info) {
|
||||
rFrame->subpassInfo = rp->subpass_info->a;
|
||||
}
|
||||
rFrame->subpassCmdSets = malloc (rp->subpassCount
|
||||
* sizeof (qfv_cmdbufferset_t));
|
||||
for (size_t j = 0; j < rp->subpassCount; j++) {
|
||||
DARRAY_INIT (&rFrame->subpassCmdSets[j], 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < rp->attachment_views->size; i++) {
|
||||
dfunc->vkDestroyImageView (device->dev, rp->attachment_views->a[i], 0);
|
||||
}
|
||||
for (size_t i = 0; i < rp->attachment_images->size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0);
|
||||
}
|
||||
dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0);
|
||||
|
||||
free (rp->attachment_images);
|
||||
free (rp->attachment_views);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
for (size_t i = 0; i < rp->frames.size; i++) {
|
||||
__auto_type rFrame = &rp->frames.a[i];
|
||||
for (int j = 0; j < rFrame->subpassCount; j++) {
|
||||
DARRAY_CLEAR (&rFrame->subpassCmdSets[j]);
|
||||
}
|
||||
free (rFrame->subpassCmdSets);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0);
|
||||
}
|
||||
free (rp->framebuffers);
|
||||
}
|
||||
|
||||
qfv_renderpass_t *
|
||||
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name,
|
||||
qfv_output_t *output, qfv_draw_t draw)
|
||||
{
|
||||
plitem_t *item;
|
||||
|
||||
qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t));
|
||||
|
||||
rp->name = name;
|
||||
|
||||
plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass");
|
||||
hashtab_t *tab = ctx->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 {
|
||||
ctx->output = *output;
|
||||
rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, rp->renderpassDef);
|
||||
QFV_AddHandle (tab, path, (uint64_t) rp->renderpass);
|
||||
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS,
|
||||
rp->renderpass, va (ctx->va_ctx, "renderpass:%s",
|
||||
name));
|
||||
}
|
||||
rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, "subpasses"));
|
||||
plitem_t *rp_info = get_rp_item (ctx, rp, "info");
|
||||
if (rp_info) {
|
||||
plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info");
|
||||
if (subpass_info) {
|
||||
rp->subpass_info = QFV_ParseSubpasses (ctx, subpass_info,
|
||||
rp->renderpassDef);
|
||||
if (rp->subpass_info->size > rp->subpassCount) {
|
||||
Sys_Printf ("warning:%s:%d: insufficient entries in "
|
||||
"subpass_info\n", name, PL_Line (subpass_info));
|
||||
}
|
||||
}
|
||||
|
||||
plitem_t *color = PL_ObjectForKey (rp_info, "color");
|
||||
if (color) {
|
||||
QFV_ParseRGBA (ctx, (float *)&rp->color, color, rp->renderpassDef);
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
create_attachements (ctx, rp);
|
||||
|
||||
item = get_rp_item (ctx, rp, "clearValues");
|
||||
rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef);
|
||||
|
||||
rp->draw = draw;
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
PL_Free (renderpass->renderpassDef);
|
||||
|
||||
destroy_attachments (ctx, renderpass);
|
||||
dfunc->vkDestroyRenderPass (device->dev, renderpass->renderpass, 0);
|
||||
destroy_renderframes (ctx, renderpass);
|
||||
destroy_framebuffers (ctx, renderpass);
|
||||
|
||||
DARRAY_CLEAR (&renderpass->frames);
|
||||
free (renderpass->clearValues);
|
||||
free (renderpass);
|
||||
}
|
||||
|
|
|
@ -317,8 +317,8 @@ build_configs (vulkan_ctx_t *ctx)
|
|||
cexpr_init_symtab (&builtin_configs, &ectx);
|
||||
}
|
||||
|
||||
static plitem_t *
|
||||
get_builtin_config (vulkan_ctx_t *ctx, const char *name)
|
||||
plitem_t *
|
||||
Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name)
|
||||
{
|
||||
if (!builtin_configs.tab) {
|
||||
build_configs (ctx);
|
||||
|
@ -353,7 +353,7 @@ static plitem_t *
|
|||
qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name)
|
||||
{
|
||||
if (!ctx->pipelineDef) {
|
||||
ctx->pipelineDef = get_builtin_config (ctx, "qfpipeline");
|
||||
ctx->pipelineDef = Vulkan_GetConfig (ctx, "qfpipeline");
|
||||
}
|
||||
|
||||
plitem_t *item = ctx->pipelineDef;
|
||||
|
@ -365,37 +365,6 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name)
|
|||
return item;
|
||||
}
|
||||
|
||||
static plitem_t *
|
||||
qfv_load_renderpass (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name)
|
||||
{
|
||||
if (!rp->renderpassDef) {
|
||||
rp->renderpassDef = get_builtin_config (ctx, "deferred");
|
||||
}
|
||||
|
||||
plitem_t *item = rp->renderpassDef;
|
||||
if (!item || !(item = PL_ObjectForKey (item, name))) {
|
||||
Sys_Printf ("error loading %s\n", name);
|
||||
} else {
|
||||
Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_image_size (VkImage image, qfv_device_t *device)
|
||||
{
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
size_t size;
|
||||
size_t align;
|
||||
|
||||
VkMemoryRequirements requirements;
|
||||
dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements);
|
||||
size = requirements.size;
|
||||
align = requirements.alignment - 1;
|
||||
size = (size + align) & ~(align);
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
renderpass_draw (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
|
@ -406,199 +375,24 @@ renderpass_draw (qfv_renderframe_t *rFrame)
|
|||
Vulkan_Compose_Draw (rFrame);
|
||||
}
|
||||
|
||||
static void
|
||||
create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
||||
plitem_t *item = qfv_load_renderpass (ctx, rp, "images");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_images = images;
|
||||
size_t memSize = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
memSize += get_image_size (images->a[i], device);
|
||||
}
|
||||
VkDeviceMemory mem;
|
||||
mem = QFV_AllocImageMemory (device, images->a[0],
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
memSize, 0);
|
||||
rp->attachmentMemory = mem;
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
mem, "memory:framebuffers");
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
QFV_BindImageMemory (device, images->a[i], mem, offset);
|
||||
offset += get_image_size (images->a[i], device);
|
||||
}
|
||||
|
||||
item = qfv_load_renderpass (ctx, rp, "imageViews");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_views = views;
|
||||
|
||||
item = qfv_load_renderpass (ctx, rp, "framebuffer");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages,
|
||||
malloc);
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
ctx->output = (qfv_output_t) {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.view = ctx->swapchain->imageViews->a[i],
|
||||
.format = ctx->swapchain->format,
|
||||
};
|
||||
rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item,
|
||||
rp->renderpassDef);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp,
|
||||
qfv_renderframe_t *rFrame)
|
||||
{
|
||||
// FIXME should not be hard-coded
|
||||
static qfv_subpass_t subpass_info[] = {
|
||||
{ .name = "depth", .color = { 0.5, 0.5, 0.5, 1} },
|
||||
{ .name = "translucent", .color = { 0.25, 0.25, 0.6, 1} },
|
||||
{ .name = "g-buffef", .color = { 0.3, 0.7, 0.3, 1} },
|
||||
{ .name = "lighting", .color = { 0.8, 0.8, 0.8, 1} },
|
||||
{ .name = "compose", .color = { 0.7, 0.3, 0.3, 1} },
|
||||
};
|
||||
|
||||
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
|
||||
rFrame->vulkan_ctx = ctx;
|
||||
rFrame->renderpass = rp;
|
||||
rFrame->subpassCount = QFV_NumPasses;
|
||||
rFrame->subpassInfo = subpass_info; //FIXME
|
||||
rFrame->subpassCmdSets = malloc (QFV_NumPasses
|
||||
* sizeof (qfv_cmdbufferset_t));
|
||||
for (int j = 0; j < QFV_NumPasses; j++) {
|
||||
DARRAY_INIT (&rFrame->subpassCmdSets[j], 4);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
|
||||
Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
const char *name = "renderpass";//FIXME
|
||||
plitem_t *item;
|
||||
|
||||
qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t));
|
||||
|
||||
rp->name = name;
|
||||
rp->color = (vec4f_t) { 0, 1, 0, 1 }; //FIXME
|
||||
|
||||
hashtab_t *tab = ctx->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 {
|
||||
ctx->output = (qfv_output_t) {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.view = ctx->swapchain->imageViews->a[0],
|
||||
.format = ctx->swapchain->format,
|
||||
};
|
||||
item = qfv_load_renderpass (ctx, rp, name);
|
||||
rp->renderpass = QFV_ParseRenderPass (ctx, item, 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));
|
||||
}
|
||||
|
||||
int width = ctx->window_width;
|
||||
int height = ctx->window_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]);
|
||||
}
|
||||
|
||||
create_attachements (ctx, rp);
|
||||
|
||||
item = qfv_load_renderpass (ctx, rp, "clearValues");
|
||||
rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef);
|
||||
|
||||
rp->draw = renderpass_draw;
|
||||
|
||||
qfv_output_t output = {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.view = ctx->swapchain->imageViews->a[0],
|
||||
.format = ctx->swapchain->format,
|
||||
};
|
||||
__auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred",
|
||||
&output, renderpass_draw);
|
||||
DARRAY_APPEND (&ctx->renderPasses, rp);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < rp->attachment_views->size; i++) {
|
||||
dfunc->vkDestroyImageView (device->dev, rp->attachment_views->a[i], 0);
|
||||
}
|
||||
for (size_t i = 0; i < rp->attachment_images->size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0);
|
||||
}
|
||||
dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0);
|
||||
|
||||
free (rp->attachment_images);
|
||||
free (rp->attachment_views);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
for (size_t i = 0; i < rp->frames.size; i++) {
|
||||
__auto_type rFrame = &rp->frames.a[i];
|
||||
for (int j = 0; j < rFrame->subpassCount; j++) {
|
||||
DARRAY_CLEAR (&rFrame->subpassCmdSets[j]);
|
||||
}
|
||||
free (rFrame->subpassCmdSets);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0);
|
||||
}
|
||||
free (rp->framebuffers);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < ctx->renderPasses.size; i++) {
|
||||
__auto_type rp = ctx->renderPasses.a[i];
|
||||
|
||||
PL_Free (rp->renderpassDef);
|
||||
|
||||
destroy_attachments (ctx, rp);
|
||||
dfunc->vkDestroyRenderPass (device->dev, rp->renderpass, 0);
|
||||
destroy_renderframes (ctx, rp);
|
||||
destroy_framebuffers (ctx, rp);
|
||||
|
||||
DARRAY_CLEAR (&rp->frames);
|
||||
free (rp->clearValues);
|
||||
free (rp);
|
||||
Vulkan_DestroyRenderPass (ctx, ctx->renderPasses.a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue