[vulkan] Start work on alias model rendering

This commit is contained in:
Bill Currie 2021-01-26 20:58:24 +09:00
parent 12ec6c5c29
commit 748217b438
10 changed files with 378 additions and 35 deletions

View file

@ -43,6 +43,7 @@ typedef struct aliasskin_s {
struct qfv_tex_s *colora;
struct qfv_tex_s *colorb;
} aliasskin_t;
typedef struct aliasvrt_s {
float vertex[4];
float normal[4];
@ -68,15 +69,39 @@ typedef struct qfv_light_s {
float cone;
} qfv_light_t;
#define ALIAS_LIGHTS 8
typedef struct qfv_light_buffer_s {
int light_count;
qfv_light_t lights[] __attribute__((aligned(16)));
qfv_light_t lights[ALIAS_LIGHTS] __attribute__((aligned(16)));
} qfv_light_buffer_t;
typedef struct alias_ctx_s {
} alias_ctx_t;
#define ALIAS_BUFFER_INFOS 2
#define ALIAS_IMAGE_INFOS 4
typedef struct aliasframe_s {
VkCommandBuffer cmd;
VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS];
VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS];
VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS];
qfv_light_buffer_t *lights;
VkBuffer light_buffer;
} aliasframe_t;
typedef struct aliasframeset_s
DARRAY_TYPE (aliasframe_t) aliasframeset_t;
typedef struct aliasctx_s {
aliasframeset_t frames;
VkPipeline pipeline;
VkPipelineLayout layout;
VkSampler sampler;
VkDeviceMemory light_memory;
} aliasctx_t;
struct vulkan_ctx_s;
struct entity_s;
void *Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum,
qboolean group, maliasskindesc_t *skindesc,
struct vulkan_ctx_s *ctx);
@ -87,4 +112,11 @@ void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr,
void *_m, int _s, int extra,
struct vulkan_ctx_s *ctx);
void Vulkan_AliasBegin (struct vulkan_ctx_s *ctx);
void Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx);
void Vulkan_AliasEnd (struct vulkan_ctx_s *ctx);
void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_alias_h

View file

@ -63,6 +63,7 @@ typedef struct vulkan_ctx_s {
struct hashtab_s *descriptorPools;
struct hashtab_s *samplers;
struct aliasctx_s *alias_context;
struct bspctx_s *bsp_context;
struct drawctx_s *draw_context;

View file

@ -236,6 +236,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \
libs/video/renderer/vulkan/util.c \
libs/video/renderer/vulkan/util.h \
libs/video/renderer/vulkan/vkparse.c \
libs/video/renderer/vulkan/vulkan_alias.c \
libs/video/renderer/vulkan/vulkan_bsp.c \
libs/video/renderer/vulkan/vulkan_draw.c \
libs/video/renderer/vulkan/vulkan_lightmap.c \

View file

@ -98,6 +98,7 @@ vulkan_R_Init (void)
// are being built
vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline");
Vulkan_Texture_Init (vulkan_ctx);
Vulkan_Alias_Init (vulkan_ctx);
Vulkan_Bsp_Init (vulkan_ctx);
Vulkan_Draw_Init (vulkan_ctx);
Vulkan_Particles_Init (vulkan_ctx);
@ -611,6 +612,7 @@ vulkan_vid_render_shutdown (void)
df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0);
Vulkan_Draw_Shutdown (vulkan_ctx);
Vulkan_Bsp_Shutdown (vulkan_ctx);
Vulkan_Alias_Shutdown (vulkan_ctx);
Mod_ClearAll ();
Vulkan_Texture_Shutdown (vulkan_ctx);
Vulkan_Shutdown_Common (vulkan_ctx);

View file

