[model] Isolate renderer specific texture data

This cleans up texture_t and possibly even improves locality of
reference when running through texture chains (not profiled, and not
actually the goal).
This commit is contained in:
Bill Currie 2021-01-19 13:05:39 +09:00
parent 40fc9f0000
commit 6e0cb7b917
14 changed files with 130 additions and 62 deletions

View file

@ -91,19 +91,13 @@ typedef struct instsurf_s {
typedef struct texture_s {
char *name;
unsigned int width, height;
int gl_texturenum;
int gl_fb_texturenum;
int sky_tex[2];
instsurf_t *tex_chain; // for gl_texsort drawing
instsurf_t **tex_chain_tail;
struct elechain_s *elechain;
struct elechain_s **elechain_tail;
unsigned width, height;
void *render; // renderer specific data
int anim_total; // total tenths in sequence ( 0 = no)
int anim_min, anim_max; // time for this frame min <=time< max
struct texture_s *anim_next; // in the animation sequence
struct texture_s *alternate_anims; // bmodels in frmae 1 use these
unsigned int offsets[MIPLEVELS]; // four mip maps stored
unsigned offsets[MIPLEVELS]; // four mip maps stored
} texture_t;

View file

@ -80,6 +80,7 @@ typedef struct vid_particle_funcs_s {
} vid_particle_funcs_t;
typedef struct vid_model_funcs_s {
size_t texture_render_size;// size of renderer specific texture data
void (*Mod_LoadLighting) (bsp_t *bsp);
void (*Mod_SubdivideSurface) (msurface_t *fa);
void (*Mod_ProcessTexture) (texture_t *tx);

View file

@ -37,12 +37,9 @@ void gl_Mod_SubdivideSurface (msurface_t *fa);
void gl_Mod_ProcessTexture(texture_t *tx);
void glsl_Mod_LoadLighting (bsp_t *bsp);
void glsl_Mod_SubdivideSurface (msurface_t *fa);
void glsl_Mod_ProcessTexture(texture_t *tx);
void sw_Mod_LoadLighting (bsp_t *bsp);
void sw_Mod_SubdivideSurface (msurface_t *fa);
void sw_Mod_ProcessTexture(texture_t *tx);
void gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);
void glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);

View file

@ -9,6 +9,33 @@
#include "r_screen.h"
#include "r_shared.h"
typedef struct gltex_s {
texture_t *texture;
int gl_texturenum;
int gl_fb_texturenum;
instsurf_t *tex_chain; // for gl_texsort drawing
instsurf_t **tex_chain_tail;
} gltex_t;
typedef struct glsltex_s {
texture_t *texture;
int gl_texturenum;
int sky_tex[2];
instsurf_t *tex_chain; // for gl_texsort drawing
instsurf_t **tex_chain_tail;
struct elechain_s *elechain;
struct elechain_s **elechain_tail;
} glsltex_t;
typedef struct vulktex_s {
texture_t *texture;
struct qfv_tex_s *tex;
instsurf_t *tex_chain; // for gl_texsort drawing
instsurf_t **tex_chain_tail;
struct elechain_s *elechain;
struct elechain_s **elechain_tail;
} vulktex_t;
extern viddef_t vid; // global video state
extern vid_render_data_t vid_render_data;

View file

