[model] Make alias skin loading a batch operation

Really, this won't make all that much difference because alias models
with more than one skin are quite rare, and those with animated skin
groups are even rarer. However, for those models that do have more than
one skin, it will allow for reduced allocation overheads, and when
supported (glsl, vulkan, maybe gl), loading all the skins into an array
texture (since all skins are the same size, though external skins may
vary), but that's not implemented yet, this just wraps the old one skin
at a time code.
This commit is contained in:
Bill Currie 2022-04-04 15:38:27 +09:00
parent f66df59c43
commit e40f3f4f93
12 changed files with 105 additions and 35 deletions

View file

@ -94,10 +94,8 @@ struct qfv_renderframe_s;
struct entity_s; struct entity_s;
struct mod_alias_ctx_s; struct mod_alias_ctx_s;
void *Vulkan_Mod_LoadSkin (struct mod_alias_ctx_s *alias_ctx, byte *skin, void Vulkan_Mod_LoadAllSkins (struct mod_alias_ctx_s *alias_ctx,
int skinsize, int snum, int gnum, qboolean group, struct vulkan_ctx_s *ctx);
maliasskindesc_t *skindesc,
struct vulkan_ctx_s *ctx);
void Vulkan_Mod_FinalizeAliasModel (struct mod_alias_ctx_s *alias_ctx, void Vulkan_Mod_FinalizeAliasModel (struct mod_alias_ctx_s *alias_ctx,
struct vulkan_ctx_s *ctx); struct vulkan_ctx_s *ctx);
void Vulkan_Mod_LoadExternalSkins (struct mod_alias_ctx_s *alias_ctx, void Vulkan_Mod_LoadExternalSkins (struct mod_alias_ctx_s *alias_ctx,

View file

@ -58,9 +58,7 @@ typedef struct vid_model_funcs_s {
void (*Mod_LoadSpriteModel) (model_t *mod, void *buffer); void (*Mod_LoadSpriteModel) (model_t *mod, void *buffer);
void (*Mod_MakeAliasModelDisplayLists) (struct mod_alias_ctx_s *alias_ctx, void (*Mod_MakeAliasModelDisplayLists) (struct mod_alias_ctx_s *alias_ctx,
void *_m, int _s, int extra); void *_m, int _s, int extra);
void *(*Mod_LoadSkin) (struct mod_alias_ctx_s *alias_ctx, byte *skin, void (*Mod_LoadAllSkins) (struct mod_alias_ctx_s *alias_ctx);
int skinsize, int snum, int gnum,
qboolean group, maliasskindesc_t *skindesc);
void (*Mod_FinalizeAliasModel) (struct mod_alias_ctx_s *alias_ctx); void (*Mod_FinalizeAliasModel) (struct mod_alias_ctx_s *alias_ctx);
void (*Mod_LoadExternalSkins) (struct mod_alias_ctx_s *alias_ctx); void (*Mod_LoadExternalSkins) (struct mod_alias_ctx_s *alias_ctx);
void (*Mod_IQMFinish) (model_t *mod); void (*Mod_IQMFinish) (model_t *mod);

View file

@ -7,9 +7,17 @@
#include "QF/skin.h" #include "QF/skin.h"
#include "QF/plugin/vid_render.h" #include "QF/plugin/vid_render.h"
typedef struct mod_alias_skin_s {
int skin_num;
int group_num; // -1 if not in an animated group
byte *texels;
maliasskindesc_t *skindesc;
} mod_alias_skin_t;
typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t; typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t;
typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t; typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t;
typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t; typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t;
typedef struct askinset_s DARRAY_TYPE (mod_alias_skin_t) askinset_t;
typedef struct mod_alias_ctx_s { typedef struct mod_alias_ctx_s {
aliashdr_t *header; aliashdr_t *header;
@ -17,6 +25,7 @@ typedef struct mod_alias_ctx_s {
stvertset_t stverts; stvertset_t stverts;
mtriangleset_t triangles; mtriangleset_t triangles;
trivertxset_t poseverts; trivertxset_t poseverts;
askinset_t skins;
int aliasbboxmins[3]; int aliasbboxmins[3];
int aliasbboxmaxs[3]; int aliasbboxmaxs[3];
} mod_alias_ctx_t; } mod_alias_ctx_t;
@ -49,27 +58,21 @@ extern vid_model_funcs_t *m_funcs;
void gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, void gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
int _s, int extra); int _s, int extra);
void *gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, void gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc);
void gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx); void gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx);
void gl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx); void gl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx);
void gl_Mod_IQMFinish (model_t *mod); void gl_Mod_IQMFinish (model_t *mod);
void glsl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void glsl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx,
void *_m, int _s, int extra); void *_m, int _s, int extra);
void *glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, void glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc);
void glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx); void glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx);
void glsl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx); void glsl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx);
void glsl_Mod_IQMFinish (model_t *mod); void glsl_Mod_IQMFinish (model_t *mod);
void sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, void sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
int _s, int extra); int _s, int extra);
void *sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, void sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc);
void sw_Mod_IQMFinish (model_t *mod); void sw_Mod_IQMFinish (model_t *mod);
void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp);