@ -1,9 +1,9 @@
#version 450
layout (set = 0, binding = 1) uniform sampler2D Texture;
layout (set = 0, binding = 2) uniform sampler2D GlowMap;
layout (set = 0, binding = 3) uniform sampler2D ColorA;
layout (set = 0, binding = 4) uniform sampler2D ColorB;
layout (set = 2, binding = 0) uniform sampler2D Texture;
layout (set = 2, binding = 1) uniform sampler2D GlowMap;
layout (set = 2, binding = 2) uniform sampler2D ColorA;
layout (set = 2, binding = 3) uniform sampler2D ColorB;
struct LightData {
vec3 color;

View file

@ -49,9 +49,26 @@
borderColor = float_transparent_black;
unnormalizedCoordinates = false;
};
alias.sampler = {
magFilter = linear;
minFilter = linear;
mipmapMode = linear;
addressModeU = clamp_to_edge;
addressModeV = clamp_to_edge;
addressModeW = clamp_to_edge;
mipLodBias = 0;
anisotropyEnable = false;
maxAnisotropy = 0;
compareEnable = false;
compareOp = always;
minLod = 0;
maxLod = 1000;
borderColor = float_transparent_black;
unnormalizedCoordinates = false;
};
};
descriptorPools = {
twod = {
twod.pool = {
flags = 0;
maxSets = $framebuffers.size;
bindings = (
@ -65,9 +82,19 @@
},
);
};
alias.pool = {
flags = 0;
maxSets = "2z * $framebuffers.size";
bindings = (
{
type = uniform_buffer;
descriptorCount = "2z * $framebuffers.size";
},
);
};
};
setLayouts = {
twod = {
twod.set = {
bindings = (
{
binding = 0;
@ -124,8 +151,7 @@
},
);
};
alias.textures = {
flags = push_descriptor;
alias.matrices = {
bindings = (
{
binding = 0;
@ -133,6 +159,17 @@
descriptorCount = 1;
stageFlags = vertex;
},
);
};
alias.textures = {
flags = push_descriptor;
bindings = (
{
binding = 0;
descriptorType = combined_image_sampler;
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 1;
descriptorType = combined_image_sampler;
@ -151,12 +188,6 @@
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 4;
descriptorType = combined_image_sampler;
descriptorCount = 1;
stageFlags = fragment;
},
);
};
alias.lights = {
@ -188,8 +219,8 @@
};
};
pipelineLayouts = {
twod = {
setLayouts = (twod);
twod.layout = {
setLayouts = (twod.set);
};
quakebsp.layout = {
setLayouts = (quakebsp.textures);
@ -207,7 +238,7 @@
);
};
alias.layout = {
setLayouts = (alias.textures, alias.lights);
setLayouts = (alias.matrices, alias.lights, alias.textures);
pushConstantRanges = (
{
stageFlags = vertex;
@ -244,7 +275,7 @@
mapEntries = (
{ size = 4; offset = 0; constantID = 0; },
);
data = <00000000>;
data = <00000008>;
};
},
);
@ -300,7 +331,7 @@
);
};
inputAssembly = {
topology = triangle;
topology = triangle_list;
primitiveRestartEnable = false;
};
viewport = {
@ -357,7 +388,7 @@
dynamic = {
dynamicState = ( viewport, scissor, blend_constants );
};
layout = alias;
layout = alias.layout;
//renderPass = renderpass;
};
quakebsp.main = {
@ -643,7 +674,7 @@
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = twod;
layout = twod.layout;
//renderPass = renderpass;
};
};

View file

