[vulkan] Switch alias pipeline to multi-texture

This gets the alias pipeline in line with the bsp pipeline, and thus
everything is about as functional as it was before the rework (minus
dealing with large texture sets).
This commit is contained in:
Bill Currie 2021-12-09 00:25:50 +09:00
parent 11492d77ce
commit d5b824a47c
6 changed files with 148 additions and 87 deletions

View file

@ -60,11 +60,9 @@ typedef struct qfv_alias_skin_s {
VkImageView view; VkImageView view;
byte colora[4]; byte colora[4];
byte colorb[4]; byte colorb[4];
int texind;
} qfv_alias_skin_t; } qfv_alias_skin_t;
#define ALIAS_BUFFER_INFOS 1
#define ALIAS_IMAGE_INFOS 1
typedef enum { typedef enum {
QFV_aliasDepth, QFV_aliasDepth,
QFV_aliasGBuffer, QFV_aliasGBuffer,
@ -75,20 +73,25 @@ typedef enum {
typedef struct aliasframe_s { typedef struct aliasframe_s {
qfv_cmdbufferset_t cmdSet; qfv_cmdbufferset_t cmdSet;
VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS];
VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS];
VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS];
} aliasframe_t; } aliasframe_t;
typedef struct aliasframeset_s typedef struct aliasframeset_s
DARRAY_TYPE (aliasframe_t) aliasframeset_t; DARRAY_TYPE (aliasframe_t) aliasframeset_t;
typedef struct aliasindset_s
DARRAY_TYPE (unsigned) aliasindset_t;
typedef struct aliasctx_s { typedef struct aliasctx_s {
aliasframeset_t frames; aliasframeset_t frames;
VkPipeline depth; VkPipeline depth;
VkPipeline gbuf; VkPipeline gbuf;
VkDescriptorSet descriptors;
VkDescriptorPool pool;
VkDescriptorSetLayout setLayout;
VkPipelineLayout layout; VkPipelineLayout layout;
unsigned maxImages;
VkSampler sampler; VkSampler sampler;
aliasindset_t texindices;
} aliasctx_t; } aliasctx_t;
struct vulkan_ctx_s; struct vulkan_ctx_s;
@ -108,6 +111,9 @@ void Vulkan_Mod_MakeAliasModelDisplayLists (struct mod_alias_ctx_s *alias_ctx,
void *_m, int _s, int extra, void *_m, int _s, int extra,
struct vulkan_ctx_s *ctx); struct vulkan_ctx_s *ctx);
void Vulkan_AliasAddSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin);
void Vulkan_AliasRemoveSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin);
void Vulkan_AliasBegin (struct qfv_renderframe_s *rFrame); void Vulkan_AliasBegin (struct qfv_renderframe_s *rFrame);
void Vulkan_DrawAlias (struct entity_s *ent, struct qfv_renderframe_s *rFrame); void Vulkan_DrawAlias (struct entity_s *ent, struct qfv_renderframe_s *rFrame);
void Vulkan_AliasEnd (struct qfv_renderframe_s *rFrame); void Vulkan_AliasEnd (struct qfv_renderframe_s *rFrame);

View file

@ -70,6 +70,7 @@ skin_clear (int skin_offset, aliashdr_t *hdr, vulkan_ctx_t *ctx)
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
qfv_alias_skin_t *skin = (qfv_alias_skin_t *) ((byte *) hdr + skin_offset); qfv_alias_skin_t *skin = (qfv_alias_skin_t *) ((byte *) hdr + skin_offset);
Vulkan_AliasRemoveSkin (ctx, skin);
dfunc->vkDestroyImageView (device->dev, skin->view, 0); dfunc->vkDestroyImageView (device->dev, skin->view, 0);
dfunc->vkDestroyImage (device->dev, skin->image, 0); dfunc->vkDestroyImage (device->dev, skin->image, 0);
dfunc->vkFreeMemory (device->dev, skin->memory, 0); dfunc->vkFreeMemory (device->dev, skin->memory, 0);
@ -221,6 +222,8 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
free (tskin); free (tskin);
Vulkan_AliasAddSkin (ctx, skin);
qfvPopDebug (ctx); qfvPopDebug (ctx);
return skinpix + skinsize; return skinpix + skinsize;
} }