@ -51,6 +51,8 @@
#include "mod_internal.h"
#include "r_internal.h"
static gltex_t gl_notexture = { };
static tex_t *
Mod_LoadAnExternalTexture (char *tname, char *mname)
{
@ -80,10 +82,13 @@ static int
Mod_LoadExternalTextures (model_t *mod, texture_t *tx)
{
tex_t *base, *luma;
gltex_t *gltx;
int external = 0;
gltx = tx->render;
if ((base = Mod_LoadAnExternalTexture (tx->name, mod->name))) {
external = 1;
tx->gl_texturenum =
gltx->gl_texturenum =
GL_LoadTexture (tx->name, base->width, base->height,
base->data, true, false,
base->format > 2 ? base->format : 1);
@ -94,15 +99,15 @@ Mod_LoadExternalTextures (model_t *mod, texture_t *tx)
luma = Mod_LoadAnExternalTexture (va ("%s_glow", tx->name),
mod->name);
tx->gl_fb_texturenum = 0;
gltx->gl_fb_texturenum = 0;
if (luma) {
tx->gl_fb_texturenum =
gltx->gl_fb_texturenum =
GL_LoadTexture (va ("fb_%s", tx->name), luma->width,
luma->height, luma->data, true, true,
luma->format > 2 ? luma->format : 1);
} else if (base->format < 3) {
tx->gl_fb_texturenum =
gltx->gl_fb_texturenum =
Mod_Fullbright (base->data, base->width, base->height,
va ("fb_%s", tx->name));
}
@ -115,6 +120,10 @@ gl_Mod_ProcessTexture (texture_t *tx)
{
const char *name;
if (!tx) {
r_notexture_mip->render = &gl_notexture;
return;
}
if (gl_textures_external && gl_textures_external->int_val) {
if (Mod_LoadExternalTextures (loadmodel, tx)) {
return;
@ -123,10 +132,11 @@ gl_Mod_ProcessTexture (texture_t *tx)
if (strncmp (tx->name, "sky", 3) == 0) {
return;
}
gltex_t *gltex = tx->render;
name = va ("fb_%s", tx->name);
tx->gl_fb_texturenum =
gltex->gl_fb_texturenum =
Mod_Fullbright ((byte *) (tx + 1), tx->width, tx->height, name);
tx->gl_texturenum =
gltex->gl_texturenum =
GL_LoadTexture (tx->name, tx->width, tx->height, (byte *) (tx + 1),
true, false, 1);
}

View file

@ -57,6 +57,9 @@
#include "compat.h"
#include "mod_internal.h"
#include "r_internal.h"
static glsltex_t glsl_notexture = { };
static void
glsl_brush_clear (model_t *m)
@ -66,11 +69,15 @@ glsl_brush_clear (model_t *m)
m->needload = true;
for (i = 0; i < m->numtextures; i++) {
// NOTE: some maps (eg e1m2) have empty texture slots
if (m->textures[i] && m->textures[i]->gl_texturenum) {
GLSL_ReleaseTexture (m->textures[i]->gl_texturenum);
GLSL_ReleaseTexture (m->textures[i]->sky_tex[0]);
GLSL_ReleaseTexture (m->textures[i]->sky_tex[1]);
m->textures[i]->gl_texturenum = 0;
glsltex_t *tex = 0;
if (m->textures[i]) {
tex = m->textures[i]->render;
}
if (tex && tex->gl_texturenum) {
GLSL_ReleaseTexture (tex->gl_texturenum);
GLSL_ReleaseTexture (tex->sky_tex[0]);
GLSL_ReleaseTexture (tex->sky_tex[1]);
tex->gl_texturenum = 0;
}
}
for (i = 0; i < m->numsurfaces; i++) {
@ -96,6 +103,11 @@ load_skytex (texture_t *tx, byte *data)
void
glsl_Mod_ProcessTexture (texture_t *tx)
{
if (!tx) {
r_notexture_mip->render = &glsl_notexture;
return;
}
glsltex_t *tex = tx->render;
if (!strncmp (tx->name, "sky", 3)) {
// sky textures need to be loaded as two separate textures to allow
// wrapping on both sky layers.
@ -112,23 +124,23 @@ glsl_Mod_ProcessTexture (texture_t *tx)
// a square sky texture probably means it's black, but just in
// case some other magic is being done, duplicate the square to
// both sky layers.
tx->sky_tex[0] = load_skytex (tx, tx_data);
tx->sky_tex[1] = tx->sky_tex[0];
tex->sky_tex[0] = load_skytex (tx, tx_data);
tex->sky_tex[1] = tex->sky_tex[0];
} else if (tx_w == 2 * tx_h) {
data = alloca (tx_h * tx_h);
for (i = 0; i < 2; i++) {
for (j = 0; j < tx_h; j++)
memcpy (&data[j * tx_h], &tx_data[j * tx_w + i * tx_h],
tx_h);
tx->sky_tex[i] = load_skytex (tx, data);
tex->sky_tex[i] = load_skytex (tx, data);
}
tx->gl_texturenum = 0;
tex->gl_texturenum = 0;
} else {
Sys_Error ("Mod_ProcessTexture: invalid sky texture: %dx%d\n",
tx_w, tx_h);
}
} else {
tx->gl_texturenum = GLSL_LoadQuakeMipTex (tx);
tex->gl_texturenum = GLSL_LoadQuakeMipTex (tx);
}
}

View file

@ -204,8 +204,22 @@ Mod_LoadTextures (bsp_t *bsp)
if (!strncmp (mt->name, "sky", 3))
loadmodel->skytexture = tx;
if (mod_funcs && mod_funcs->Mod_ProcessTexture)
}
if (mod_funcs && mod_funcs->Mod_ProcessTexture) {
size_t render_size = mod_funcs->texture_render_size;
byte *render_data = 0;
if (render_size) {
render_data = Hunk_AllocName (m->nummiptex * render_size,
loadname);
}
for (i = 0; i < m->nummiptex; i++) {
tx = loadmodel->textures[i];
tx->render = render_data;
render_data += render_size;
mod_funcs->Mod_ProcessTexture (tx);
}
// signal the end of the textures
mod_funcs->Mod_ProcessTexture (0);
}
// sequence the animations

View file

@ -85,7 +85,7 @@ static instsurf_t **sky_chain_tail;
(chain) = inst; \
} while (0)
static texture_t **r_texture_chains;
static gltex_t **r_texture_chains;
static int r_num_texture_chains;
static int max_texture_chains;
@ -129,16 +129,17 @@ release_instsurfs (void)
}
void
gl_R_AddTexture (texture_t *tex)
gl_R_AddTexture (texture_t *tx)
{
int i;
if (r_num_texture_chains == max_texture_chains) {
max_texture_chains += 64;
r_texture_chains = realloc (r_texture_chains,
max_texture_chains * sizeof (texture_t *));
max_texture_chains * sizeof (gltex_t *));
for (i = r_num_texture_chains; i < max_texture_chains; i++)
r_texture_chains[i] = 0;
}
gltex_t *tex = tx->render;
r_texture_chains[r_num_texture_chains++] = tex;
tex->tex_chain = NULL;
tex->tex_chain_tail = &tex->tex_chain;
@ -174,7 +175,7 @@ R_RenderFullbrights (void)
int i, j;
glpoly_t *p;
instsurf_t *sc;
texture_t *tex;
gltex_t *tex;
for (i = 0; i < r_num_texture_chains; i++) {
if (!(tex = r_texture_chains[i]) || !tex->gl_fb_texturenum)
@ -332,13 +333,15 @@ gl_R_DrawWaterSurfaces (void)
i = -1;
for (s = waterchain; s; s = s->tex_chain) {
gltex_t *tex;
fa = s->surface;
if (s->transform)
qfglLoadMatrixf (s->transform);
else
qfglLoadMatrixf (gl_r_world_matrix);
if (i != fa->texinfo->texture->gl_texturenum) {
i = fa->texinfo->texture->gl_texturenum;
tex = fa->texinfo->texture->render;
if (i != tex->gl_texturenum) {
i = tex->gl_texturenum;
qfglBindTexture (GL_TEXTURE_2D, i);
}
GL_EmitWaterPolys (fa);
@ -360,7 +363,7 @@ DrawTextureChains (int disable_blend, int do_bind)
int i;
instsurf_t *s;
msurface_t *fa;
texture_t *tex;
gltex_t *tex;
if (gl_mtex_active_tmus >= 2) {
// Lightmaps
@ -469,7 +472,7 @@ static void
clear_texture_chains (void)
{
int i;
texture_t *tex;
gltex_t *tex;
for (i = 0; i < r_num_texture_chains; i++) {
tex = r_texture_chains[i];
@ -478,7 +481,7 @@ clear_texture_chains (void)
tex->tex_chain = NULL;
tex->tex_chain_tail = &tex->tex_chain;
}
tex = r_notexture_mip;
tex = r_notexture_mip->render;
tex->tex_chain = NULL;
tex->tex_chain_tail = &tex->tex_chain;
release_instsurfs ();
@ -496,12 +499,14 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color)
} else if (surf->flags & SURF_DRAWSKY) {
CHAIN_SURF_F2B (surf, sky_chain);
} else {
texture_t *tex;
texture_t *tx;
gltex_t *tex;
if (!surf->texinfo->texture->anim_total)
tex = surf->texinfo->texture;
tx = surf->texinfo->texture;
else
tex = R_TextureAnimation (surf);
tx = R_TextureAnimation (surf);
tex = tx->render;
CHAIN_SURF_F2B (surf, tex->tex_chain);
R_AddToLightmapChain (surf);

View file

@ -73,7 +73,7 @@ static instsurf_t **waterchain_tail = &waterchain;
static instsurf_t *sky_chain;
static instsurf_t **sky_chain_tail = &sky_chain;
static texture_t **r_texture_chains;
static glsltex_t **r_texture_chains;
static int r_num_texture_chains;
static int max_texture_chains;
@ -293,16 +293,17 @@ GET_RELEASE (instsurf_t, static_instsurf)
GET_RELEASE (instsurf_t, instsurf)
void
glsl_R_AddTexture (texture_t *tex)
glsl_R_AddTexture (texture_t *tx)
{
int i;
if (r_num_texture_chains == max_texture_chains) {
max_texture_chains += 64;
r_texture_chains = realloc (r_texture_chains,
max_texture_chains * sizeof (texture_t *));
max_texture_chains * sizeof (glsltex_t *));
for (i = r_num_texture_chains; i < max_texture_chains; i++)
r_texture_chains[i] = 0;
}
glsltex_t *tex = tx->render;
r_texture_chains[r_num_texture_chains++] = tex;
tex->tex_chain = 0;
tex->tex_chain_tail = &tex->tex_chain;
@ -325,7 +326,7 @@ glsl_R_InitSurfaceChains (model_t *model)
}
static inline void
clear_tex_chain (texture_t *tex)
clear_tex_chain (glsltex_t *tex)
{
tex->tex_chain = 0;
tex->tex_chain_tail = &tex->tex_chain;
@ -343,7 +344,7 @@ clear_texture_chains (void)
continue;
clear_tex_chain (r_texture_chains[i]);
}
clear_tex_chain (r_notexture_mip);
clear_tex_chain (r_notexture_mip->render);
release_elechains ();
release_elementss ();
release_instsurfs ();
@ -382,12 +383,14 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color)
} else if ((surf->flags & SURF_DRAWTURB) || (color && color[3] < 1.0)) {
CHAIN_SURF_B2F (surf, waterchain);
} else {
texture_t *tex;
texture_t *tx;
glsltex_t *tex;
if (!surf->texinfo->texture->anim_total)
tex = surf->texinfo->texture;
tx = surf->texinfo->texture;
else
tex = R_TextureAnimation (surf);
tx = R_TextureAnimation (surf);
tex = tx->render;
CHAIN_SURF_F2B (surf, tex->tex_chain);
update_lightmap (surf);
@ -444,7 +447,7 @@ glsl_R_RegisterTextures (model_t **models, int num_models)
}
static elechain_t *
add_elechain (texture_t *tex, int ec_index)
add_elechain (glsltex_t *tex, int ec_index)
{
elechain_t *ec;
@ -563,7 +566,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models)
// non-bsp models don't have surfaces.
dm = m->submodels;
for (j = 0; j < m->numsurfaces; j++) {
texture_t *tex;
glsltex_t *tex;
if (j == dm->firstface + dm->numfaces) {
dm++;
if (dm - m->submodels == m->numsubmodels) {
@ -578,7 +581,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models)
surf->ec_index = dm - m->submodels;
if (!surf->ec_index && m != r_worldentity.model)
surf->ec_index = -1 - i; // instanced model
tex = surf->texinfo->texture;
tex = surf->texinfo->texture->render;
CHAIN_SURF_F2B (surf, tex->tex_chain);
}
}
@ -590,7 +593,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models)
// For animated textures, if a surface is on one texture of the group, it
// will be on all.
for (i = 0; i < r_num_texture_chains; i++) {
texture_t *tex;
glsltex_t *tex;
instsurf_t *is;
elechain_t *ec = 0;
elements_t *el = 0;
@ -1057,7 +1060,7 @@ sky_end (void)
}
static inline void
add_surf_elements (texture_t *tex, instsurf_t *is,
add_surf_elements (glsltex_t *tex, instsurf_t *is,
elechain_t **ec, elements_t **el)
{
msurface_t *surf = is->surface;
@ -1096,7 +1099,7 @@ add_surf_elements (texture_t *tex, instsurf_t *is,
}
static void
build_tex_elechain (texture_t *tex)
build_tex_elechain (glsltex_t *tex)
{
instsurf_t *is;
elechain_t *ec = 0;
@ -1136,7 +1139,7 @@ glsl_R_DrawWorld (void)
bsp_begin ();
qfeglActiveTexture (GL_TEXTURE0 + 0);
for (i = 0; i < r_num_texture_chains; i++) {
texture_t *tex;
glsltex_t *tex;
elechain_t *ec = 0;
tex = r_texture_chains[i];
@ -1163,7 +1166,7 @@ glsl_R_DrawWaterSurfaces ()
{
instsurf_t *is;
msurface_t *surf;
texture_t *tex = 0;
glsltex_t *tex = 0;
elechain_t *ec = 0;
elements_t *el = 0;
@ -1173,7 +1176,7 @@ glsl_R_DrawWaterSurfaces ()
turb_begin ();
for (is = waterchain; is; is = is->tex_chain) {
surf = is->surface;
if (tex != surf->texinfo->texture) {
if (tex != surf->texinfo->texture->render) {
if (tex) {
qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
for (ec = tex->elechain; ec; ec = ec->next)
@ -1184,7 +1187,7 @@ glsl_R_DrawWaterSurfaces ()
tex->elechain = 0;
tex->elechain_tail = &tex->elechain;
}
tex = surf->texinfo->texture;
tex = surf->texinfo->texture->render;
}
add_surf_elements (tex, is, &ec, &el);
}
@ -1209,7 +1212,7 @@ glsl_R_DrawSky (void)
{
instsurf_t *is;
msurface_t *surf;
texture_t *tex = 0;
glsltex_t *tex = 0;
elechain_t *ec = 0;
elements_t *el = 0;
@ -1219,7 +1222,7 @@ glsl_R_DrawSky (void)
sky_begin ();
for (is = sky_chain; is; is = is->tex_chain) {
surf = is->surface;
if (tex != surf->texinfo->texture) {
if (tex != surf->texinfo->texture->render) {
if (tex) {
if (!skybox_loaded) {
qfeglActiveTexture (GL_TEXTURE0 + 0);
@ -1233,7 +1236,7 @@ glsl_R_DrawSky (void)
tex->elechain = 0;
tex->elechain_tail = &tex->elechain;
}
tex = surf->texinfo->texture;
tex = surf->texinfo->texture->render;
}
add_surf_elements (tex, is, &ec, &el);
}

View file

@ -46,6 +46,7 @@
gl_ctx_t *gl_ctx;
static vid_model_funcs_t model_funcs = {
sizeof (gltex_t),
gl_Mod_LoadLighting,
gl_Mod_SubdivideSurface,
gl_Mod_ProcessTexture,

View file

@ -46,6 +46,7 @@
gl_ctx_t *glsl_ctx;
static vid_model_funcs_t model_funcs = {
sizeof (glsltex_t),
glsl_Mod_LoadLighting,
0,//Mod_SubdivideSurface,
glsl_Mod_ProcessTexture,

View file

@ -39,6 +39,7 @@
sw_ctx_t *sw_ctx;
static vid_model_funcs_t model_funcs = {
0,
sw_Mod_LoadLighting,
0,//Mod_SubdivideSurface,
0,//Mod_ProcessTexture,

View file

@ -44,6 +44,7 @@
sw_ctx_t *sw32_ctx;
static vid_model_funcs_t model_funcs = {
0,
sw_Mod_LoadLighting,
0,//Mod_SubdivideSurface,
0,//Mod_ProcessTexture,

View file

@ -449,6 +449,7 @@ vulkan_Skin_InitTranslations (void)
}
static vid_model_funcs_t model_funcs = {
sizeof (vulktex_t),
vulkan_Mod_LoadLighting,
vulkan_Mod_SubdivideSurface,
vulkan_Mod_ProcessTexture,