@ -0,0 +1,276 @@
/*
vulkan_alias.c
Vulkan alias model pipeline
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2012/1/7
Date: 2021/1/26
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include "qfalloca.h"
#include "QF/cvar.h"
#include "QF/darray.h"
#include "QF/dstring.h"
#include "QF/image.h"
#include "QF/render.h"
#include "QF/skin.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/vrect.h"
#include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_texture.h"
#include "QF/Vulkan/command.h"
#include "QF/Vulkan/descriptor.h"
#include "QF/Vulkan/device.h"
#include "r_internal.h"
#include "vid_vulkan.h"
#include "vkparse.h"
static VkImageView
get_view (qfv_tex_t *tex, qfv_tex_t *default_tex)
{
if (tex) {
return tex->view;
}
if (default_tex) {
return default_tex->view;
}
return 0;
}
void
Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context;
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
model_t *model = ent->model;
aliashdr_t *hdr;
qfv_alias_mesh_t *mesh;
float blend;
aliasskin_t *skin;
if (!(hdr = model->aliashdr)) {
hdr = Cache_Get (&model->cache);
}
mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands);
blend = R_AliasGetLerpedFrames (ent, hdr);
if (0/*XXX ent->skin && ent->skin->tex*/) {
//skin = ent->skin->tex;
} else {
maliasskindesc_t *skindesc;
skindesc = R_AliasGetSkindesc (ent->skinnum, hdr);
skin = (aliasskin_t *) ((byte *) hdr + skindesc->skin);
}
VkDeviceSize offsets[] = {
ent->pose1 * hdr->poseverts,
ent->pose2 * hdr->poseverts,
0,
};
VkBuffer buffers[] = {
mesh->vertex_buffer,
mesh->vertex_buffer,
mesh->uv_buffer,
};
dfunc->vkCmdBindVertexBuffers (aframe->cmd, 0, 3, buffers, offsets);
dfunc->vkCmdBindIndexBuffer (aframe->cmd, mesh->index_buffer, 0,
VK_INDEX_TYPE_UINT32);
dfunc->vkCmdPushConstants (aframe->cmd, actx->layout,
VK_SHADER_STAGE_VERTEX_BIT,
0, 16 * sizeof (float), ent->transform);
dfunc->vkCmdPushConstants (aframe->cmd, actx->layout,
VK_SHADER_STAGE_VERTEX_BIT,
64, sizeof (float), &blend);
aframe->imageInfo[0].imageView = get_view (skin->tex, ctx->default_white);
aframe->imageInfo[1].imageView = get_view (skin->glow, ctx->default_black);
aframe->imageInfo[2].imageView = get_view (skin->colora,
ctx->default_black);
aframe->imageInfo[3].imageView = get_view (skin->colorb,
ctx->default_black);
dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout,
0, 2, aframe->descriptors
+ ALIAS_BUFFER_INFOS);
dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0);
}
void
Vulkan_AliasBegin (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context;
//XXX quat_t fog;
__auto_type cframe = &ctx->framebuffers.a[ctx->curFrame];
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = aframe->cmd;
DARRAY_APPEND (cframe->subCommand, cmd);
//FIXME need per frame matrices
aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
aframe->bufferInfo[1].buffer = aframe->light_buffer;
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass.renderpass, 0,
cframe->framebuffer,
0, 0, 0,
};
VkCommandBufferBeginInfo beginInfo = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit,
};
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->pipeline);
VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1};
VkRect2D scissor = { {0, 0}, {vid.width, vid.height} };
dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor);
dfunc->vkUpdateDescriptorSets (device->dev, 2, aframe->descriptors, 0, 0);
//XXX glsl_Fog_GetColor (fog);
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
}
void
Vulkan_AliasEnd (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context;
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
dfunc->vkEndCommandBuffer (aframe->cmd);
}
static VkDescriptorBufferInfo base_buffer_info = {
0, 0, VK_WHOLE_SIZE
};
static VkDescriptorImageInfo base_image_info = {
0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
};
static VkWriteDescriptorSet base_buffer_write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
0, 0, 1,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0, 0, 0
};
static VkWriteDescriptorSet base_image_write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
0, 0, 1,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, 0, 0
};
void
Vulkan_Alias_Init (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
aliasctx_t *actx = calloc (1, sizeof (aliasctx_t));
ctx->alias_context = actx;
size_t frames = ctx->framebuffers.size;
DARRAY_INIT (&actx->frames, frames);
DARRAY_RESIZE (&actx->frames, frames);
actx->frames.grow = 0;
actx->pipeline = Vulkan_CreatePipeline (ctx, "alias");
actx->layout = QFV_GetPipelineLayout (ctx, "alias.layout");
actx->sampler = QFV_GetSampler (ctx, "alias.sampler");
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca);
for (size_t i = 0; i < layouts->size / 2; i++) {
__auto_type mats = QFV_GetDescriptorSetLayout (ctx, "alias.matrices");
__auto_type lights = QFV_GetDescriptorSetLayout (ctx, "alias.lights");
layouts->a[2 * i + 0] = mats;
layouts->a[2 * i + 1] = lights;
}
__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool");
__auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca);
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers);
__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts);
for (size_t i = 0; i < frames; i++) {
__auto_type aframe = &actx->frames.a[i];
aframe->cmd = cmdBuffers->a[i];
for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) {
aframe->bufferInfo[j] = base_buffer_info;
aframe->descriptors[j] = base_buffer_write;
aframe->descriptors[j].dstSet = sets->a[2 * i + j];
aframe->descriptors[j].dstBinding = 0;
aframe->descriptors[j].pBufferInfo = &aframe->bufferInfo[j];
}
for (int j = 0; j < ALIAS_IMAGE_INFOS; j++) {
aframe->imageInfo[j] = base_image_info;
aframe->imageInfo[j].sampler = actx->sampler;
int k = j + ALIAS_BUFFER_INFOS;
aframe->descriptors[k] = base_image_write;
aframe->descriptors[k].dstBinding = j;
aframe->descriptors[k].pImageInfo = &aframe->imageInfo[j];
}
}
free (sets);
}
void
Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context;
dfunc->vkDestroyPipeline (device->dev, actx->pipeline, 0);
DARRAY_CLEAR (&actx->frames);
free (actx);
}