View file

@ -99,11 +99,15 @@
}; };
alias_pool = { alias_pool = {
flags = 0; flags = 0;
maxSets = "2z * $frames.size"; maxSets = 1;
bindings = ( bindings = (
{ {
type = uniform_buffer; type = sampler;
descriptorCount = "2z * $frames.size"; descriptorCount = 1;
},
{
type = sampled_image;
descriptorCount = $properties.limits.maxImages;
}, },
); );
}; };

View file

@ -7,12 +7,11 @@ layout (set = 1, binding = 1) uniform texture2DArray skins[MaxTextures];
layout (push_constant) uniform PushConstants { layout (push_constant) uniform PushConstants {
layout (offset = 68) layout (offset = 68)
uint base_color; uint texind;
uint colorA; uint colorA;
uint colorB; uint colorB;
vec4 base_color;
vec4 fog; vec4 fog;
vec4 color;
int texind;
}; };
layout (location = 0) in vec2 st; layout (location = 0) in vec2 st;
@ -31,7 +30,7 @@ main (void)
vec4 e; vec4 e;
int i; int i;
vec3 light = vec3 (0); vec3 light = vec3 (0);
c = texture (sampler2DArray(skins[texind], samp), vec3 (st, 0)) * unpackUnorm4x8(base_color); c = texture (sampler2DArray(skins[texind], samp), vec3 (st, 0)) * base_color;
c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 1)) * unpackUnorm4x8(colorA); c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 1)) * unpackUnorm4x8(colorA);
c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 2)) * unpackUnorm4x8(colorB); c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 2)) * unpackUnorm4x8(colorB);
e = texture (sampler2DArray(skins[texind], samp), vec3 (st, 3)); e = texture (sampler2DArray(skins[texind], samp), vec3 (st, 3));

View file

@ -54,6 +54,7 @@
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
#include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_matrices.h"
#include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_texture.h"
#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/command.h" #include "QF/Vulkan/command.h"
@ -89,7 +90,6 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context; aliasctx_t *actx = ctx->alias_context;
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
__auto_type mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); __auto_type mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands);
@ -114,13 +114,6 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
dfunc->vkCmdPushConstants (cmd, actx->layout, dfunc->vkCmdPushConstants (cmd, actx->layout,
VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT,
68, frag_size, frag_constants); 68, frag_size, frag_constants);
aframe->imageInfo[0].imageView = skin->view;
dfunc->vkCmdPushDescriptorSetKHR (cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout,
0, ALIAS_IMAGE_INFOS,
aframe->descriptors
+ ALIAS_BUFFER_INFOS);
} }
dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0);
} }
@ -139,7 +132,13 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame)
mat4f_t mat; mat4f_t mat;
float blend; float blend;
} vertex_constants; } vertex_constants;
byte fragment_constants[3][4]; struct {
uint32_t texind;
byte colorA[4];
byte colorB[4];
float base_color[4];
float fog[4];
} fragment_constants;
if (!(hdr = model->aliashdr)) { if (!(hdr = model->aliashdr)) {
hdr = Cache_Get (&model->cache); hdr = Cache_Get (&model->cache);
@ -155,19 +154,21 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame)
skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr);
skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin);
} }
QuatScale (ent->renderer.colormod, 255, fragment_constants[0]); fragment_constants.texind = skin->texind;
QuatCopy (skin->colora, fragment_constants[1]); QuatCopy (ent->renderer.colormod, fragment_constants.base_color);
QuatCopy (skin->colorb, fragment_constants[2]); QuatCopy (skin->colora, fragment_constants.colorA);
QuatCopy (skin->colorb, fragment_constants.colorB);
QuatZero (fragment_constants.fog);
emit_commands (aframe->cmdSet.a[QFV_aliasDepth], emit_commands (aframe->cmdSet.a[QFV_aliasDepth],
ent->animation.pose1, ent->animation.pose2, ent->animation.pose1, ent->animation.pose2,
0, &vertex_constants, 17 * sizeof (float), 0, &vertex_constants, 17 * sizeof (float),
fragment_constants, sizeof (fragment_constants), &fragment_constants, sizeof (fragment_constants),
hdr, rFrame); hdr, rFrame);
emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer],
ent->animation.pose1, ent->animation.pose2, ent->animation.pose1, ent->animation.pose2,
skin, &vertex_constants, 17 * sizeof (float), skin, &vertex_constants, 17 * sizeof (float),
fragment_constants, sizeof (fragment_constants), &fragment_constants, sizeof (fragment_constants),
hdr, rFrame); hdr, rFrame);
} }
@ -202,20 +203,15 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline,
{ 0.6, 0.5, 0, 1}); { 0.6, 0.5, 0, 1});
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
//VkDescriptorSet sets[] = { VkDescriptorSet sets[] = {
// aframe->descriptors[0].dstSet, Vulkan_Matrix_Descrptors (ctx, ctx->curFrame),
// aframe->descriptors[1].dstSet, actx->descriptors,
//}; };
//dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
// actx->layout, 0, 2, sets, 0, 0); actx->layout, 0, 2, sets, 0, 0);
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout,
0, 1, aframe->descriptors + 0);
dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor);
//dfunc->vkUpdateDescriptorSets (device->dev, 2, aframe->descriptors, 0, 0);
//XXX glsl_Fog_GetColor (fog); //XXX glsl_Fog_GetColor (fog);
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0; //XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
} }
@ -243,9 +239,6 @@ Vulkan_AliasBegin (qfv_renderframe_t *rFrame)
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer],
aframe->cmdSet.a[QFV_aliasGBuffer]); aframe->cmdSet.a[QFV_aliasGBuffer]);
//FIXME need per frame matrices
//XXX aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
alias_begin_subpass (QFV_aliasDepth, actx->depth, rFrame); alias_begin_subpass (QFV_aliasDepth, actx->depth, rFrame);
alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, rFrame); alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, rFrame);
} }
@ -281,29 +274,74 @@ Vulkan_AliasDepthRange (qfv_renderframe_t *rFrame,
&viewport); &viewport);
} }
static VkDescriptorBufferInfo base_buffer_info = { static VkDescriptorImageInfo base_sampler_info = { };
0, 0, VK_WHOLE_SIZE
};
static VkDescriptorImageInfo base_image_info = { static VkDescriptorImageInfo base_image_info = {
0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
}; };
static VkWriteDescriptorSet base_buffer_write = { static VkWriteDescriptorSet base_sampler_write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
0, 0, 1, .dstBinding = 0,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 1,
0, 0, 0 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
}; };
static VkWriteDescriptorSet base_image_write = { static VkWriteDescriptorSet base_image_write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
0, 0, 1, .dstBinding = 1,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
0, 0, 0
}; };
void
Vulkan_AliasAddSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context;
if (!actx->texindices.size) {
Sys_Error ("ran out of skins (smart texture handling not implemented)");
}
skin->texind = DARRAY_REMOVE (&actx->texindices);
VkDescriptorImageInfo imageInfo[1];
imageInfo[0] = base_image_info;
imageInfo[0].imageView = skin->view;
VkWriteDescriptorSet write[2];
write[0] = base_image_write;
write[0].dstSet = actx->descriptors;
write[0].dstArrayElement = skin->texind;
write[0].descriptorCount = 1;
write[0].pImageInfo = imageInfo;
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
}
void
Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context;
DARRAY_APPEND (&actx->texindices, skin->texind);
VkDescriptorImageInfo imageInfo[1];
imageInfo[0] = base_image_info;
imageInfo[0].imageView = ctx->default_magenta_array->view;
VkWriteDescriptorSet write[2];
write[0] = base_image_write;
write[0].dstSet = actx->descriptors;
write[0].dstArrayElement = skin->texind;
write[0].descriptorCount = 1;
write[0].pImageInfo = imageInfo;
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
}
void void
Vulkan_Alias_Init (vulkan_ctx_t *ctx) Vulkan_Alias_Init (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
qfvPushDebug (ctx, "alias init"); qfvPushDebug (ctx, "alias init");
@ -320,22 +358,49 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx)
actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout");
actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler");
/*__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca); //FIXME too many places
for (size_t i = 0; i < layouts->size / 2; i++) { __auto_type limits = device->physDev->properties.limits;
__auto_type mats = QFV_GetDescriptorSetLayout (ctx, "alias.matrices"); actx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8);
__auto_type lights = QFV_GetDescriptorSetLayout (ctx, "alias.lights"); actx->pool = Vulkan_CreateDescriptorPool (ctx, "alias_pool");
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, actx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "alias_set");
mats, va (ctx->va_ctx, "set_layout:%s:%d", //FIXME kinda dumb
"alias.matrices", i)); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, for (size_t i = 0; i < layouts->size; i++) {
lights, va (ctx->va_ctx, "set_layout:%s:%d", layouts->a[i] = actx->setLayout;
"alias.lights", i)); }
layouts->a[2 * i + 0] = mats; __auto_type sets = QFV_AllocateDescriptorSet (device, actx->pool, layouts);
layouts->a[2 * i + 1] = lights; actx->descriptors = sets->a[0];
}*/ free (sets);
//__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool");
DARRAY_INIT (&actx->texindices, actx->maxImages);
DARRAY_RESIZE (&actx->texindices, actx->maxImages);
actx->texindices.grow = 0;
actx->texindices.maxSize = actx->maxImages;
for (unsigned i = 0; i < actx->maxImages; i++) {
actx->texindices.a[i] = i;
}
VkDescriptorImageInfo samplerInfo[1];
samplerInfo[0] = base_sampler_info;
samplerInfo[0].sampler = actx->sampler;
VkDescriptorImageInfo imageInfo[actx->maxImages];
for (unsigned i = 0; i < actx->maxImages; i++) {
imageInfo[i] = base_image_info;
imageInfo[i].imageView = ctx->default_magenta_array->view;
}
VkWriteDescriptorSet write[2];
write[0] = base_sampler_write;
write[0].dstSet = actx->descriptors;
write[0].pImageInfo = samplerInfo;
write[1] = base_image_write;
write[1].dstSet = actx->descriptors;
write[1].descriptorCount = actx->maxImages;
write[1].pImageInfo = imageInfo;
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
//__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts);
for (size_t i = 0; i < frames; i++) { for (size_t i = 0; i < frames; i++) {
__auto_type aframe = &actx->frames.a[i]; __auto_type aframe = &actx->frames.a[i];
@ -351,23 +416,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx)
va (ctx->va_ctx, "cmd:alias:%zd:%s", i, va (ctx->va_ctx, "cmd:alias:%zd:%s", i,
alias_pass_names[j])); alias_pass_names[j]));
} }
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[ALIAS_BUFFER_INFOS*i + j];
aframe->descriptors[j].dstBinding = j;
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 = k;
aframe->descriptors[k].pImageInfo = &aframe->imageInfo[j];
}
}
//free (sets);
qfvPopDebug (ctx); qfvPopDebug (ctx);
} }

View file

@ -890,12 +890,12 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset,
VK_INDEX_TYPE_UINT32); VK_INDEX_TYPE_UINT32);
VkDescriptorSet set[2] = { VkDescriptorSet sets[] = {
Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), Vulkan_Matrix_Descrptors (ctx, ctx->curFrame),
bctx->descriptors, bctx->descriptors,
}; };
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, 2, set, 0, 0); layout, 0, 2, sets, 0, 0);
//XXX glsl_Fog_GetColor (fog); //XXX glsl_Fog_GetColor (fog);
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0; //XXX fog[3] = glsl_Fog_GetDensity () / 64.0;