2021-01-19 16:25:54 +00:00
|
|
|
/*
|
|
|
|
vulkan_bsp.c
|
|
|
|
|
|
|
|
Vulkan bsp
|
|
|
|
|
|
|
|
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/18
|
|
|
|
|
|
|
|
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/image.h"
|
|
|
|
#include "QF/render.h"
|
|
|
|
#include "QF/sys.h"
|
|
|
|
#include "QF/va.h"
|
|
|
|
|
2021-07-24 05:19:52 +00:00
|
|
|
#include "QF/scene/entity.h"
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
#include "QF/Vulkan/qf_bsp.h"
|
|
|
|
#include "QF/Vulkan/qf_lightmap.h"
|
2021-12-08 12:11:36 +00:00
|
|
|
#include "QF/Vulkan/qf_matrices.h"
|
2021-01-19 16:25:54 +00:00
|
|
|
#include "QF/Vulkan/qf_texture.h"
|
2021-01-20 07:28:04 +00:00
|
|
|
#include "QF/Vulkan/buffer.h"
|
2021-01-23 11:42:53 +00:00
|
|
|
#include "QF/Vulkan/barrier.h"
|
2021-01-19 16:25:54 +00:00
|
|
|
#include "QF/Vulkan/command.h"
|
2021-01-31 10:58:55 +00:00
|
|
|
#include "QF/Vulkan/debug.h"
|
2021-01-19 16:25:54 +00:00
|
|
|
#include "QF/Vulkan/descriptor.h"
|
|
|
|
#include "QF/Vulkan/device.h"
|
2021-01-23 11:42:53 +00:00
|
|
|
#include "QF/Vulkan/image.h"
|
2021-01-21 17:20:32 +00:00
|
|
|
#include "QF/Vulkan/instance.h"
|
2021-12-02 12:58:29 +00:00
|
|
|
#include "QF/Vulkan/renderpass.h"
|
2021-01-21 07:39:11 +00:00
|
|
|
#include "QF/Vulkan/scrap.h"
|
2021-01-19 16:25:54 +00:00
|
|
|
#include "QF/Vulkan/staging.h"
|
|
|
|
|
|
|
|
#include "r_internal.h"
|
|
|
|
#include "vid_vulkan.h"
|
|
|
|
|
2021-12-17 06:51:33 +00:00
|
|
|
typedef struct bsp_push_constants_s {
|
|
|
|
mat4f_t Model;
|
|
|
|
quat_t fog;
|
|
|
|
float time;
|
|
|
|
} bsp_push_constants_t;
|
|
|
|
|
2021-04-01 23:48:11 +00:00
|
|
|
static const char * __attribute__((used)) bsp_pass_names[] = {
|
2021-02-14 02:35:06 +00:00
|
|
|
"depth",
|
|
|
|
"g-buffer",
|
2021-03-23 03:24:24 +00:00
|
|
|
"sky",
|
|
|
|
"turb",
|
2021-02-14 02:35:06 +00:00
|
|
|
};
|
|
|
|
|
2021-03-22 23:25:56 +00:00
|
|
|
static QFV_Subpass subpass_map[] = {
|
|
|
|
QFV_passDepth, // QFV_bspDepth
|
|
|
|
QFV_passGBuffer, // QFV_bspGBuffer
|
2021-03-23 03:24:24 +00:00
|
|
|
QFV_passTranslucent, // QFV_bspSky
|
|
|
|
QFV_passTranslucent, // QFV_bspTurb
|
2021-03-22 23:25:56 +00:00
|
|
|
};
|
|
|
|
|
2021-01-21 17:42:58 +00:00
|
|
|
static float identity[] = {
|
|
|
|
1, 0, 0, 0,
|
|
|
|
0, 1, 0, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 0, 1,
|
|
|
|
};
|
|
|
|
|
2022-05-05 12:22:44 +00:00
|
|
|
static vulktex_t vulkan_notexture = { };
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
#define ALLOC_CHUNK 64
|
|
|
|
|
2021-01-20 06:11:50 +00:00
|
|
|
typedef struct bsppoly_s {
|
2021-01-19 16:25:54 +00:00
|
|
|
uint32_t count;
|
|
|
|
uint32_t indices[1];
|
2021-01-20 06:11:50 +00:00
|
|
|
} bsppoly_t;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
#define CHAIN_SURF_F2B(surf,chain) \
|
2021-07-13 07:02:47 +00:00
|
|
|
({ \
|
2021-01-19 16:25:54 +00:00
|
|
|
instsurf_t *inst = (surf)->instsurf; \
|
|
|
|
if (__builtin_expect(!inst, 1)) \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst = get_instsurf (bctx); \
|
2021-01-19 16:25:54 +00:00
|
|
|
inst->surface = (surf); \
|
|
|
|
*(chain##_tail) = inst; \
|
|
|
|
(chain##_tail) = &inst->tex_chain; \
|
|
|
|
*(chain##_tail) = 0; \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst; \
|
|
|
|
})
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
#define CHAIN_SURF_B2F(surf,chain) \
|
2021-07-13 07:02:47 +00:00
|
|
|
({ \
|
2021-01-19 16:25:54 +00:00
|
|
|
instsurf_t *inst = (surf)->instsurf; \
|
|
|
|
if (__builtin_expect(!inst, 1)) \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst = get_instsurf (bctx); \
|
2021-01-19 16:25:54 +00:00
|
|
|
inst->surface = (surf); \
|
|
|
|
inst->tex_chain = (chain); \
|
|
|
|
(chain) = inst; \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst; \
|
|
|
|
})
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
#define GET_RELEASE(type,name) \
|
|
|
|
static inline type * \
|
|
|
|
get_##name (bspctx_t *bctx) \
|
|
|
|
{ \
|
|
|
|
type *ele; \
|
|
|
|
if (!bctx->free_##name##s) { \
|
|
|
|
int i; \
|
|
|
|
bctx->free_##name##s = calloc (ALLOC_CHUNK, sizeof (type)); \
|
|
|
|
for (i = 0; i < ALLOC_CHUNK - 1; i++) \
|
|
|
|
bctx->free_##name##s[i]._next = &bctx->free_##name##s[i + 1]; \
|
|
|
|
} \
|
|
|
|
ele = bctx->free_##name##s; \
|
|
|
|
bctx->free_##name##s = ele->_next; \
|
|
|
|
ele->_next = 0; \
|
|
|
|
*bctx->name##s_tail = ele; \
|
|
|
|
bctx->name##s_tail = &ele->_next; \
|
|
|
|
return ele; \
|
|
|
|
} \
|
|
|
|
static inline void \
|
|
|
|
release_##name##s (bspctx_t *bctx) \
|
|
|
|
{ \
|
|
|
|
if (bctx->name##s) { \
|
|
|
|
*bctx->name##s_tail = bctx->free_##name##s; \
|
|
|
|
bctx->free_##name##s = bctx->name##s; \
|
|
|
|
bctx->name##s = 0; \
|
|
|
|
bctx->name##s_tail = &bctx->name##s; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
GET_RELEASE (elechain_t, elechain)
|
|
|
|
GET_RELEASE (elements_t, elements)
|
|
|
|
GET_RELEASE (instsurf_t, static_instsurf)
|
|
|
|
GET_RELEASE (instsurf_t, instsurf)
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_texture (texture_t *tx, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
|
|
|
|
vulktex_t *tex = tx->render;
|
2021-12-17 03:20:32 +00:00
|
|
|
if (tex->tex) {
|
|
|
|
DARRAY_APPEND (&bctx->texture_chains, tex);
|
|
|
|
tex->descriptor = Vulkan_CreateTextureDescriptor (ctx, tex->tex,
|
|
|
|
bctx->sampler);
|
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
tex->tex_chain = 0;
|
|
|
|
tex->tex_chain_tail = &tex->tex_chain;
|
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-01 10:31:11 +00:00
|
|
|
init_surface_chains (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
|
|
|
|
release_static_instsurfs (bctx);
|
|
|
|
release_instsurfs (bctx);
|
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (unsigned i = 0; i < brush->nummodelsurfaces; i++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->surfaces[i].instsurf = get_static_instsurf (bctx);
|
|
|
|
brush->surfaces[i].instsurf->surface = &brush->surfaces[i];
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
clear_tex_chain (vulktex_t *tex)
|
|
|
|
{
|
|
|
|
tex->tex_chain = 0;
|
|
|
|
tex->tex_chain_tail = &tex->tex_chain;
|
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clear_texture_chains (bspctx_t *bctx)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < bctx->texture_chains.size; i++) {
|
|
|
|
if (!bctx->texture_chains.a[i])
|
|
|
|
continue;
|
|
|
|
clear_tex_chain (bctx->texture_chains.a[i]);
|
|
|
|
}
|
|
|
|
clear_tex_chain (r_notexture_mip->render);
|
|
|
|
release_elechains (bctx);
|
|
|
|
release_elementss (bctx);
|
|
|
|
release_instsurfs (bctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Vulkan_ClearElements (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
release_elechains (bctx);
|
|
|
|
release_elementss (bctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2021-07-22 06:39:28 +00:00
|
|
|
chain_surface (msurface_t *surf, vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
instsurf_t *is;
|
|
|
|
|
|
|
|
if (surf->flags & SURF_DRAWSKY) {
|
2021-07-13 07:02:47 +00:00
|
|
|
is = CHAIN_SURF_F2B (surf, bctx->sky_chain);
|
2021-07-22 06:39:28 +00:00
|
|
|
} else if ((surf->flags & SURF_DRAWTURB)
|
|
|
|
|| (bctx->color && bctx->color[3] < 1.0)) {
|
2021-07-13 07:02:47 +00:00
|
|
|
is = CHAIN_SURF_B2F (surf, bctx->waterchain);
|
2021-01-19 16:25:54 +00:00
|
|
|
} else {
|
|
|
|
texture_t *tx;
|
|
|
|
vulktex_t *tex;
|
|
|
|
|
|
|
|
if (!surf->texinfo->texture->anim_total)
|
|
|
|
tx = surf->texinfo->texture;
|
|
|
|
else
|
2021-07-22 06:39:28 +00:00
|
|
|
tx = R_TextureAnimation (bctx->entity, surf);
|
2021-01-19 16:25:54 +00:00
|
|
|
tex = tx->render;
|
2021-07-13 07:02:47 +00:00
|
|
|
is = CHAIN_SURF_F2B (surf, tex->tex_chain);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-07-22 06:39:28 +00:00
|
|
|
is->transform = bctx->transform;
|
|
|
|
is->color = bctx->color;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-01 10:31:11 +00:00
|
|
|
register_textures (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
texture_t *tex;
|
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (unsigned i = 0; i < brush->numtextures; i++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
tex = brush->textures[i];
|
2021-01-19 16:25:54 +00:00
|
|
|
if (!tex)
|
|
|
|
continue;
|
|
|
|
add_texture (tex, ctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clear_textures (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
bctx->texture_chains.size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
model_t *m;
|
2022-03-14 06:27:43 +00:00
|
|
|
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
clear_textures (ctx);
|
2021-02-01 10:31:11 +00:00
|
|
|
init_surface_chains (brush, ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
add_texture (r_notexture_mip, ctx);
|
2021-02-01 10:31:11 +00:00
|
|
|
register_textures (brush, ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
for (i = 0; i < num_models; i++) {
|
|
|
|
m = models[i];
|
|
|
|
if (!m)
|
|
|
|
continue;
|
|
|
|
// sub-models are done as part of the main model
|
2021-02-01 05:39:00 +00:00
|
|
|
if (*m->path == '*')
|
2021-01-19 16:25:54 +00:00
|
|
|
continue;
|
|
|
|
// world has already been done, not interested in non-brush models
|
2022-03-14 06:27:43 +00:00
|
|
|
if (m == r_refdef.worldmodel || m->type != mod_brush)
|
2021-01-19 16:25:54 +00:00
|
|
|
continue;
|
2021-02-01 10:31:11 +00:00
|
|
|
brush = &m->brush;
|
|
|
|
brush->numsubmodels = 1; // no support for submodels in non-world model
|
|
|
|
register_textures (brush, ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static elechain_t *
|
2021-07-19 14:38:09 +00:00
|
|
|
add_elechain (vulktex_t *tex, bspctx_t *bctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
elechain_t *ec;
|
|
|
|
|
|
|
|
ec = get_elechain (bctx);
|
|
|
|
ec->elements = get_elements (bctx);
|
|
|
|
ec->transform = 0;
|
|
|
|
ec->color = 0;
|
|
|
|
*tex->elechain_tail = ec;
|
|
|
|
tex->elechain_tail = &ec->next;
|
|
|
|
return ec;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-07-15 12:38:12 +00:00
|
|
|
count_verts_inds (model_t **models, msurface_t *surf,
|
2021-01-20 06:11:50 +00:00
|
|
|
uint32_t *verts, uint32_t *inds)
|
|
|
|
{
|
2021-07-15 12:38:12 +00:00
|
|
|
*verts = surf->numedges;
|
|
|
|
*inds = surf->numedges + 1;
|
2021-01-20 06:11:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bsppoly_t *
|
2021-07-15 12:38:12 +00:00
|
|
|
build_surf_displist (model_t **models, msurface_t *surf, int base,
|
2021-01-20 06:11:50 +00:00
|
|
|
bspvert_t **vert_list)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
int numverts;
|
|
|
|
int numindices;
|
|
|
|
int i;
|
|
|
|
vec_t *vec;
|
|
|
|
mvertex_t *vertices;
|
|
|
|
medge_t *edges;
|
|
|
|
int *surfedges;
|
|
|
|
int index;
|
|
|
|
bspvert_t *verts;
|
2021-01-20 06:11:50 +00:00
|
|
|
bsppoly_t *poly;
|
2021-01-19 16:25:54 +00:00
|
|
|
uint32_t *ind;
|
|
|
|
float s, t;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-07-15 12:38:12 +00:00
|
|
|
if (surf->model_index < 0) {
|
2021-01-20 06:11:50 +00:00
|
|
|
// instance model
|
2021-07-15 12:38:12 +00:00
|
|
|
brush = &models[~surf->model_index]->brush;
|
2021-01-19 16:25:54 +00:00
|
|
|
} else {
|
2021-01-20 06:11:50 +00:00
|
|
|
// main or sub model
|
2022-03-14 06:27:43 +00:00
|
|
|
brush = &r_refdef.worldmodel->brush;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-02-01 10:31:11 +00:00
|
|
|
vertices = brush->vertexes;
|
|
|
|
edges = brush->edges;
|
|
|
|
surfedges = brush->surfedges;
|
2021-01-20 06:11:50 +00:00
|
|
|
// create a triangle fan
|
2021-07-15 12:38:12 +00:00
|
|
|
numverts = surf->numedges;
|
2021-01-20 06:11:50 +00:00
|
|
|
numindices = numverts + 1;
|
|
|
|
verts = *vert_list;
|
2021-01-21 05:37:39 +00:00
|
|
|
// surf->polys is set to the next slot before the call
|
2021-07-15 12:38:12 +00:00
|
|
|
poly = (bsppoly_t *) surf->polys;
|
2021-01-19 16:25:54 +00:00
|
|
|
poly->count = numindices;
|
2021-01-20 06:11:50 +00:00
|
|
|
for (i = 0, ind = poly->indices; i < numverts; i++) {
|
|
|
|
*ind++ = base + i;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-01-20 06:11:50 +00:00
|
|
|
*ind++ = -1; // end of primitive
|
2021-07-15 12:38:12 +00:00
|
|
|
surf->polys = (glpoly_t *) poly;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-07-15 12:38:12 +00:00
|
|
|
mtexinfo_t *texinfo = surf->texinfo;
|
2021-01-19 16:25:54 +00:00
|
|
|
for (i = 0; i < numverts; i++) {
|
2021-07-15 12:38:12 +00:00
|
|
|
index = surfedges[surf->firstedge + i];
|
2021-01-20 06:11:50 +00:00
|
|
|
if (index > 0) {
|
2021-01-19 16:25:54 +00:00
|
|
|
vec = vertices[edges[index].v[0]].position;
|
2021-01-20 06:11:50 +00:00
|
|
|
} else {
|
2021-01-19 16:25:54 +00:00
|
|
|
vec = vertices[edges[-index].v[1]].position;
|
2021-01-20 06:11:50 +00:00
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-07-15 12:38:12 +00:00
|
|
|
s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3];
|
|
|
|
t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3];
|
2021-01-19 16:25:54 +00:00
|
|
|
VectorCopy (vec, verts[i].vertex);
|
|
|
|
verts[i].vertex[3] = 1;
|
2021-07-15 12:38:12 +00:00
|
|
|
verts[i].tlst[0] = s / texinfo->texture->width;
|
|
|
|
verts[i].tlst[1] = t / texinfo->texture->height;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
//lightmap texture coordinates
|
2021-07-15 12:38:12 +00:00
|
|
|
if (!surf->lightpic) {
|
2021-01-19 16:25:54 +00:00
|
|
|
// sky and water textures don't have lightmaps
|
|
|
|
verts[i].tlst[2] = 0;
|
|
|
|
verts[i].tlst[3] = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2021-07-15 12:38:12 +00:00
|
|
|
s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3];
|
|
|
|
t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3];
|
|
|
|
s -= surf->texturemins[0];
|
|
|
|
t -= surf->texturemins[1];
|
|
|
|
s += surf->lightpic->rect->x * 16 + 8;
|
|
|
|
t += surf->lightpic->rect->y * 16 + 8;
|
2021-01-19 16:25:54 +00:00
|
|
|
s /= 16;
|
|
|
|
t /= 16;
|
2021-07-15 12:38:12 +00:00
|
|
|
verts[i].tlst[2] = s * surf->lightpic->size;
|
|
|
|
verts[i].tlst[3] = t * surf->lightpic->size;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-01-20 06:11:50 +00:00
|
|
|
*vert_list += numverts;
|
|
|
|
return (bsppoly_t *) &poly->indices[numindices];
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|
|
|
{
|
2021-01-20 06:11:50 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
2021-01-20 07:28:04 +00:00
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-01-19 16:25:54 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
int vertex_index_base;
|
|
|
|
model_t *m;
|
|
|
|
dmodel_t *dm;
|
|
|
|
msurface_t *surf;
|
2021-01-20 06:11:50 +00:00
|
|
|
qfv_stagebuf_t *stage;
|
|
|
|
bspvert_t *vertices;
|
|
|
|
bsppoly_t *poly;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2022-04-25 22:26:32 +00:00
|
|
|
if (!num_models) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-13 13:59:51 +00:00
|
|
|
// run through all surfaces, chaining them to their textures, thus
|
2021-01-19 16:25:54 +00:00
|
|
|
// effectively sorting the surfaces by texture (without worrying about
|
|
|
|
// surface order on the same texture chain).
|
2021-08-01 12:54:05 +00:00
|
|
|
for (int i = 0; i < num_models; i++) {
|
2021-01-19 16:25:54 +00:00
|
|
|
m = models[i];
|
|
|
|
if (!m)
|
|
|
|
continue;
|
|
|
|
// sub-models are done as part of the main model
|
2021-07-13 13:59:51 +00:00
|
|
|
// and non-bsp models don't have surfaces.
|
2021-02-01 10:31:11 +00:00
|
|
|
if (*m->path == '*' || m->type != mod_brush)
|
2021-01-19 16:25:54 +00:00
|
|
|
continue;
|
2021-02-01 10:31:11 +00:00
|
|
|
brush = &m->brush;
|
|
|
|
dm = brush->submodels;
|
2021-08-01 12:54:05 +00:00
|
|
|
for (unsigned j = 0; j < brush->numsurfaces; j++) {
|
2021-01-19 16:25:54 +00:00
|
|
|
vulktex_t *tex;
|
|
|
|
if (j == dm->firstface + dm->numfaces) {
|
2021-07-13 13:59:51 +00:00
|
|
|
// move on to the next sub-model
|
2021-01-19 16:25:54 +00:00
|
|
|
dm++;
|
2021-08-02 05:02:41 +00:00
|
|
|
if (dm == brush->submodels + brush->numsubmodels) {
|
2021-01-19 16:25:54 +00:00
|
|
|
// limit the surfaces
|
|
|
|
// probably never hit
|
|
|
|
Sys_Printf ("R_BuildDisplayLists: too many surfaces\n");
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->numsurfaces = j;
|
2021-01-19 16:25:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-02-01 10:31:11 +00:00
|
|
|
surf = brush->surfaces + j;
|
2021-07-13 13:59:51 +00:00
|
|
|
surf->model_index = dm - brush->submodels;
|
2022-03-14 06:27:43 +00:00
|
|
|
if (!surf->model_index && m != r_refdef.worldmodel) {
|
2021-07-13 13:59:51 +00:00
|
|
|
surf->model_index = -1 - i; // instanced model
|
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
tex = surf->texinfo->texture->render;
|
2021-01-20 06:11:50 +00:00
|
|
|
// append surf to the texture chain
|
2021-01-19 16:25:54 +00:00
|
|
|
CHAIN_SURF_F2B (surf, tex->tex_chain);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// All vertices from all brush models go into one giant vbo.
|
2021-01-20 06:11:50 +00:00
|
|
|
uint32_t vertex_count = 0;
|
|
|
|
uint32_t index_count = 0;
|
|
|
|
uint32_t poly_count = 0;
|
|
|
|
for (size_t i = 0; i < bctx->texture_chains.size; i++) {
|
|
|
|
vulktex_t *tex = bctx->texture_chains.a[i];
|
|
|
|
for (instsurf_t *is = tex->tex_chain; is; is = is->tex_chain) {
|
|
|
|
uint32_t verts, inds;
|
|
|
|
count_verts_inds (models, is->surface, &verts, &inds);
|
|
|
|
vertex_count += verts;
|
|
|
|
index_count += inds;
|
|
|
|
poly_count++;
|
|
|
|
}
|
|
|
|
}
|
2021-01-20 07:28:04 +00:00
|
|
|
|
2021-01-21 17:20:32 +00:00
|
|
|
size_t atom = device->physDev->properties.limits.nonCoherentAtomSize;
|
|
|
|
size_t atom_mask = atom - 1;
|
2021-01-20 07:28:04 +00:00
|
|
|
size_t frames = bctx->frames.size;
|
|
|
|
size_t index_buffer_size = index_count * frames * sizeof (uint32_t);
|
|
|
|
size_t vertex_buffer_size = vertex_count * sizeof (bspvert_t);
|
2021-01-21 17:20:32 +00:00
|
|
|
|
|
|
|
index_buffer_size = (index_buffer_size + atom_mask) & ~atom_mask;
|
2021-01-31 10:58:55 +00:00
|
|
|
stage = QFV_CreateStagingBuffer (device, "bsp", vertex_buffer_size,
|
|
|
|
ctx->cmdpool);
|
2021-01-20 07:28:04 +00:00
|
|
|
qfv_packet_t *packet = QFV_PacketAcquire (stage);
|
|
|
|
vertices = QFV_PacketExtend (packet, vertex_buffer_size);
|
2021-01-19 16:25:54 +00:00
|
|
|
vertex_index_base = 0;
|
2021-07-13 13:59:51 +00:00
|
|
|
// holds all the polygon definitions: vertex indices + poly_count "end of
|
|
|
|
// primitive" markers.
|
2022-05-12 15:55:37 +00:00
|
|
|
free (bctx->polys);
|
2021-01-20 06:11:50 +00:00
|
|
|
bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t));
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
// All usable surfaces have been chained to the (base) texture they use.
|
|
|
|
// Run through the textures, using their chains to build display maps.
|
|
|
|
// For animated textures, if a surface is on one texture of the group, it
|
|
|
|
// will be on all.
|
2021-01-20 06:11:50 +00:00
|
|
|
poly = bctx->polys;
|
|
|
|
int count = 0;
|
2021-01-19 16:25:54 +00:00
|
|
|
for (size_t i = 0; i < bctx->texture_chains.size; i++) {
|
|
|
|
vulktex_t *tex;
|
|
|
|
instsurf_t *is;
|
|
|
|
|
|
|
|
tex = bctx->texture_chains.a[i];
|
|
|
|
|
|
|
|
for (is = tex->tex_chain; is; is = is->tex_chain) {
|
|
|
|
msurface_t *surf = is->surface;
|
|
|
|
|
2021-01-20 06:11:50 +00:00
|
|
|
surf->polys = (glpoly_t *) poly;
|
|
|
|
poly = build_surf_displist (models, surf, vertex_index_base,
|
|
|
|
&vertices);
|
2021-01-19 16:25:54 +00:00
|
|
|
vertex_index_base += surf->numedges;
|
2021-01-20 06:11:50 +00:00
|
|
|
count++;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
clear_texture_chains (bctx);
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_vulkan,
|
2021-07-13 13:59:51 +00:00
|
|
|
"R_BuildDisplayLists: verts:%u, inds:%u, "
|
|
|
|
"polys:%u (%d) %zd\n",
|
2021-01-20 06:11:50 +00:00
|
|
|
vertex_count, index_count, poly_count, count,
|
2021-07-13 13:59:51 +00:00
|
|
|
((size_t) poly - (size_t) bctx->polys) / sizeof(uint32_t));
|
2021-01-20 07:28:04 +00:00
|
|
|
if (index_buffer_size > bctx->index_buffer_size) {
|
|
|
|
if (bctx->index_buffer) {
|
|
|
|
dfunc->vkUnmapMemory (device->dev, bctx->index_memory);
|
|
|
|
dfunc->vkDestroyBuffer (device->dev, bctx->index_buffer, 0);
|
|
|
|
dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0);
|
|
|
|
}
|
|
|
|
bctx->index_buffer
|
|
|
|
= QFV_CreateBuffer (device, index_buffer_size,
|
|
|
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
2021-01-20 07:51:35 +00:00
|
|
|
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, bctx->index_buffer,
|
|
|
|
"buffer:bsp:index");
|
2021-01-20 07:28:04 +00:00
|
|
|
bctx->index_memory
|
|
|
|
= QFV_AllocBufferMemory (device, bctx->index_buffer,
|
2022-04-06 05:40:40 +00:00
|
|
|
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
2021-01-20 07:28:04 +00:00
|
|
|
index_buffer_size, 0);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
|
|
|
bctx->index_memory, "memory:bsp:index");
|
2021-01-20 07:28:04 +00:00
|
|
|
QFV_BindBufferMemory (device,
|
|
|
|
bctx->index_buffer, bctx->index_memory, 0);
|
|
|
|
bctx->index_buffer_size = index_buffer_size;
|
|
|
|
void *data;
|
|
|
|
dfunc->vkMapMemory (device->dev, bctx->index_memory, 0,
|
|
|
|
index_buffer_size, 0, &data);
|
|
|
|
uint32_t *index_data = data;
|
|
|
|
for (size_t i = 0; i < frames; i++) {
|
2021-01-20 07:51:35 +00:00
|
|
|
uint32_t offset = index_count * i;
|
|
|
|
bctx->frames.a[i].index_data = index_data + offset;
|
|
|
|
bctx->frames.a[i].index_offset = offset * sizeof (uint32_t);
|
2021-01-21 05:37:39 +00:00
|
|
|
bctx->frames.a[i].index_count = 0;
|
2021-01-20 07:28:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (vertex_buffer_size > bctx->vertex_buffer_size) {
|
|
|
|
if (bctx->vertex_buffer) {
|
|
|
|
dfunc->vkDestroyBuffer (device->dev, bctx->vertex_buffer, 0);
|
|
|
|
dfunc->vkFreeMemory (device->dev, bctx->vertex_memory, 0);
|
|
|
|
}
|
|
|
|
bctx->vertex_buffer
|
|
|
|
= QFV_CreateBuffer (device, vertex_buffer_size,
|
|
|
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER,
|
|
|
|
bctx->vertex_buffer, "buffer:bsp:vertex");
|
2021-01-20 07:28:04 +00:00
|
|
|
bctx->vertex_memory
|
|
|
|
= QFV_AllocBufferMemory (device, bctx->vertex_buffer,
|
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
vertex_buffer_size, 0);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
|
|
|
bctx->vertex_memory, "memory:bsp:vertex");
|
2021-01-20 07:28:04 +00:00
|
|
|
QFV_BindBufferMemory (device,
|
|
|
|
bctx->vertex_buffer, bctx->vertex_memory, 0);
|
|
|
|
bctx->vertex_buffer_size = vertex_buffer_size;
|
|
|
|
}
|
|
|
|
|
2021-04-24 06:47:31 +00:00
|
|
|
qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite];
|
|
|
|
bb.barrier.buffer = bctx->vertex_buffer;
|
|
|
|
bb.barrier.size = vertex_buffer_size;
|
|
|
|
dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages,
|
|
|
|
0, 0, 0, 1, &bb.barrier, 0, 0);
|
2021-01-20 07:28:04 +00:00
|
|
|
VkBufferCopy copy_region = { packet->offset, 0, vertex_buffer_size };
|
2021-01-21 12:24:54 +00:00
|
|
|
dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer,
|
2021-01-20 07:28:04 +00:00
|
|
|
bctx->vertex_buffer, 1, ©_region);
|
2021-04-24 06:47:31 +00:00
|
|
|
bb = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead];
|
|
|
|
bb.barrier.buffer = bctx->vertex_buffer;
|
|
|
|
bb.barrier.size = vertex_buffer_size;
|
|
|
|
dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages,
|
|
|
|
0, 0, 0, 1, &bb.barrier, 0, 0);
|
2021-01-20 07:28:04 +00:00
|
|
|
QFV_PacketSubmit (packet);
|
2021-01-20 06:11:50 +00:00
|
|
|
QFV_DestroyStagingBuffer (stage);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
float dot, radius;
|
|
|
|
model_t *model;
|
|
|
|
plane_t *plane;
|
|
|
|
msurface_t *surf;
|
|
|
|
qboolean rotated;
|
2021-03-19 11:18:45 +00:00
|
|
|
vec3_t mins, maxs;
|
|
|
|
vec4f_t org;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush;
|
2021-07-22 06:39:28 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
|
|
|
|
bctx->entity = e;
|
|
|
|
bctx->transform = e->renderer.full_transform;
|
|
|
|
bctx->color = e->renderer.colormod;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
model = e->renderer.model;
|
2021-02-01 10:31:11 +00:00
|
|
|
brush = &model->brush;
|
2021-03-09 14:52:40 +00:00
|
|
|
mat4f_t mat;
|
|
|
|
Transform_GetWorldMatrix (e->transform, mat);
|
|
|
|
memcpy (e->renderer.full_transform, mat, sizeof (mat));//FIXME
|
|
|
|
if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) {
|
2021-01-19 16:25:54 +00:00
|
|
|
rotated = true;
|
|
|
|
radius = model->radius;
|
2022-03-30 15:07:20 +00:00
|
|
|
if (R_CullSphere (r_refdef.frustum, (vec_t*)&mat[3], radius)) { //FIXME
|
2021-01-19 16:25:54 +00:00
|
|
|
return;
|
2021-03-19 11:18:45 +00:00
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
} else {
|
|
|
|
rotated = false;
|
2021-03-19 11:18:45 +00:00
|
|
|
VectorAdd (mat[3], model->mins, mins);
|
|
|
|
VectorAdd (mat[3], model->maxs, maxs);
|
2022-03-19 03:33:12 +00:00
|
|
|
if (R_CullBox (r_refdef.frustum, mins, maxs))
|
2021-01-19 16:25:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
org = r_refdef.frame.position - mat[3];
|
2021-01-19 16:25:54 +00:00
|
|
|
if (rotated) {
|
2021-03-19 11:18:45 +00:00
|
|
|
vec4f_t temp = org;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
org[0] = DotProduct (temp, mat[0]);
|
|
|
|
org[1] = DotProduct (temp, mat[1]);
|
|
|
|
org[2] = DotProduct (temp, mat[2]);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
surf = &brush->surfaces[brush->firstmodelsurface];
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (unsigned i = 0; i < brush->nummodelsurfaces; i++, surf++) {
|
2021-01-19 16:25:54 +00:00
|
|
|
// find the node side on which we are
|
|
|
|
plane = surf->plane;
|
|
|
|
|
|
|
|
dot = PlaneDiff (org, plane);
|
|
|
|
|
|
|
|
// enqueue the polygon
|
|
|
|
if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON))
|
|
|
|
|| (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
|
2021-07-22 06:39:28 +00:00
|
|
|
chain_surface (surf, ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
visit_leaf (mleaf_t *leaf)
|
|
|
|
{
|
|
|
|
// deal with model fragments in this leaf
|
|
|
|
if (leaf->efrags)
|
|
|
|
R_StoreEfrags (leaf->efrags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
get_side (mnode_t *node)
|
|
|
|
{
|
|
|
|
// find the node side on which we are
|
|
|
|
plane_t *plane = node->plane;
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
vec4f_t org = r_refdef.frame.position;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
if (plane->type < 3)
|
2022-03-08 09:41:09 +00:00
|
|
|
return (org[plane->type] - plane->dist) < 0;
|
|
|
|
return (DotProduct (org, plane->normal) - plane->dist) < 0;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2021-02-01 10:31:11 +00:00
|
|
|
visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
msurface_t *surf;
|
|
|
|
|
|
|
|
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
|
|
|
side = (~side + 1) & SURF_PLANEBACK;
|
|
|
|
// draw stuff
|
|
|
|
if ((c = node->numsurfaces)) {
|
2021-02-01 10:31:11 +00:00
|
|
|
surf = brush->surfaces + node->firstsurface;
|
2021-01-19 16:25:54 +00:00
|
|
|
for (; c; c--, surf++) {
|
|
|
|
if (surf->visframe != r_visframecount)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// side is either 0 or SURF_PLANEBACK
|
|
|
|
if (side ^ (surf->flags & SURF_PLANEBACK))
|
|
|
|
continue; // wrong side
|
|
|
|
|
2021-07-22 06:39:28 +00:00
|
|
|
chain_surface (surf, ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
test_node (mnode_t *node)
|
|
|
|
{
|
|
|
|
if (node->contents < 0)
|
|
|
|
return 0;
|
|
|
|
if (node->visframe != r_visframecount)
|
|
|
|
return 0;
|
2022-03-19 03:33:12 +00:00
|
|
|
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
|
2021-01-19 16:25:54 +00:00
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-01 10:31:11 +00:00
|
|
|
R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
typedef struct {
|
|
|
|
mnode_t *node;
|
|
|
|
int side;
|
|
|
|
} rstack_t;
|
|
|
|
rstack_t *node_ptr;
|
|
|
|
rstack_t *node_stack;
|
|
|
|
mnode_t *node;
|
|
|
|
mnode_t *front;
|
|
|
|
int side;
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
node = brush->nodes;
|
2021-01-19 16:25:54 +00:00
|
|
|
// +2 for paranoia
|
2021-02-01 10:31:11 +00:00
|
|
|
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
|
2021-01-19 16:25:54 +00:00
|
|
|
node_ptr = node_stack;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
while (test_node (node)) {
|
|
|
|
side = get_side (node);
|
|
|
|
front = node->children[side];
|
|
|
|
if (test_node (front)) {
|
|
|
|
node_ptr->node = node;
|
|
|
|
node_ptr->side = side;
|
|
|
|
node_ptr++;
|
|
|
|
node = front;
|
|
|
|
continue;
|
|
|
|
}
|
2021-07-22 07:13:12 +00:00
|
|
|
// front is either not a node (ie, is a leaf) or is not visible
|
|
|
|
// if node is visible, then at least one of its child nodes
|
|
|
|
// must also be visible, and a leaf child in front of the node
|
|
|
|
// will be visible, so no need for vis checks on a leaf
|
2021-01-19 16:25:54 +00:00
|
|
|
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
|
|
|
|
visit_leaf ((mleaf_t *) front);
|
2021-02-01 10:31:11 +00:00
|
|
|
visit_node (brush, node, side, ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
node = node->children[!side];
|
|
|
|
}
|
|
|
|
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
|
|
|
visit_leaf ((mleaf_t *) node);
|
|
|
|
if (node_ptr != node_stack) {
|
|
|
|
node_ptr--;
|
|
|
|
node = node_ptr->node;
|
|
|
|
side = node_ptr->side;
|
2021-02-01 10:31:11 +00:00
|
|
|
visit_node (brush, node, side, ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
node = node->children[!side];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-14 02:35:06 +00:00
|
|
|
static void
|
|
|
|
push_transform (vec_t *transform, VkPipelineLayout layout,
|
2021-12-17 06:51:33 +00:00
|
|
|
qfv_device_t *device, VkCommandBuffer cmd)
|
2021-02-14 02:35:06 +00:00
|
|
|
{
|
2021-12-17 06:51:33 +00:00
|
|
|
qfv_push_constants_t push_constants[] = {
|
|
|
|
{ VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
field_offset (bsp_push_constants_t, Model),
|
|
|
|
sizeof (mat4f_t), transform },
|
|
|
|
};
|
|
|
|
QFV_PushConstants (device, cmd, layout, 1, push_constants);
|
2021-02-14 02:35:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-12-17 03:20:32 +00:00
|
|
|
bind_texture (vulktex_t *tex, uint32_t setnum, VkPipelineLayout layout,
|
|
|
|
qfv_devfuncs_t *dfunc, VkCommandBuffer cmd)
|
2021-02-14 02:35:06 +00:00
|
|
|
{
|
2021-12-17 03:20:32 +00:00
|
|
|
VkDescriptorSet sets[] = {
|
|
|
|
tex->descriptor,
|
|
|
|
};
|
|
|
|
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
layout, setnum, 1, sets, 0, 0);
|
2021-02-14 02:35:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-12-17 06:51:33 +00:00
|
|
|
push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout,
|
|
|
|
qfv_device_t *device, VkCommandBuffer cmd)
|
2021-02-14 02:35:06 +00:00
|
|
|
{
|
2021-12-17 06:51:33 +00:00
|
|
|
qfv_push_constants_t push_constants[] = {
|
|
|
|
//{ VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat), mat },
|
|
|
|
{ VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
field_offset (bsp_push_constants_t, fog),
|
|
|
|
sizeof (constants->fog), &constants->fog },
|
|
|
|
{ VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
field_offset (bsp_push_constants_t, time),
|
|
|
|
sizeof (constants->time), &constants->time },
|
|
|
|
};
|
|
|
|
QFV_PushConstants (device, cmd, layout, 2, push_constants);
|
2021-02-14 02:35:06 +00:00
|
|
|
}
|
|
|
|
|
2021-01-20 17:13:40 +00:00
|
|
|
static void
|
2021-12-17 06:51:33 +00:00
|
|
|
draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_device_t *device,
|
2021-01-20 17:13:40 +00:00
|
|
|
VkCommandBuffer cmd)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-12-17 06:51:33 +00:00
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-01-19 16:25:54 +00:00
|
|
|
elements_t *el;
|
|
|
|
|
|
|
|
if (ec->transform) {
|
2021-12-17 06:51:33 +00:00
|
|
|
push_transform (ec->transform, layout, device, cmd);
|
2021-01-21 17:42:58 +00:00
|
|
|
} else {
|
|
|
|
//FIXME should cache current transform
|
2021-12-17 06:51:33 +00:00
|
|
|
push_transform (identity, layout, device, cmd);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
for (el = ec->elements; el; el = el->next) {
|
2021-01-20 17:13:40 +00:00
|
|
|
if (!el->index_count)
|
2021-01-19 16:25:54 +00:00
|
|
|
continue;
|
2021-01-20 17:13:40 +00:00
|
|
|
dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index,
|
|
|
|
0, 0);
|
2021-02-24 10:58:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reset_elechain (elechain_t *ec)
|
|
|
|
{
|
|
|
|
elements_t *el;
|
|
|
|
|
|
|
|
for (el = ec->elements; el; el = el->next) {
|
2021-01-20 17:13:40 +00:00
|
|
|
el->first_index = 0;
|
|
|
|
el->index_count = 0;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-01-20 17:13:40 +00:00
|
|
|
}
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
static void
|
2021-02-19 02:14:54 +00:00
|
|
|
bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
|
2021-12-08 12:11:36 +00:00
|
|
|
VkPipelineLayout layout, qfv_renderframe_t *rFrame)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-01-19 16:25:54 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
2021-02-05 01:22:32 +00:00
|
|
|
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
|
2021-01-19 16:25:54 +00:00
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-02-19 02:14:54 +00:00
|
|
|
VkCommandBuffer cmd = bframe->cmdSet.a[subpass];
|
2021-01-20 17:13:40 +00:00
|
|
|
|
2021-01-20 07:51:35 +00:00
|
|
|
dfunc->vkResetCommandBuffer (cmd, 0);
|
2021-01-19 16:25:54 +00:00
|
|
|
VkCommandBufferInheritanceInfo inherit = {
|
|
|
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
|
2021-12-02 12:58:29 +00:00
|
|
|
rFrame->renderpass->renderpass, subpass_map[subpass],
|
2021-01-19 16:25:54 +00:00
|
|
|
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,
|
|
|
|
};
|
2021-01-20 07:51:35 +00:00
|
|
|
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
|
|
|
|
2021-04-18 11:40:43 +00:00
|
|
|
QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "bsp:%s",
|
|
|
|
bsp_pass_names[subpass]),
|
2021-03-22 23:25:56 +00:00
|
|
|
{0, 0.5, 0.6, 1});
|
|
|
|
|
2021-01-20 07:51:35 +00:00
|
|
|
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
2021-02-14 02:35:06 +00:00
|
|
|
pipeline);
|
2022-04-01 11:34:41 +00:00
|
|
|
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
|
|
|
|
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
|
2021-01-20 07:51:35 +00:00
|
|
|
|
|
|
|
VkDeviceSize offsets[] = { 0 };
|
|
|
|
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets);
|
|
|
|
dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset,
|
|
|
|
VK_INDEX_TYPE_UINT32);
|
|
|
|
|
2021-12-08 15:25:50 +00:00
|
|
|
VkDescriptorSet sets[] = {
|
2021-12-13 01:39:01 +00:00
|
|
|
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
2021-12-08 12:11:36 +00:00
|
|
|
};
|
|
|
|
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
2021-12-17 03:20:32 +00:00
|
|
|
layout, 0, 1, sets, 0, 0);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
//XXX glsl_Fog_GetColor (fog);
|
|
|
|
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-14 02:35:06 +00:00
|
|
|
bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-02-14 02:35:06 +00:00
|
|
|
|
2021-03-22 23:25:56 +00:00
|
|
|
QFV_duCmdEndLabel (device, cmd);
|
2021-02-14 02:35:06 +00:00
|
|
|
dfunc->vkEndCommandBuffer (cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-12-02 12:58:29 +00:00
|
|
|
bsp_begin (qfv_renderframe_t *rFrame)
|
2021-02-14 02:35:06 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-01-19 16:25:54 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
2021-02-14 02:35:06 +00:00
|
|
|
//XXX quat_t fog;
|
|
|
|
|
|
|
|
bctx->default_color[3] = 1;
|
|
|
|
QuatCopy (bctx->default_color, bctx->last_color);
|
|
|
|
|
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
|
|
|
|
2021-12-02 12:58:29 +00:00
|
|
|
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth],
|
2021-02-14 02:35:06 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspDepth]);
|
2021-12-02 12:58:29 +00:00
|
|
|
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer],
|
2021-02-14 02:35:06 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspGBuffer]);
|
|
|
|
|
2021-12-17 03:20:32 +00:00
|
|
|
qfvPushDebug (ctx, "bsp_begin_subpass");
|
2021-12-08 12:11:36 +00:00
|
|
|
bsp_begin_subpass (QFV_bspDepth, bctx->depth, bctx->layout, rFrame);
|
|
|
|
bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, bctx->layout, rFrame);
|
2021-12-17 03:20:32 +00:00
|
|
|
qfvPopDebug (ctx);
|
2021-02-14 02:35:06 +00:00
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-02-14 02:35:06 +00:00
|
|
|
static void
|
|
|
|
bsp_end (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
2021-01-19 16:25:54 +00:00
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-02-14 02:35:06 +00:00
|
|
|
|
|
|
|
bsp_end_subpass (bframe->cmdSet.a[QFV_bspDepth], ctx);
|
|
|
|
bsp_end_subpass (bframe->cmdSet.a[QFV_bspGBuffer], ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 03:24:24 +00:00
|
|
|
static void
|
2021-12-02 12:58:29 +00:00
|
|
|
turb_begin (qfv_renderframe_t *rFrame)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-03-23 03:24:24 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
bctx->default_color[3] = bound (0, r_wateralpha, 1);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-03-23 03:24:24 +00:00
|
|
|
QuatCopy (bctx->default_color, bctx->last_color);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-03-23 03:24:24 +00:00
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-12-02 12:58:29 +00:00
|
|
|
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspTurb]);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-12-17 03:20:32 +00:00
|
|
|
qfvPushDebug (ctx, "bsp_begin_subpass");
|
2021-12-08 12:11:36 +00:00
|
|
|
bsp_begin_subpass (QFV_bspTurb, bctx->turb, bctx->layout, rFrame);
|
2021-12-17 03:20:32 +00:00
|
|
|
qfvPopDebug (ctx);
|
2021-03-23 03:24:24 +00:00
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-03-23 03:24:24 +00:00
|
|
|
static void
|
|
|
|
turb_end (vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-03-23 03:24:24 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-03-23 03:24:24 +00:00
|
|
|
bsp_end_subpass (bframe->cmdSet.a[QFV_bspTurb], ctx);
|
|
|
|
}
|
2022-02-18 04:29:41 +00:00
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
static void
|
2021-12-02 12:58:29 +00:00
|
|
|
sky_begin (qfv_renderframe_t *rFrame)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-01-23 11:42:53 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
bctx->default_color[3] = 1;
|
|
|
|
QuatCopy (bctx->default_color, bctx->last_color);
|
|
|
|
|
2021-01-23 11:42:53 +00:00
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-02-14 02:35:06 +00:00
|
|
|
|
2021-12-02 12:58:29 +00:00
|
|
|
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-12-17 03:20:32 +00:00
|
|
|
qfvPushDebug (ctx, "bsp_begin_subpass");
|
2021-03-25 06:54:34 +00:00
|
|
|
if (bctx->skybox_tex) {
|
2021-12-08 12:11:36 +00:00
|
|
|
bsp_begin_subpass (QFV_bspSky, bctx->skybox, bctx->layout, rFrame);
|
2021-03-25 06:54:34 +00:00
|
|
|
} else {
|
2021-12-08 12:11:36 +00:00
|
|
|
bsp_begin_subpass (QFV_bspSky, bctx->skysheet, bctx->layout, rFrame);
|
2021-03-25 06:54:34 +00:00
|
|
|
}
|
2021-12-17 03:20:32 +00:00
|
|
|
qfvPopDebug (ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-23 11:42:53 +00:00
|
|
|
sky_end (vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-01-23 11:42:53 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-02-14 02:35:06 +00:00
|
|
|
|
2021-03-23 03:24:24 +00:00
|
|
|
bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
add_surf_elements (vulktex_t *tex, instsurf_t *is,
|
2021-01-20 17:13:40 +00:00
|
|
|
elechain_t **ec, elements_t **el,
|
|
|
|
bspctx_t *bctx, bspframe_t *bframe)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-07-22 07:13:12 +00:00
|
|
|
bsppoly_t *poly = (bsppoly_t *) is->surface->polys;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
if (!tex->elechain) {
|
2021-07-19 14:38:09 +00:00
|
|
|
(*ec) = add_elechain (tex, bctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
(*ec)->transform = is->transform;
|
|
|
|
(*ec)->color = is->color;
|
|
|
|
(*el) = (*ec)->elements;
|
2021-01-21 05:37:39 +00:00
|
|
|
(*el)->first_index = bframe->index_count;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
if (is->transform != (*ec)->transform || is->color != (*ec)->color) {
|
2021-07-19 14:38:09 +00:00
|
|
|
(*ec) = add_elechain (tex, bctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
(*ec)->transform = is->transform;
|
|
|
|
(*ec)->color = is->color;
|
|
|
|
(*el) = (*ec)->elements;
|
2021-01-21 05:37:39 +00:00
|
|
|
(*el)->first_index = bframe->index_count;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-01-20 17:13:40 +00:00
|
|
|
memcpy (bframe->index_data + bframe->index_count,
|
|
|
|
poly->indices, poly->count * sizeof (poly->indices[0]));
|
|
|
|
(*el)->index_count += poly->count;
|
2021-01-21 05:37:39 +00:00
|
|
|
bframe->index_count += poly->count;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-20 17:13:40 +00:00
|
|
|
build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
|
|
|
instsurf_t *is;
|
|
|
|
elechain_t *ec = 0;
|
|
|
|
elements_t *el = 0;
|
|
|
|
|
|
|
|
for (is = tex->tex_chain; is; is = is->tex_chain) {
|
2021-12-17 06:52:17 +00:00
|
|
|
// emit the polygon indices for the surface to the texture's
|
2021-07-22 07:13:12 +00:00
|
|
|
// element chain
|
2021-01-20 17:13:40 +00:00
|
|
|
add_surf_elements (tex, is, &ec, &el, bctx, bframe);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-12-02 12:58:29 +00:00
|
|
|
Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-01-20 17:13:40 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-01-19 16:25:54 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
2021-01-20 17:13:40 +00:00
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-01-19 16:25:54 +00:00
|
|
|
entity_t worldent;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
clear_texture_chains (bctx); // do this first for water and skys
|
2021-01-21 05:37:39 +00:00
|
|
|
bframe->index_count = 0;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
memset (&worldent, 0, sizeof (worldent));
|
2022-03-14 06:27:43 +00:00
|
|
|
worldent.renderer.model = r_refdef.worldmodel;
|
|
|
|
brush = &r_refdef.worldmodel->brush;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2022-03-14 06:27:43 +00:00
|
|
|
bctx->entity = &worldent;
|
2021-07-22 06:39:28 +00:00
|
|
|
bctx->transform = 0;
|
|
|
|
bctx->color = 0;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
R_VisitWorldNodes (brush, ctx);
|
2022-04-25 22:26:32 +00:00
|
|
|
if (!bctx->vertex_buffer) {
|
|
|
|
return;
|
|
|
|
}
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
if (r_drawentities) {
|
2022-03-04 16:48:10 +00:00
|
|
|
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
|
|
|
|
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
|
2021-01-19 16:25:54 +00:00
|
|
|
R_DrawBrushModel (ent, ctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 12:58:29 +00:00
|
|
|
bsp_begin (rFrame);
|
2021-01-20 17:13:40 +00:00
|
|
|
|
2021-12-17 06:51:33 +00:00
|
|
|
push_transform (identity, bctx->layout, device,
|
2021-02-14 02:35:06 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspDepth]);
|
2021-12-17 06:51:33 +00:00
|
|
|
push_transform (identity, bctx->layout, device,
|
2021-02-14 02:35:06 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspGBuffer]);
|
2022-03-30 16:26:57 +00:00
|
|
|
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
2021-12-17 06:51:33 +00:00
|
|
|
push_fragconst (&frag_constants, bctx->layout, device,
|
2021-02-14 02:35:06 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspGBuffer]);
|
2021-01-19 16:25:54 +00:00
|
|
|
for (size_t i = 0; i < bctx->texture_chains.size; i++) {
|
|
|
|
vulktex_t *tex;
|
2021-01-20 17:13:40 +00:00
|
|
|
elechain_t *ec = 0;
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
tex = bctx->texture_chains.a[i];
|
|
|
|
|
2021-01-20 17:13:40 +00:00
|
|
|
build_tex_elechain (tex, bctx, bframe);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-12-17 03:20:32 +00:00
|
|
|
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
|
|
bframe->cmdSet.a[QFV_bspGBuffer]);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-01-20 17:13:40 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next) {
|
2021-12-17 06:51:33 +00:00
|
|
|
draw_elechain (ec, bctx->layout, device,
|
2021-02-14 02:35:06 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspDepth]);
|
2021-12-17 06:51:33 +00:00
|
|
|
draw_elechain (ec, bctx->layout, device,
|
2021-02-14 02:35:06 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspGBuffer]);
|
2021-02-24 10:58:31 +00:00
|
|
|
reset_elechain (ec);
|
2021-01-20 17:13:40 +00:00
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
|
|
|
bsp_end (ctx);
|
2021-12-17 06:52:17 +00:00
|
|
|
}
|
2021-01-21 17:20:32 +00:00
|
|
|
|
2021-12-17 06:52:17 +00:00
|
|
|
void
|
|
|
|
Vulkan_Bsp_Flush (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-01-21 17:20:32 +00:00
|
|
|
size_t atom = device->physDev->properties.limits.nonCoherentAtomSize;
|
|
|
|
size_t atom_mask = atom - 1;
|
|
|
|
size_t offset = bframe->index_offset;
|
|
|
|
size_t size = bframe->index_count * sizeof (uint32_t);
|
|
|
|
|
2022-04-25 22:26:32 +00:00
|
|
|
if (!bframe->index_count) {
|
|
|
|
return;
|
|
|
|
}
|
2021-01-21 17:20:32 +00:00
|
|
|
offset &= ~atom_mask;
|
|
|
|
size = (size + atom_mask) & ~atom_mask;
|
|
|
|
|
|
|
|
VkMappedMemoryRange range = {
|
|
|
|
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
|
|
|
bctx->index_memory, offset, size
|
|
|
|
};
|
|
|
|
dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-12-02 12:58:29 +00:00
|
|
|
Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-03-23 03:24:24 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-01-19 16:25:54 +00:00
|
|
|
instsurf_t *is;
|
|
|
|
vulktex_t *tex = 0;
|
|
|
|
elechain_t *ec = 0;
|
|
|
|
elements_t *el = 0;
|
|
|
|
|
|
|
|
if (!bctx->waterchain)
|
|
|
|
return;
|
|
|
|
|
2021-12-02 12:58:29 +00:00
|
|
|
turb_begin (rFrame);
|
2021-12-17 06:51:33 +00:00
|
|
|
push_transform (identity, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspTurb]);
|
2022-03-30 16:26:57 +00:00
|
|
|
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
2021-12-17 06:51:33 +00:00
|
|
|
push_fragconst (&frag_constants, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspTurb]);
|
2021-01-19 16:25:54 +00:00
|
|
|
for (is = bctx->waterchain; is; is = is->tex_chain) {
|
2021-07-22 07:13:12 +00:00
|
|
|
msurface_t *surf = is->surface;
|
2021-03-23 03:24:24 +00:00
|
|
|
if (tex != surf->texinfo->texture->render) {
|
2021-01-19 16:25:54 +00:00
|
|
|
if (tex) {
|
2021-12-17 03:20:32 +00:00
|
|
|
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
|
|
bframe->cmdSet.a[QFV_bspTurb]);
|
2021-03-23 03:24:24 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next) {
|
2021-12-17 06:51:33 +00:00
|
|
|
draw_elechain (ec, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspTurb]);
|
|
|
|
reset_elechain (ec);
|
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
2021-03-23 03:24:24 +00:00
|
|
|
tex = surf->texinfo->texture->render;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-12-17 06:52:17 +00:00
|
|
|
// emit the polygon indices for the surface to the texture's
|
2021-07-22 07:13:12 +00:00
|
|
|
// element chain
|
2021-03-23 03:24:24 +00:00
|
|
|
add_surf_elements (tex, is, &ec, &el, bctx, bframe);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
if (tex) {
|
2021-12-17 03:20:32 +00:00
|
|
|
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
|
|
bframe->cmdSet.a[QFV_bspTurb]);
|
2021-03-23 03:24:24 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next) {
|
2021-12-17 06:51:33 +00:00
|
|
|
draw_elechain (ec, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspTurb]);
|
|
|
|
reset_elechain (ec);
|
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
2021-03-23 03:24:24 +00:00
|
|
|
turb_end (ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
bctx->waterchain = 0;
|
2021-03-23 03:24:24 +00:00
|
|
|
bctx->waterchain_tail = &bctx->waterchain;
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-12-02 12:58:29 +00:00
|
|
|
Vulkan_DrawSky (qfv_renderframe_t *rFrame)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-01-23 11:42:53 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-01-19 16:25:54 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
2021-01-20 17:13:40 +00:00
|
|
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
2021-01-19 16:25:54 +00:00
|
|
|
instsurf_t *is;
|
|
|
|
vulktex_t *tex = 0;
|
|
|
|
elechain_t *ec = 0;
|
|
|
|
elements_t *el = 0;
|
|
|
|
|
|
|
|
if (!bctx->sky_chain)
|
|
|
|
return;
|
|
|
|
|
2021-12-02 12:58:29 +00:00
|
|
|
sky_begin (rFrame);
|
2021-12-17 03:20:32 +00:00
|
|
|
vulktex_t skybox = { .descriptor = bctx->skybox_descriptor };
|
|
|
|
bind_texture (&skybox, 2, bctx->layout, dfunc,
|
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2021-12-17 06:51:33 +00:00
|
|
|
push_transform (identity, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2022-03-30 16:26:57 +00:00
|
|
|
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
2021-12-17 06:51:33 +00:00
|
|
|
push_fragconst (&frag_constants, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2021-01-19 16:25:54 +00:00
|
|
|
for (is = bctx->sky_chain; is; is = is->tex_chain) {
|
2021-07-22 07:13:12 +00:00
|
|
|
msurface_t *surf = is->surface;
|
2021-01-19 16:25:54 +00:00
|
|
|
if (tex != surf->texinfo->texture->render) {
|
|
|
|
if (tex) {
|
2021-12-17 03:20:32 +00:00
|
|
|
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2021-01-23 11:42:53 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next) {
|
2021-12-17 06:51:33 +00:00
|
|
|
draw_elechain (ec, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2021-02-24 10:58:31 +00:00
|
|
|
reset_elechain (ec);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
|
|
|
tex = surf->texinfo->texture->render;
|
|
|
|
}
|
2021-12-17 06:52:17 +00:00
|
|
|
// emit the polygon indices for the surface to the texture's
|
2021-07-22 07:13:12 +00:00
|
|
|
// element chain
|
2021-01-20 17:13:40 +00:00
|
|
|
add_surf_elements (tex, is, &ec, &el, bctx, bframe);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
if (tex) {
|
2021-12-17 03:20:32 +00:00
|
|
|
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2021-01-23 11:42:53 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next) {
|
2021-12-17 06:51:33 +00:00
|
|
|
draw_elechain (ec, bctx->layout, device,
|
2021-03-23 03:24:24 +00:00
|
|
|
bframe->cmdSet.a[QFV_bspSky]);
|
2021-02-24 10:58:31 +00:00
|
|
|
reset_elechain (ec);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
2021-01-23 11:42:53 +00:00
|
|
|
sky_end (ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
bctx->sky_chain = 0;
|
|
|
|
bctx->sky_chain_tail = &bctx->sky_chain;
|
|
|
|
}
|
|
|
|
|
2021-01-23 11:42:53 +00:00
|
|
|
static void
|
|
|
|
create_default_skys (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
VkImage skybox;
|
|
|
|
VkImage skysheet;
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
VkImageView boxview;
|
|
|
|
VkImageView sheetview;
|
|
|
|
|
|
|
|
bctx->default_skybox = calloc (2, sizeof (qfv_tex_t));
|
|
|
|
bctx->default_skysheet = bctx->default_skybox + 1;
|
|
|
|
|
|
|
|
VkExtent3D extents = { 1, 1, 1 };
|
|
|
|
skybox = QFV_CreateImage (device, 1, VK_IMAGE_TYPE_2D,
|
|
|
|
VK_FORMAT_B8G8R8A8_UNORM, extents, 1, 1,
|
|
|
|
VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT
|
|
|
|
| VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, skybox,
|
|
|
|
"bsp:image:default_skybox");
|
2021-01-23 11:42:53 +00:00
|
|
|
|
|
|
|
skysheet = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D,
|
|
|
|
VK_FORMAT_B8G8R8A8_UNORM, extents, 1, 2,
|
|
|
|
VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT
|
|
|
|
| VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, skysheet,
|
|
|
|
"bsp:image:default_skysheet");
|
|
|
|
|
2021-01-23 11:42:53 +00:00
|
|
|
VkMemoryRequirements requirements;
|
|
|
|
dfunc->vkGetImageMemoryRequirements (device->dev, skybox, &requirements);
|
|
|
|
size_t boxsize = requirements.size;
|
|
|
|
dfunc->vkGetImageMemoryRequirements (device->dev, skysheet, &requirements);
|
|
|
|
size_t sheetsize = requirements.size;
|
|
|
|
|
|
|
|
memory = QFV_AllocImageMemory (device, skybox,
|
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
boxsize + sheetsize,
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_IMAGE_USAGE_SAMPLED_BIT);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, memory,
|
|
|
|
"bsp:memory:default_skys");
|
2021-01-23 11:42:53 +00:00
|
|
|
|
|
|
|
QFV_BindImageMemory (device, skybox, memory, 0);
|
|
|
|
QFV_BindImageMemory (device, skysheet, memory, boxsize);
|
|
|
|
|
|
|
|
boxview = QFV_CreateImageView (device, skybox, VK_IMAGE_VIEW_TYPE_CUBE,
|
|
|
|
VK_FORMAT_B8G8R8A8_UNORM,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, boxview,
|
2021-03-25 06:54:34 +00:00
|
|
|
"bsp:iview:default_skybox");
|
2021-01-23 11:42:53 +00:00
|
|
|
|
|
|
|
sheetview = QFV_CreateImageView (device, skysheet,
|
|
|
|
VK_IMAGE_VIEW_TYPE_2D_ARRAY,
|
|
|
|
VK_FORMAT_B8G8R8A8_UNORM,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
2021-01-31 10:58:55 +00:00
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, sheetview,
|
|
|
|
"bsp:iview:default_skysheet");
|
2021-01-23 11:42:53 +00:00
|
|
|
|
|
|
|
bctx->default_skybox->image = skybox;
|
|
|
|
bctx->default_skybox->view = boxview;
|
|
|
|
bctx->default_skybox->memory = memory;
|
|
|
|
bctx->default_skysheet->image = skysheet;
|
|
|
|
bctx->default_skysheet->view = sheetview;
|
|
|
|
|
|
|
|
// temporarily commandeer the light map's staging buffer
|
|
|
|
qfv_packet_t *packet = QFV_PacketAcquire (bctx->light_stage);
|
2021-04-24 03:42:29 +00:00
|
|
|
|
|
|
|
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
|
|
|
|
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
|
|
|
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
|
VkImageMemoryBarrier barriers[2] = { ib.barrier, ib.barrier };
|
2021-01-23 11:42:53 +00:00
|
|
|
barriers[0].image = skybox;
|
|
|
|
barriers[1].image = skysheet;
|
2021-04-24 03:42:29 +00:00
|
|
|
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
|
2021-01-23 11:42:53 +00:00
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
2, barriers);
|
|
|
|
|
|
|
|
VkClearColorValue color = {};
|
|
|
|
VkImageSubresourceRange range = {
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0, VK_REMAINING_MIP_LEVELS,
|
|
|
|
0, VK_REMAINING_ARRAY_LAYERS
|
|
|
|
};
|
|
|
|
dfunc->vkCmdClearColorImage (packet->cmd, skybox,
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
&color, 1, &range);
|
|
|
|
dfunc->vkCmdClearColorImage (packet->cmd, skysheet,
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
&color, 1, &range);
|
|
|
|
|
2021-04-24 03:42:29 +00:00
|
|
|
ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
|
|
|
|
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
|
|
|
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
|
barriers[0] = ib.barrier;
|
|
|
|
barriers[1] = ib.barrier;
|
2021-01-23 11:42:53 +00:00
|
|
|
barriers[0].image = skybox;
|
|
|
|
barriers[1].image = skysheet;
|
2021-04-24 03:42:29 +00:00
|
|
|
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
|
2021-01-23 11:42:53 +00:00
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
2, barriers);
|
|
|
|
QFV_PacketSubmit (packet);
|
|
|
|
}
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
void
|
|
|
|
Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
|
2022-05-05 12:22:44 +00:00
|
|
|
r_notexture_mip->render = &vulkan_notexture;
|
|
|
|
|
2021-12-02 13:48:50 +00:00
|
|
|
qfvPushDebug (ctx, "bsp init");
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
bspctx_t *bctx = calloc (1, sizeof (bspctx_t));
|
|
|
|
ctx->bsp_context = bctx;
|
|
|
|
|
|
|
|
bctx->waterchain_tail = &bctx->waterchain;
|
|
|
|
bctx->sky_chain_tail = &bctx->sky_chain;
|
|
|
|
bctx->static_instsurfs_tail = &bctx->static_instsurfs;
|
|
|
|
bctx->elechains_tail = &bctx->elechains;
|
|
|
|
bctx->elementss_tail = &bctx->elementss;
|
|
|
|
bctx->instsurfs_tail = &bctx->instsurfs;
|
|
|
|
|
2021-01-31 10:58:55 +00:00
|
|
|
bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048,
|
|
|
|
tex_frgba, ctx->staging);
|
2021-01-19 16:25:54 +00:00
|
|
|
size_t size = QFV_ScrapSize (bctx->light_scrap);
|
2021-01-31 10:58:55 +00:00
|
|
|
bctx->light_stage = QFV_CreateStagingBuffer (device, "lightmap", size,
|
|
|
|
ctx->cmdpool);
|
2021-01-19 16:25:54 +00:00
|
|
|
|
2021-01-23 11:42:53 +00:00
|
|
|
create_default_skys (ctx);
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
DARRAY_INIT (&bctx->texture_chains, 64);
|
|
|
|
|
2021-02-05 01:22:32 +00:00
|
|
|
size_t frames = ctx->frames.size;
|
2021-01-19 16:25:54 +00:00
|
|
|
DARRAY_INIT (&bctx->frames, frames);
|
|
|
|
DARRAY_RESIZE (&bctx->frames, frames);
|
|
|
|
bctx->frames.grow = 0;
|
|
|
|
|
2021-12-16 14:00:17 +00:00
|
|
|
bctx->depth = Vulkan_CreateGraphicsPipeline (ctx, "bsp_depth");
|
|
|
|
bctx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "bsp_gbuf");
|
|
|
|
bctx->skybox = Vulkan_CreateGraphicsPipeline (ctx, "bsp_skybox");
|
|
|
|
bctx->skysheet = Vulkan_CreateGraphicsPipeline (ctx, "bsp_skysheet");
|
|
|
|
bctx->turb = Vulkan_CreateGraphicsPipeline (ctx, "bsp_turb");
|
2021-02-04 08:03:49 +00:00
|
|
|
bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout");
|
|
|
|
bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler");
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
for (size_t i = 0; i < frames; i++) {
|
|
|
|
__auto_type bframe = &bctx->frames.a[i];
|
2021-02-14 02:35:06 +00:00
|
|
|
|
|
|
|
DARRAY_INIT (&bframe->cmdSet, QFV_bspNumPasses);
|
|
|
|
DARRAY_RESIZE (&bframe->cmdSet, QFV_bspNumPasses);
|
|
|
|
bframe->cmdSet.grow = 0;
|
|
|
|
|
|
|
|
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &bframe->cmdSet);
|
|
|
|
|
|
|
|
for (int j = 0; j < QFV_bspNumPasses; j++) {
|
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
|
|
|
bframe->cmdSet.a[i],
|
|
|
|
va (ctx->va_ctx, "cmd:bsp:%zd:%s", i,
|
|
|
|
bsp_pass_names[j]));
|
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-12-17 03:20:32 +00:00
|
|
|
|
|
|
|
bctx->skybox_descriptor
|
|
|
|
= Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox,
|
|
|
|
bctx->sampler);
|
|
|
|
|
2021-12-02 13:48:50 +00:00
|
|
|
qfvPopDebug (ctx);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
|
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
|
2021-02-14 02:35:06 +00:00
|
|
|
for (size_t i = 0; i < bctx->frames.size; i++) {
|
|
|
|
__auto_type bframe = &bctx->frames.a[i];
|
|
|
|
free (bframe->cmdSet.a);
|
|
|
|
}
|
|
|
|
|
2021-02-19 02:14:54 +00:00
|
|
|
dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0);
|
|
|
|
dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0);
|
2021-03-25 06:54:34 +00:00
|
|
|
dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0);
|
|
|
|
dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0);
|
2021-03-23 03:24:24 +00:00
|
|
|
dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0);
|
2021-01-19 16:25:54 +00:00
|
|
|
DARRAY_CLEAR (&bctx->texture_chains);
|
|
|
|
DARRAY_CLEAR (&bctx->frames);
|
|
|
|
QFV_DestroyStagingBuffer (bctx->light_stage);
|
|
|
|
QFV_DestroyScrap (bctx->light_scrap);
|
2021-01-20 07:28:04 +00:00
|
|
|
if (bctx->vertex_buffer) {
|
|
|
|
dfunc->vkDestroyBuffer (device->dev, bctx->vertex_buffer, 0);
|
|
|
|
dfunc->vkFreeMemory (device->dev, bctx->vertex_memory, 0);
|
|
|
|
}
|
|
|
|
if (bctx->index_buffer) {
|
|
|
|
dfunc->vkDestroyBuffer (device->dev, bctx->index_buffer, 0);
|
|
|
|
dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0);
|
|
|
|
}
|
2021-01-23 11:42:53 +00:00
|
|
|
|
2021-03-25 06:54:34 +00:00
|
|
|
if (bctx->skybox_tex) {
|
|
|
|
Vulkan_UnloadTex (ctx, bctx->skybox_tex);
|
|
|
|
}
|
|
|
|
|
2021-01-23 11:42:53 +00:00
|
|
|
dfunc->vkDestroyImageView (device->dev, bctx->default_skysheet->view, 0);
|
|
|
|
dfunc->vkDestroyImage (device->dev, bctx->default_skysheet->image, 0);
|
|
|
|
|
|
|
|
dfunc->vkDestroyImageView (device->dev, bctx->default_skybox->view, 0);
|
|
|
|
dfunc->vkDestroyImage (device->dev, bctx->default_skybox->image, 0);
|
|
|
|
dfunc->vkFreeMemory (device->dev, bctx->default_skybox->memory, 0);
|
|
|
|
free (bctx->default_skybox);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 06:54:34 +00:00
|
|
|
void
|
|
|
|
Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx)
|
2021-01-19 16:25:54 +00:00
|
|
|
{
|
2021-03-25 06:54:34 +00:00
|
|
|
bspctx_t *bctx = ctx->bsp_context;
|
|
|
|
|
|
|
|
const char *name;
|
2021-01-19 16:25:54 +00:00
|
|
|
int i;
|
|
|
|
tex_t *tex;
|
|
|
|
static const char *sky_suffix[] = { "ft", "bk", "up", "dn", "rt", "lf"};
|
|
|
|
|
2021-03-25 06:54:34 +00:00
|
|
|
if (bctx->skybox_tex) {
|
|
|
|
Vulkan_UnloadTex (ctx, bctx->skybox_tex);
|
2021-12-17 03:20:32 +00:00
|
|
|
Vulkan_FreeTexture (ctx, bctx->skybox_descriptor);
|
2021-03-25 06:54:34 +00:00
|
|
|
}
|
|
|
|
bctx->skybox_tex = 0;
|
|
|
|
|
|
|
|
if (!sky || !*sky) {
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
sky = r_skyname;
|
2021-03-25 06:54:34 +00:00
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
|
|
|
|
if (!*sky || !strcasecmp (sky, "none")) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_vulkan, "Skybox unloaded\n");
|
2021-12-17 03:20:32 +00:00
|
|
|
bctx->skybox_descriptor
|
|
|
|
= Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox,
|
|
|
|
bctx->sampler);
|
2021-01-19 16:25:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-25 06:54:34 +00:00
|
|
|
name = va (ctx->va_ctx, "env/%s_map", sky);
|
|
|
|
tex = LoadImage (name, 1);
|
|
|
|
if (tex) {
|
|
|
|
bctx->skybox_tex = Vulkan_LoadEnvMap (ctx, tex, sky);
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_vulkan, "Loaded %s\n", name);
|
2021-01-19 16:25:54 +00:00
|
|
|
} else {
|
2021-03-25 06:54:34 +00:00
|
|
|
int failed = 0;
|
|
|
|
tex_t *sides[6] = { };
|
|
|
|
|
2021-01-19 16:25:54 +00:00
|
|
|
for (i = 0; i < 6; i++) {
|
2021-03-25 06:54:34 +00:00
|
|
|
name = va (ctx->va_ctx, "env/%s%s", sky, sky_suffix[i]);
|
|
|
|
tex = LoadImage (name, 1);
|
|
|
|
if (!tex) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_vulkan, "Couldn't load %s\n", name);
|
2021-01-19 16:25:54 +00:00
|
|
|
// also look in gfx/env, where Darkplaces looks for skies
|
2021-03-25 06:54:34 +00:00
|
|
|
name = va (ctx->va_ctx, "gfx/env/%s%s", sky, sky_suffix[i]);
|
|
|
|
tex = LoadImage (name, 1);
|
|
|
|
if (!tex) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_vulkan, "Couldn't load %s\n", name);
|
2021-03-25 06:54:34 +00:00
|
|
|
failed = 1;
|
2021-01-19 16:25:54 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2021-04-24 23:38:48 +00:00
|
|
|
//FIXME find a better way (also, assumes data and struct together)
|
|
|
|
sides[i] = malloc (ImageSize (tex, 1));
|
|
|
|
memcpy (sides[i], tex, ImageSize (tex, 1));
|
|
|
|
sides[i]->data = (byte *)(sides[i] + 1);
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_vulkan, "Loaded %s\n", name);
|
2021-03-25 06:54:34 +00:00
|
|
|
}
|
|
|
|
if (!failed) {
|
|
|
|
bctx->skybox_tex = Vulkan_LoadEnvSides (ctx, sides, sky);
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-04-24 23:38:48 +00:00
|
|
|
for (i = 0; i < 6; i++) {
|
|
|
|
free (sides[i]);
|
|
|
|
}
|
2021-01-19 16:25:54 +00:00
|
|
|
}
|
2021-03-25 06:54:34 +00:00
|
|
|
if (bctx->skybox_tex) {
|
2021-12-17 03:20:32 +00:00
|
|
|
bctx->skybox_descriptor
|
2022-02-17 16:17:25 +00:00
|
|
|
= Vulkan_CreateTextureDescriptor (ctx, bctx->skybox_tex,
|
2021-12-17 03:20:32 +00:00
|
|
|
bctx->sampler);
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_vulkan, "Skybox %s loaded\n", sky);
|
2021-03-25 06:54:34 +00:00
|
|
|
}
|
|
|
|
}
|