View file

@ -383,13 +383,13 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
dctx->pipeline = Vulkan_CreatePipeline (ctx, "twod");
dctx->layout = QFV_GetPipelineLayout (ctx, "twod");
dctx->layout = QFV_GetPipelineLayout (ctx, "twod.layout");
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
for (size_t i = 0; i < layouts->size; i++) {
layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod");
layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod.set");
}
__auto_type pool = QFV_GetDescriptorPool (ctx, "twod");
__auto_type pool = QFV_GetDescriptorPool (ctx, "twod.pool");
VkDescriptorBufferInfo bufferInfo = {
ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE

View file

@ -49,7 +49,7 @@
#include "QF/sys.h"
#include "QF/Vulkan/qf_vid.h"
//#include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_bsp.h"
//#include "QF/Vulkan/qf_iqm.h"
#include "QF/Vulkan/qf_lightmap.h"
@ -109,8 +109,8 @@ setup_view (vulkan_ctx_t *ctx)
static void
R_RenderEntities (vulkan_ctx_t *ctx)
{
//entity_t *ent;
//int begun;
entity_t *ent;
int begun;
if (!r_drawentities->int_val)
return;
@ -121,17 +121,16 @@ R_RenderEntities (vulkan_ctx_t *ctx)
if (ent->model->type != mod_##type_name) \
continue; \
if (!begun) { \
glsl_R_##Type##Begin (); \
Vulkan_##Type##Begin (ctx); \
begun = 1; \
} \
currententity = ent; \
glsl_R_Draw##Type (); \
Vulkan_Draw##Type (ent, ctx); \
} \
if (begun) \
glsl_R_##Type##End (); \
Vulkan_##Type##End (ctx); \
} while (0)
//RE_LOOP (alias, Alias);
RE_LOOP (alias, Alias);
//RE_LOOP (iqm, IQM);
//RE_LOOP (sprite, Sprite);
}

View file

@ -242,6 +242,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
plitem_t *item = ctx->pipelineDef;
if (!item || !(item = PL_ObjectForKey (item, "renderpass"))) {
Sys_Printf ("error loading renderpass\n");
return;
} else {
Sys_Printf ("Found renderpass def\n");
}