View file

@ -52,7 +52,7 @@
#include "compat.h" #include "compat.h"
void * static void *
gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group, int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc) maliasskindesc_t *skindesc)
@ -103,6 +103,20 @@ gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
return skin + skinsize; return skin + skinsize;
} }
void
gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
__auto_type skin = alias_ctx->skins.a + i;
gl_Mod_LoadSkin (alias_ctx, skin->texels, skinsize,
skin->skin_num, skin->group_num,
skin->group_num != -1, skin->skindesc);
}
}
void void
gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx)
{ {

View file

@ -90,7 +90,7 @@ glsl_alias_clear (model_t *m, void *data)
} }
} }
void * static void *
glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group, int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc) maliasskindesc_t *skindesc)
@ -114,6 +114,20 @@ glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
return skin + skinsize; return skin + skinsize;
} }
void
glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
__auto_type skin = alias_ctx->skins.a + i;
glsl_Mod_LoadSkin (alias_ctx, skin->texels, skinsize,
skin->skin_num, skin->group_num,
skin->group_num != -1, skin->skindesc);
}
}
void void
glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx)
{ {

View file

@ -75,8 +75,14 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins,
pskindesc[snum].type = pskintype->type; pskindesc[snum].type = pskintype->type;
if (pskintype->type == ALIAS_SKIN_SINGLE) { if (pskintype->type == ALIAS_SKIN_SINGLE) {
skin = (byte *) (pskintype + 1); skin = (byte *) (pskintype + 1);
skin = m_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, snum, 0, mod_alias_skin_t askin = {
false, &pskindesc[snum]); .skin_num = snum,
.group_num = -1,
.texels = skin,
.skindesc = &pskindesc[snum],
};
skin += skinsize;
DARRAY_APPEND (&alias_ctx->skins, askin);
} else { } else {
pskintype++; pskintype++;
pinskingroup = (daliasskingroup_t *) pskintype; pinskingroup = (daliasskingroup_t *) pskintype;
@ -107,13 +113,20 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins,
for (gnum = 0; gnum < groupskins; gnum++) { for (gnum = 0; gnum < groupskins; gnum++) {
paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE; paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE;
skin = mod_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, skin = (byte *) (pskintype + 1);
snum, gnum, true, mod_alias_skin_t askin = {
&paliasskingroup->skindescs[gnum]); .skin_num = snum,
.group_num = gnum,
.texels = skin,
.skindesc = &paliasskingroup->skindescs[gnum],
};
skin += skinsize;
DARRAY_APPEND (&alias_ctx->skins, askin);
} }
} }
pskintype = (daliasskintype_t *) skin; pskintype = (daliasskintype_t *) skin;
} }
mod_funcs->Mod_LoadAllSkins (alias_ctx);
return pskintype; return pskintype;
} }
@ -232,6 +245,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
DARRAY_INIT (&alias_ctx.poseverts, 256); DARRAY_INIT (&alias_ctx.poseverts, 256);
DARRAY_INIT (&alias_ctx.stverts, 256); DARRAY_INIT (&alias_ctx.stverts, 256);
DARRAY_INIT (&alias_ctx.triangles, 256); DARRAY_INIT (&alias_ctx.triangles, 256);
DARRAY_INIT (&alias_ctx.skins, 256);
if (LittleLong (* (unsigned int *) buffer) == HEADER_MDL16) if (LittleLong (* (unsigned int *) buffer) == HEADER_MDL16)
extra = 1; // extra precision bytes extra = 1; // extra precision bytes
@ -392,4 +406,5 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
DARRAY_CLEAR (&alias_ctx.poseverts); DARRAY_CLEAR (&alias_ctx.poseverts);
DARRAY_CLEAR (&alias_ctx.stverts); DARRAY_CLEAR (&alias_ctx.stverts);
DARRAY_CLEAR (&alias_ctx.triangles); DARRAY_CLEAR (&alias_ctx.triangles);
DARRAY_CLEAR (&alias_ctx.skins);
} }

View file

@ -49,7 +49,7 @@
// an animating sequence of poses // an animating sequence of poses
void * static void *
sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin,
int skinsize, int snum, int gnum, int skinsize, int snum, int gnum,
qboolean group, maliasskindesc_t *skindesc) qboolean group, maliasskindesc_t *skindesc)
@ -64,6 +64,20 @@ sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin,
return skin + skinsize; return skin + skinsize;
} }
void
sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
__auto_type skin = alias_ctx->skins.a + i;
sw_Mod_LoadSkin (alias_ctx, skin->texels, skinsize,
skin->skin_num, skin->group_num,
skin->group_num != -1, skin->skindesc);
}
}
static void static void
process_frame (mod_alias_ctx_t *alias_ctx, maliasframedesc_t *frame, process_frame (mod_alias_ctx_t *alias_ctx, maliasframedesc_t *frame,
int posenum, int extra) int posenum, int extra)

View file

@ -111,7 +111,7 @@ vulkan_alias_clear (model_t *m, void *data)
} }
} }
void * static void *
Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
int snum, int gnum, qboolean group, int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) maliasskindesc_t *skindesc, vulkan_ctx_t *ctx)
@ -228,6 +228,20 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
return skinpix + skinsize; return skinpix + skinsize;
} }
void
Vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx)
{
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
__auto_type skin = alias_ctx->skins.a + i;
Vulkan_Mod_LoadSkin (alias_ctx, skin->texels, skinsize,
skin->skin_num, skin->group_num,
skin->group_num != -1, skin->skindesc, ctx);
}
}
void void
Vulkan_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx) Vulkan_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx)
{ {
@ -401,6 +415,9 @@ Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
for (i = 0; i < numtris; i++) { for (i = 0; i < numtris; i++) {
for (j = 0; j < 3; j++) { for (j = 0; j < 3; j++) {
int vind = alias_ctx->triangles.a[i].vertindex[j]; int vind = alias_ctx->triangles.a[i].vertindex[j];
// can't use indexmap to do the test because it indicates only
// that the vertex has been duplicated, not whether or not
// the vertex is the original or the duplicate
if (alias_ctx->stverts.a[vind].onseam if (alias_ctx->stverts.a[vind].onseam
&& !alias_ctx->triangles.a[i].facesfront) { && !alias_ctx->triangles.a[i].facesfront) {
vind = indexmap[vind]; vind = indexmap[vind];

View file

@ -163,7 +163,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel, Mod_LoadSpriteModel,
gl_Mod_MakeAliasModelDisplayLists, gl_Mod_MakeAliasModelDisplayLists,
gl_Mod_LoadSkin, gl_Mod_LoadAllSkins,
gl_Mod_FinalizeAliasModel, gl_Mod_FinalizeAliasModel,
gl_Mod_LoadExternalSkins, gl_Mod_LoadExternalSkins,
gl_Mod_IQMFinish, gl_Mod_IQMFinish,

View file

@ -74,7 +74,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel, Mod_LoadSpriteModel,
glsl_Mod_MakeAliasModelDisplayLists, glsl_Mod_MakeAliasModelDisplayLists,
glsl_Mod_LoadSkin, glsl_Mod_LoadAllSkins,
glsl_Mod_FinalizeAliasModel, glsl_Mod_FinalizeAliasModel,
glsl_Mod_LoadExternalSkins, glsl_Mod_LoadExternalSkins,
glsl_Mod_IQMFinish, glsl_Mod_IQMFinish,

View file

@ -83,7 +83,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel, Mod_LoadSpriteModel,
sw_Mod_MakeAliasModelDisplayLists, sw_Mod_MakeAliasModelDisplayLists,
sw_Mod_LoadSkin, sw_Mod_LoadAllSkins,
0, 0,
0, 0,
sw_Mod_IQMFinish, sw_Mod_IQMFinish,

View file

@ -540,13 +540,10 @@ vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx,
vulkan_ctx); vulkan_ctx);
} }
static void * static void
vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc)
{ {
return Vulkan_Mod_LoadSkin (alias_ctx, skin, skinsize, snum, gnum, group, Vulkan_Mod_LoadAllSkins (alias_ctx, vulkan_ctx);
skindesc, vulkan_ctx);
} }
static void static void
@ -638,7 +635,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel, Mod_LoadSpriteModel,
vulkan_Mod_MakeAliasModelDisplayLists, vulkan_Mod_MakeAliasModelDisplayLists,
vulkan_Mod_LoadSkin, vulkan_Mod_LoadAllSkins,
vulkan_Mod_FinalizeAliasModel, vulkan_Mod_FinalizeAliasModel,
vulkan_Mod_LoadExternalSkins, vulkan_Mod_LoadExternalSkins,
vulkan_Mod_IQMFinish, vulkan_Mod_IQMFinish,