mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
[model] Load bsp textures into vulkan
The textures for an entire model are loaded into a single memory object with shared between multiple images.
This commit is contained in:
parent
ba5e86d927
commit
0f81432090
16 changed files with 247 additions and 23 deletions
|
@ -2,9 +2,14 @@
|
||||||
#define __QF_Vulkan_qf_texture_h
|
#define __QF_Vulkan_qf_texture_h
|
||||||
|
|
||||||
#include "QF/image.h"
|
#include "QF/image.h"
|
||||||
|
#include "QF/Vulkan/qf_vid.h"
|
||||||
|
|
||||||
typedef struct qfv_tex_s qfv_tex_t;
|
typedef struct qfv_tex_s {
|
||||||
struct vulkan_ctx_s;
|
VkDeviceMemory memory;
|
||||||
|
size_t offset;
|
||||||
|
VkImage image;
|
||||||
|
VkImageView view;
|
||||||
|
} qfv_tex_t;
|
||||||
|
|
||||||
qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip);
|
qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip);
|
||||||
VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure));
|
VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure));
|
||||||
|
|
|
@ -422,7 +422,8 @@ typedef struct model_s {
|
||||||
|
|
||||||
// additional model data
|
// additional model data
|
||||||
cache_user_t cache;
|
cache_user_t cache;
|
||||||
void (*clear) (struct model_s *m);
|
void (*clear) (struct model_s *m, void *data);
|
||||||
|
void *data;
|
||||||
} model_t;
|
} model_t;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "QF/skin.h"
|
#include "QF/skin.h"
|
||||||
#include "QF/plugin/vid_render.h"
|
#include "QF/plugin/vid_render.h"
|
||||||
|
|
||||||
|
struct vulkan_ctx_s;
|
||||||
|
|
||||||
extern vid_model_funcs_t *m_funcs;
|
extern vid_model_funcs_t *m_funcs;
|
||||||
|
|
||||||
void gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m,
|
void gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m,
|
||||||
|
@ -41,6 +43,10 @@ void glsl_Mod_ProcessTexture(texture_t *tx);
|
||||||
|
|
||||||
void sw_Mod_LoadLighting (bsp_t *bsp);
|
void sw_Mod_LoadLighting (bsp_t *bsp);
|
||||||
|
|
||||||
|
void Vulkan_Mod_LoadLighting (bsp_t *bsp, struct vulkan_ctx_s *ctx);
|
||||||
|
void Vulkan_Mod_SubdivideSurface (msurface_t *fa, struct vulkan_ctx_s *ctx);
|
||||||
|
void Vulkan_Mod_ProcessTexture(texture_t *tx, struct vulkan_ctx_s *ctx);
|
||||||
|
|
||||||
void gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);
|
void gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);
|
||||||
void glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);
|
void glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);
|
||||||
void sw_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);
|
void sw_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum);
|
||||||
|
|
|
@ -29,11 +29,12 @@ typedef struct glsltex_s {
|
||||||
|
|
||||||
typedef struct vulktex_s {
|
typedef struct vulktex_s {
|
||||||
texture_t *texture;
|
texture_t *texture;
|
||||||
struct qfv_tex_s *tex;
|
|
||||||
instsurf_t *tex_chain; // for gl_texsort drawing
|
instsurf_t *tex_chain; // for gl_texsort drawing
|
||||||
instsurf_t **tex_chain_tail;
|
instsurf_t **tex_chain_tail;
|
||||||
struct elechain_s *elechain;
|
struct elechain_s *elechain;
|
||||||
struct elechain_s **elechain_tail;
|
struct elechain_s **elechain_tail;
|
||||||
|
struct qfv_tex_s *tex;
|
||||||
|
struct qfv_tex_s *glow;
|
||||||
} vulktex_t;
|
} vulktex_t;
|
||||||
|
|
||||||
extern viddef_t vid; // global video state
|
extern viddef_t vid; // global video state
|
||||||
|
|
|
@ -55,7 +55,7 @@ static vec3_t vertex_normals[NUMVERTEXNORMALS] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glsl_alias_clear (model_t *m)
|
glsl_alias_clear (model_t *m, void *data)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
aliashdr_t *hdr;
|
aliashdr_t *hdr;
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
static glsltex_t glsl_notexture = { };
|
static glsltex_t glsl_notexture = { };
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glsl_brush_clear (model_t *m)
|
glsl_brush_clear (model_t *m, void *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
@ -982,10 +982,13 @@ Mod_LoadBrushModel (model_t *mod, void *buffer)
|
||||||
char name[12];
|
char name[12];
|
||||||
|
|
||||||
snprintf (name, sizeof (name), "*%i", i + 1);
|
snprintf (name, sizeof (name), "*%i", i + 1);
|
||||||
loadmodel = Mod_FindName (name);
|
model_t *m = Mod_FindName (name);
|
||||||
*loadmodel = *mod;
|
*m = *mod;
|
||||||
strcpy (loadmodel->name, name);
|
strcpy (m->name, name);
|
||||||
mod = loadmodel;
|
mod = m;
|
||||||
|
// make sure clear is called only for the main model
|
||||||
|
m->clear = 0;
|
||||||
|
m->data = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
vulkan_model_brush.c
|
||||||
|
|
||||||
|
Vulkan support routines for model loading and caching
|
||||||
|
|
||||||
|
Copyright (C) 1996-1997 Id Software, Inc.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
*/
|
||||||
|
// models are the only shared resource between a client and server running
|
||||||
|
// on the same machine.
|
||||||
|
|
||||||
|
#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 "QF/cvar.h"
|
||||||
|
#include "QF/dstring.h"
|
||||||
|
#include "QF/image.h"
|
||||||
|
#include "QF/qendian.h"
|
||||||
|
#include "QF/quakefs.h"
|
||||||
|
#include "QF/sys.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
#include "QF/Vulkan/qf_bsp.h"
|
||||||
|
#include "QF/Vulkan/qf_model.h"
|
||||||
|
#include "QF/Vulkan/qf_texture.h"
|
||||||
|
#include "QF/Vulkan/device.h"
|
||||||
|
#include "QF/Vulkan/image.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
#include "mod_internal.h"
|
||||||
|
#include "r_internal.h"
|
||||||
|
#include "vid_vulkan.h"
|
||||||
|
|
||||||
|
static vulktex_t vulkan_notexture = { };
|
||||||
|
|
||||||
|
static void vulkan_brush_clear (model_t *model, void *data)
|
||||||
|
{
|
||||||
|
modelctx_t *mctx = data;
|
||||||
|
vulkan_ctx_t *ctx = mctx->ctx;
|
||||||
|
qfv_device_t *device = ctx->device;
|
||||||
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
|
|
||||||
|
for (int i = 0; i < model->numtextures; i++) {
|
||||||
|
texture_t *tx = model->textures[i];
|
||||||
|
if (!tx) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vulktex_t *tex = tx->render;
|
||||||
|
dfunc->vkDestroyImage (device->dev, tex->tex->image, 0);
|
||||||
|
if (tex->glow) {
|
||||||
|
dfunc->vkDestroyImage (device->dev, tex->glow->image, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dfunc->vkFreeMemory (device->dev, mctx->texture_memory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
load_textures (model_t *model, vulkan_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
qfv_device_t *device = ctx->device;
|
||||||
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
|
modelctx_t *mctx = model->data;
|
||||||
|
VkImage image = 0;
|
||||||
|
|
||||||
|
size_t memsize = 0;
|
||||||
|
for (int i = 0; i < model->numtextures; i++) {
|
||||||
|
texture_t *tx = model->textures[i];
|
||||||
|
if (!tx) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vulktex_t *tex = tx->render;
|
||||||
|
tex->tex->offset = memsize;
|
||||||
|
memsize += get_image_size (tex->tex->image, device);
|
||||||
|
// just so we have one in the end
|
||||||
|
image = tex->tex->image;
|
||||||
|
if (tex->glow) {
|
||||||
|
tex->glow->offset = memsize;
|
||||||
|
memsize += get_image_size (tex->glow->image, device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VkDeviceMemory mem;
|
||||||
|
mem = QFV_AllocImageMemory (device, image,
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||||
|
memsize, 0);
|
||||||
|
mctx->texture_memory = mem;
|
||||||
|
|
||||||
|
for (int i = 0; i < model->numtextures; i++) {
|
||||||
|
texture_t *tx = model->textures[i];
|
||||||
|
if (!tx) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vulktex_t *tex = tx->render;
|
||||||
|
|
||||||
|
dfunc->vkBindImageMemory (device->dev, tex->tex->image, mem,
|
||||||
|
tex->tex->offset);
|
||||||
|
if (tex->glow) {
|
||||||
|
dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem,
|
||||||
|
tex->glow->offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
qfv_device_t *device = ctx->device;
|
||||||
|
|
||||||
|
if (!tx) {
|
||||||
|
modelctx_t *mctx = Hunk_AllocName (sizeof (modelctx_t),
|
||||||
|
loadmodel->name);
|
||||||
|
mctx->ctx = ctx;
|
||||||
|
loadmodel->clear = vulkan_brush_clear;
|
||||||
|
loadmodel->data = mctx;
|
||||||
|
|
||||||
|
r_notexture_mip->render = &vulkan_notexture;
|
||||||
|
load_textures (loadmodel, ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vulktex_t *tex = tx->render;
|
||||||
|
tex->tex = (qfv_tex_t *) (tx + 1);
|
||||||
|
VkExtent3D extent = { tx->width, tx->height, 1 };
|
||||||
|
|
||||||
|
int layers = 1;
|
||||||
|
if (strncmp (tx->name, "sky", 3) == 0) {
|
||||||
|
layers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->tex->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D,
|
||||||
|
VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
extent, 4, layers,
|
||||||
|
VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
if (layers > 1) {
|
||||||
|
// skys are unlit, so no fullbrights
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name = va ("fb_%s", tx->name);
|
||||||
|
int size = (tx->width * tx->height * 85) / 64;
|
||||||
|
int fullbright_mark = Hunk_LowMark ();
|
||||||
|
byte *pixels = Hunk_AllocName (size, name);
|
||||||
|
|
||||||
|
if (!Mod_CalcFullbright ((byte *) (tx + 1), pixels, size)) {
|
||||||
|
Hunk_FreeToLowMark (fullbright_mark);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tex->glow = tex->tex + 1;
|
||||||
|
tex->glow->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D,
|
||||||
|
VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
extent, 4, 1,
|
||||||
|
VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
// store the pointer to the fullbright data: memory will never be set to
|
||||||
|
// actual device memory because all of the textures will be loaded in one
|
||||||
|
// big buffer
|
||||||
|
tex->glow->memory = (VkDeviceMemory) pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vulkan_Mod_LoadLighting (bsp_t *bsp, vulkan_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
mod_lightmap_bytes = 1;
|
||||||
|
if (!bsp->lightdatasize) {
|
||||||
|
loadmodel->lightdata = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize, loadname);
|
||||||
|
memcpy (loadmodel->lightdata, bsp->lightdata, bsp->lightdatasize);
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ static byte null_texture[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gl_iqm_clear (model_t *mod)
|
gl_iqm_clear (model_t *mod, void *data)
|
||||||
{
|
{
|
||||||
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
||||||
gliqm_t *gl = (gliqm_t *) iqm->extra_data;
|
gliqm_t *gl = (gliqm_t *) iqm->extra_data;
|
||||||
|
|
|
@ -68,7 +68,7 @@ static byte null_normmap[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glsl_iqm_clear (model_t *mod)
|
glsl_iqm_clear (model_t *mod, void *data)
|
||||||
{
|
{
|
||||||
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
||||||
glsliqm_t *glsl = (glsliqm_t *) iqm->extra_data;
|
glsliqm_t *glsl = (glsliqm_t *) iqm->extra_data;
|
||||||
|
|
|
@ -58,7 +58,7 @@ static tex_t null_texture = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sw_iqm_clear (model_t *mod)
|
sw_iqm_clear (model_t *mod, void *data)
|
||||||
{
|
{
|
||||||
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
||||||
swiqm_t *sw = (swiqm_t *) iqm->extra_data;
|
swiqm_t *sw = (swiqm_t *) iqm->extra_data;
|
||||||
|
|
|
@ -123,7 +123,7 @@ Mod_ClearAll (void)
|
||||||
|
|
||||||
for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) {
|
for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) {
|
||||||
if (!(*mod)->needload && (*mod)->clear) {
|
if (!(*mod)->needload && (*mod)->clear) {
|
||||||
(*mod)->clear (*mod);
|
(*mod)->clear (*mod, (*mod)->data);
|
||||||
} else {
|
} else {
|
||||||
if ((*mod)->type != mod_alias)
|
if ((*mod)->type != mod_alias)
|
||||||
(*mod)->needload = true;
|
(*mod)->needload = true;
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
#include "mod_internal.h"
|
#include "mod_internal.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glsl_sprite_clear (model_t *m)
|
glsl_sprite_clear (model_t *m, void *data)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
msprite_t *sprite = (msprite_t *) m->cache.data;
|
msprite_t *sprite = (msprite_t *) m->cache.data;
|
||||||
|
|
|
@ -68,6 +68,7 @@ static U void (*const r_scrapdelete)(rscrap_t *) = R_ScrapDelete;
|
||||||
static void
|
static void
|
||||||
R_shutdown (void *data)
|
R_shutdown (void *data)
|
||||||
{
|
{
|
||||||
|
Mod_ClearAll ();
|
||||||
if (vidrendmodule->functions->general->p_Shutdown) {
|
if (vidrendmodule->functions->general->p_Shutdown) {
|
||||||
vidrendmodule->functions->general->p_Shutdown ();
|
vidrendmodule->functions->general->p_Shutdown ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,6 +388,7 @@ vulkan_r_particles_style_f (struct cvar_s *var)
|
||||||
static void
|
static void
|
||||||
vulkan_Mod_LoadLighting (bsp_t *bsp)
|
vulkan_Mod_LoadLighting (bsp_t *bsp)
|
||||||
{
|
{
|
||||||
|
Vulkan_Mod_LoadLighting (bsp, vulkan_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -398,6 +399,7 @@ vulkan_Mod_SubdivideSurface (msurface_t *fa)
|
||||||
static void
|
static void
|
||||||
vulkan_Mod_ProcessTexture (texture_t *tx)
|
vulkan_Mod_ProcessTexture (texture_t *tx)
|
||||||
{
|
{
|
||||||
|
Vulkan_Mod_ProcessTexture (tx, vulkan_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -449,7 +451,7 @@ vulkan_Skin_InitTranslations (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static vid_model_funcs_t model_funcs = {
|
static vid_model_funcs_t model_funcs = {
|
||||||
sizeof (vulktex_t),
|
sizeof (vulktex_t) + 2 * sizeof (struct qfv_tex_s *),
|
||||||
vulkan_Mod_LoadLighting,
|
vulkan_Mod_LoadLighting,
|
||||||
vulkan_Mod_SubdivideSurface,
|
vulkan_Mod_SubdivideSurface,
|
||||||
vulkan_Mod_ProcessTexture,
|
vulkan_Mod_ProcessTexture,
|
||||||
|
|
|
@ -62,13 +62,6 @@
|
||||||
#include "r_scrap.h"
|
#include "r_scrap.h"
|
||||||
#include "vid_vulkan.h"
|
#include "vid_vulkan.h"
|
||||||
|
|
||||||
struct qfv_tex_s { // qfv_tex_t
|
|
||||||
VkDeviceMemory memory;
|
|
||||||
size_t offset;
|
|
||||||
VkImage image;
|
|
||||||
VkImageView view;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ilog2 (unsigned x)
|
ilog2 (unsigned x)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue