mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
[vulkan] Implement thread-safe rendering for the world model
Sub-models and instance models need an instance data buffer, but this gets the basics working (and the proof of concept). Using arrays like this actually simplified a lot of the code, and will make it easy to get transparency without turbulence (just another queue).
This commit is contained in:
parent
c6f520b743
commit
3a2560e4c1
3 changed files with 269 additions and 405 deletions
|
@ -39,30 +39,81 @@
|
||||||
|
|
||||||
#include "QF/simd/types.h"
|
#include "QF/simd/types.h"
|
||||||
|
|
||||||
|
typedef struct bsp_face_s {
|
||||||
|
uint32_t first_index;
|
||||||
|
uint32_t index_count;
|
||||||
|
uint32_t tex_id;
|
||||||
|
uint32_t flags;
|
||||||
|
} bsp_face_t;
|
||||||
|
|
||||||
|
typedef struct bsp_packet_s {
|
||||||
|
int first_index;
|
||||||
|
int index_count;
|
||||||
|
int transform_id;
|
||||||
|
int color_id;
|
||||||
|
} bsp_packet_t;
|
||||||
|
|
||||||
|
typedef struct bsp_packetset_s
|
||||||
|
DARRAY_TYPE (bsp_packet_t) bsp_packetset_t;
|
||||||
|
|
||||||
|
typedef struct bsp_indexset_s
|
||||||
|
DARRAY_TYPE (uint32_t) bsp_indexset_t;
|
||||||
|
|
||||||
|
typedef struct bsp_tex_s {
|
||||||
|
VkDescriptorSet descriptors;
|
||||||
|
bsp_packetset_t packets;
|
||||||
|
bsp_indexset_t indices;
|
||||||
|
} bsp_tex_t;
|
||||||
|
|
||||||
typedef struct vulktex_s {
|
typedef struct vulktex_s {
|
||||||
struct texture_s *texture;
|
|
||||||
struct instsurf_s *tex_chain; // for gl_texsort drawing
|
|
||||||
struct instsurf_s **tex_chain_tail;
|
|
||||||
struct elechain_s *elechain;
|
|
||||||
struct elechain_s **elechain_tail;
|
|
||||||
struct qfv_tex_s *tex;
|
struct qfv_tex_s *tex;
|
||||||
VkDescriptorSet descriptor;
|
VkDescriptorSet descriptor;
|
||||||
|
int tex_id;
|
||||||
} vulktex_t;
|
} vulktex_t;
|
||||||
|
|
||||||
|
typedef struct regtexset_s
|
||||||
|
DARRAY_TYPE (vulktex_t *) regtexset_t;
|
||||||
|
|
||||||
|
typedef struct bsp_texset_s
|
||||||
|
DARRAY_TYPE (bsp_tex_t) bsp_texset_t;
|
||||||
|
|
||||||
|
typedef struct bsp_draw_s {
|
||||||
|
uint32_t tex_id;
|
||||||
|
uint32_t index_count;
|
||||||
|
uint32_t instance_count;
|
||||||
|
uint32_t first_index;
|
||||||
|
uint32_t first_instance;
|
||||||
|
} bsp_draw_t;
|
||||||
|
|
||||||
|
typedef struct bsp_drawset_s
|
||||||
|
DARRAY_TYPE (bsp_draw_t) bsp_drawset_t;
|
||||||
|
|
||||||
|
typedef struct instface_s {
|
||||||
|
uint32_t inst_id;
|
||||||
|
uint32_t face;
|
||||||
|
} instface_t;
|
||||||
|
|
||||||
|
typedef struct bsp_instfaceset_s
|
||||||
|
DARRAY_TYPE (instface_t) bsp_instfaceset_t;
|
||||||
|
|
||||||
|
typedef struct bsp_pass_s {
|
||||||
|
uint32_t *indices; // points into index buffer
|
||||||
|
uint32_t index_count; // number of indices written to buffer
|
||||||
|
int vis_frame;
|
||||||
|
int *face_frames;
|
||||||
|
int *leaf_frames;
|
||||||
|
int *node_frames;
|
||||||
|
bsp_instfaceset_t *face_queue;
|
||||||
|
regtexset_t *textures;
|
||||||
|
int num_queues;
|
||||||
|
bsp_drawset_t *draw_queues;
|
||||||
|
} bsp_pass_t;
|
||||||
|
|
||||||
typedef struct bspvert_s {
|
typedef struct bspvert_s {
|
||||||
quat_t vertex;
|
quat_t vertex;
|
||||||
quat_t tlst;
|
quat_t tlst;
|
||||||
} bspvert_t;
|
} bspvert_t;
|
||||||
|
|
||||||
typedef struct elechain_s {
|
|
||||||
struct elechain_s *_next;
|
|
||||||
struct elechain_s *next;
|
|
||||||
uint32_t first_index;
|
|
||||||
uint32_t index_count;
|
|
||||||
vec_t *transform;
|
|
||||||
float *color;
|
|
||||||
} elechain_t;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
qfv_bsp_texture,
|
qfv_bsp_texture,
|
||||||
qfv_bsp_glowmap,
|
qfv_bsp_glowmap,
|
||||||
|
@ -90,33 +141,13 @@ typedef struct bspframe_s {
|
||||||
typedef struct bspframeset_s
|
typedef struct bspframeset_s
|
||||||
DARRAY_TYPE (bspframe_t) bspframeset_t;
|
DARRAY_TYPE (bspframe_t) bspframeset_t;
|
||||||
|
|
||||||
typedef struct texchainset_s
|
|
||||||
DARRAY_TYPE (vulktex_t *) texchainset_t;
|
|
||||||
|
|
||||||
typedef struct bspctx_s {
|
typedef struct bspctx_s {
|
||||||
struct entity_s *entity;
|
struct entity_s *entity;
|
||||||
vec_t *transform;
|
vec_t *transform;
|
||||||
float *color;
|
float *color;
|
||||||
|
uint32_t inst_id;
|
||||||
|
|
||||||
instsurf_t *waterchain;
|
regtexset_t registered_textures;
|
||||||
instsurf_t **waterchain_tail;
|
|
||||||
instsurf_t *sky_chain;
|
|
||||||
instsurf_t **sky_chain_tail;
|
|
||||||
|
|
||||||
texchainset_t texture_chains;
|
|
||||||
|
|
||||||
// for world and non-instance models
|
|
||||||
instsurf_t *static_instsurfs;
|
|
||||||
instsurf_t **static_instsurfs_tail;
|
|
||||||
instsurf_t *free_static_instsurfs;
|
|
||||||
|
|
||||||
// for instance models
|
|
||||||
elechain_t *elechains;
|
|
||||||
elechain_t **elechains_tail;
|
|
||||||
elechain_t *free_elechains;
|
|
||||||
instsurf_t *instsurfs;
|
|
||||||
instsurf_t **instsurfs_tail;
|
|
||||||
instsurf_t *free_instsurfs;
|
|
||||||
|
|
||||||
struct qfv_tex_s *default_skysheet;
|
struct qfv_tex_s *default_skysheet;
|
||||||
struct qfv_tex_s *skysheet_tex;
|
struct qfv_tex_s *skysheet_tex;
|
||||||
|
@ -131,7 +162,10 @@ typedef struct bspctx_s {
|
||||||
struct scrap_s *light_scrap;
|
struct scrap_s *light_scrap;
|
||||||
struct qfv_stagebuf_s *light_stage;
|
struct qfv_stagebuf_s *light_stage;
|
||||||
|
|
||||||
struct bsppoly_s *polys;
|
bsp_face_t *faces;
|
||||||
|
uint32_t *poly_indices;
|
||||||
|
|
||||||
|
bsp_pass_t main_pass; // camera view depth, gbuffer, etc
|
||||||
|
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
VkPipelineLayout layout;
|
VkPipelineLayout layout;
|
||||||
|
|
|
@ -307,7 +307,6 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
vulktex_t *tex = tx->render;
|
vulktex_t *tex = tx->render;
|
||||||
tex->texture = tx;
|
|
||||||
tex->tex = (qfv_tex_t *) (tex + 1);
|
tex->tex = (qfv_tex_t *) (tex + 1);
|
||||||
VkExtent3D extent = { tx->width, tx->height, 1 };
|
VkExtent3D extent = { tx->width, tx->height, 1 };
|
||||||
|
|
||||||
|
|
|
@ -105,67 +105,6 @@ static vulktex_t vulkan_notexture = { };
|
||||||
|
|
||||||
#define ALLOC_CHUNK 64
|
#define ALLOC_CHUNK 64
|
||||||
|
|
||||||
typedef struct bsppoly_s {
|
|
||||||
uint32_t count;
|
|
||||||
uint32_t indices[1];
|
|
||||||
} bsppoly_t;
|
|
||||||
|
|
||||||
#define CHAIN_SURF_F2B(surf,chain) \
|
|
||||||
({ \
|
|
||||||
instsurf_t *inst = (surf)->instsurf; \
|
|
||||||
if (__builtin_expect(!inst, 1)) \
|
|
||||||
inst = get_instsurf (bctx); \
|
|
||||||
inst->surface = (surf); \
|
|
||||||
*(chain##_tail) = inst; \
|
|
||||||
(chain##_tail) = &inst->tex_chain; \
|
|
||||||
*(chain##_tail) = 0; \
|
|
||||||
inst; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define CHAIN_SURF_B2F(surf,chain) \
|
|
||||||
({ \
|
|
||||||
instsurf_t *inst = (surf)->instsurf; \
|
|
||||||
if (__builtin_expect(!inst, 1)) \
|
|
||||||
inst = get_instsurf (bctx); \
|
|
||||||
inst->surface = (surf); \
|
|
||||||
inst->tex_chain = (chain); \
|
|
||||||
(chain) = inst; \
|
|
||||||
inst; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#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 (instsurf_t, static_instsurf)
|
|
||||||
GET_RELEASE (instsurf_t, instsurf)
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_texture (texture_t *tx, vulkan_ctx_t *ctx)
|
add_texture (texture_t *tx, vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
|
@ -173,83 +112,25 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx)
|
||||||
|
|
||||||
vulktex_t *tex = tx->render;
|
vulktex_t *tex = tx->render;
|
||||||
if (tex->tex) {
|
if (tex->tex) {
|
||||||
DARRAY_APPEND (&bctx->texture_chains, tex);
|
tex->tex_id = bctx->registered_textures.size;
|
||||||
|
DARRAY_APPEND (&bctx->registered_textures, tex);
|
||||||
tex->descriptor = Vulkan_CreateTextureDescriptor (ctx, tex->tex,
|
tex->descriptor = Vulkan_CreateTextureDescriptor (ctx, tex->tex,
|
||||||
bctx->sampler);
|
bctx->sampler);
|
||||||
}
|
}
|
||||||
tex->tex_chain = 0;
|
|
||||||
tex->tex_chain_tail = &tex->tex_chain;
|
|
||||||
tex->elechain = 0;
|
|
||||||
tex->elechain_tail = &tex->elechain;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_surface_chains (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
bspctx_t *bctx = ctx->bsp_context;
|
|
||||||
|
|
||||||
release_static_instsurfs (bctx);
|
|
||||||
release_instsurfs (bctx);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < brush->nummodelsurfaces; i++) {
|
|
||||||
brush->surfaces[i].instsurf = get_static_instsurf (bctx);
|
|
||||||
brush->surfaces[i].instsurf->surface = &brush->surfaces[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_instsurfs (bctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Vulkan_ClearElements (vulkan_ctx_t *ctx)
|
Vulkan_ClearElements (vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
bspctx_t *bctx = ctx->bsp_context;
|
// bspctx_t *bctx = ctx->bsp_context;
|
||||||
release_elechains (bctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
chain_surface (msurface_t *surf, vulkan_ctx_t *ctx)
|
chain_surface (const bsp_face_t *face, bsp_pass_t *pass, bspctx_t *bctx)
|
||||||
{
|
{
|
||||||
bspctx_t *bctx = ctx->bsp_context;
|
|
||||||
instsurf_t *is;
|
|
||||||
|
|
||||||
if (surf->flags & SURF_DRAWSKY) {
|
DARRAY_APPEND (&pass->face_queue[face->tex_id],
|
||||||
is = CHAIN_SURF_F2B (surf, bctx->sky_chain);
|
((instface_t) { bctx->inst_id, face - bctx->faces }));
|
||||||
} else if ((surf->flags & SURF_DRAWTURB)
|
|
||||||
|| (bctx->color && bctx->color[3] < 1.0)) {
|
|
||||||
is = CHAIN_SURF_B2F (surf, bctx->waterchain);
|
|
||||||
} else {
|
|
||||||
texture_t *tx;
|
|
||||||
vulktex_t *tex;
|
|
||||||
|
|
||||||
if (!surf->texinfo->texture->anim_total)
|
|
||||||
tx = surf->texinfo->texture;
|
|
||||||
else
|
|
||||||
tx = R_TextureAnimation (bctx->entity, surf);
|
|
||||||
tex = tx->render;
|
|
||||||
is = CHAIN_SURF_F2B (surf, tex->tex_chain);
|
|
||||||
}
|
|
||||||
is->transform = bctx->transform;
|
|
||||||
is->color = bctx->color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -269,7 +150,16 @@ static void
|
||||||
clear_textures (vulkan_ctx_t *ctx)
|
clear_textures (vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
bspctx_t *bctx = ctx->bsp_context;
|
bspctx_t *bctx = ctx->bsp_context;
|
||||||
bctx->texture_chains.size = 0;
|
|
||||||
|
if (bctx->main_pass.face_queue) {
|
||||||
|
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||||
|
DARRAY_CLEAR (&bctx->main_pass.face_queue[i]);
|
||||||
|
}
|
||||||
|
free (bctx->main_pass.face_queue);
|
||||||
|
bctx->main_pass.face_queue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bctx->registered_textures.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -280,7 +170,6 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
||||||
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
||||||
|
|
||||||
clear_textures (ctx);
|
clear_textures (ctx);
|
||||||
init_surface_chains (brush, ctx);
|
|
||||||
add_texture (r_notexture_mip, ctx);
|
add_texture (r_notexture_mip, ctx);
|
||||||
register_textures (brush, ctx);
|
register_textures (brush, ctx);
|
||||||
for (i = 0; i < num_models; i++) {
|
for (i = 0; i < num_models; i++) {
|
||||||
|
@ -297,60 +186,67 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
||||||
brush->numsubmodels = 1; // no support for submodels in non-world model
|
brush->numsubmodels = 1; // no support for submodels in non-world model
|
||||||
register_textures (brush, ctx);
|
register_textures (brush, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bspctx_t *bctx = ctx->bsp_context;
|
||||||
|
int num_tex = bctx->registered_textures.size;
|
||||||
|
bctx->main_pass.face_queue = malloc (num_tex * sizeof (bsp_instfaceset_t));
|
||||||
|
for (int i = 0; i < num_tex; i++) {
|
||||||
|
bctx->main_pass.face_queue[i]
|
||||||
|
= (bsp_instfaceset_t) DARRAY_STATIC_INIT (128);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static elechain_t *
|
typedef struct {
|
||||||
add_elechain (vulktex_t *tex, bspctx_t *bctx)
|
msurface_t *face;
|
||||||
{
|
model_t *model;
|
||||||
elechain_t *ec;
|
int model_face_base;
|
||||||
|
} faceref_t;
|
||||||
|
|
||||||
ec = get_elechain (bctx);
|
typedef struct DARRAY_TYPE (faceref_t) facerefset_t;
|
||||||
ec->first_index = 0;
|
|
||||||
ec->index_count = 0;
|
|
||||||
ec->transform = 0;
|
|
||||||
ec->color = 0;
|
|
||||||
*tex->elechain_tail = ec;
|
|
||||||
tex->elechain_tail = &ec->next;
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
count_verts_inds (model_t **models, msurface_t *surf,
|
count_verts_inds (faceref_t *faceref, uint32_t *verts, uint32_t *inds)
|
||||||
uint32_t *verts, uint32_t *inds)
|
|
||||||
{
|
{
|
||||||
|
msurface_t *surf = faceref->face;
|
||||||
*verts = surf->numedges;
|
*verts = surf->numedges;
|
||||||
*inds = surf->numedges + 1;
|
*inds = surf->numedges + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bsppoly_t *
|
typedef struct {
|
||||||
build_surf_displist (model_t **models, msurface_t *surf, int base,
|
bsp_face_t *faces;
|
||||||
bspvert_t **vert_list)
|
uint32_t *indices;
|
||||||
|
bspvert_t *vertices;
|
||||||
|
uint32_t index_base;
|
||||||
|
uint32_t vertex_base;
|
||||||
|
int tex_id;
|
||||||
|
} buildctx_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
build_surf_displist (faceref_t *faceref, buildctx_t *build)
|
||||||
{
|
{
|
||||||
mod_brush_t *brush;
|
msurface_t *surf = faceref->face;
|
||||||
if (surf->model_index < 0) {
|
mod_brush_t *brush = &faceref->model->brush;;
|
||||||
// instance model
|
|
||||||
brush = &models[~surf->model_index]->brush;
|
int facenum = surf - brush->surfaces;
|
||||||
} else {
|
bsp_face_t *face = &build->faces[facenum + faceref->model_face_base];
|
||||||
// main or sub model
|
// create a triangle fan
|
||||||
brush = &r_refdef.worldmodel->brush;
|
int numverts = surf->numedges;
|
||||||
|
face->first_index = build->index_base;
|
||||||
|
face->index_count = numverts + 1; // +1 for primitive restart
|
||||||
|
face->tex_id = build->tex_id;
|
||||||
|
face->flags = surf->flags;
|
||||||
|
build->index_base += face->index_count;
|
||||||
|
for (int i = 0; i < numverts; i++) {
|
||||||
|
build->indices[face->first_index + i] = build->vertex_base + i;
|
||||||
}
|
}
|
||||||
|
build->indices[face->first_index + numverts] = -1; // primitive restart
|
||||||
|
|
||||||
|
bspvert_t *verts = build->vertices + build->vertex_base;
|
||||||
|
build->vertex_base += numverts;
|
||||||
|
mtexinfo_t *texinfo = surf->texinfo;
|
||||||
mvertex_t *vertices = brush->vertexes;
|
mvertex_t *vertices = brush->vertexes;
|
||||||
medge_t *edges = brush->edges;
|
medge_t *edges = brush->edges;
|
||||||
int *surfedges = brush->surfedges;
|
int *surfedges = brush->surfedges;
|
||||||
|
|
||||||
// surf->polys is set to the next slot before the call
|
|
||||||
bsppoly_t *poly = (bsppoly_t *) surf->polys;
|
|
||||||
// create a triangle fan
|
|
||||||
int numverts = surf->numedges;
|
|
||||||
poly->count = numverts + 1; // +1 for primitive restart
|
|
||||||
for (int i = 0; i < numverts; i++) {
|
|
||||||
poly->indices[i] = base + i;
|
|
||||||
}
|
|
||||||
poly->indices[numverts] = -1; // primitive restart
|
|
||||||
surf->polys = (glpoly_t *) poly;
|
|
||||||
|
|
||||||
bspvert_t *verts = *vert_list;
|
|
||||||
mtexinfo_t *texinfo = surf->texinfo;
|
|
||||||
for (int i = 0; i < numverts; i++) {
|
for (int i = 0; i < numverts; i++) {
|
||||||
vec_t *vec;
|
vec_t *vec;
|
||||||
int index = surfedges[surf->firstedge + i];
|
int index = surfedges[surf->firstedge + i];
|
||||||
|
@ -388,8 +284,6 @@ build_surf_displist (model_t **models, msurface_t *surf, int base,
|
||||||
verts[i].tlst[3] = 0;
|
verts[i].tlst[3] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*vert_list += numverts;
|
|
||||||
return (bsppoly_t *) &poly->indices[poly->count];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -403,9 +297,16 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
facerefset_t *face_sets = alloca (bctx->registered_textures.size
|
||||||
|
* sizeof (facerefset_t));
|
||||||
|
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||||
|
face_sets[i] = (facerefset_t) DARRAY_STATIC_INIT (1024);
|
||||||
|
}
|
||||||
|
|
||||||
// run through all surfaces, chaining them to their textures, thus
|
// run through all surfaces, chaining them to their textures, thus
|
||||||
// effectively sorting the surfaces by texture (without worrying about
|
// effectively sorting the surfaces by texture (without worrying about
|
||||||
// surface order on the same texture chain).
|
// surface order on the same texture chain).
|
||||||
|
int face_base = 0;
|
||||||
for (int i = 0; i < num_models; i++) {
|
for (int i = 0; i < num_models; i++) {
|
||||||
model_t *m = models[i];
|
model_t *m = models[i];
|
||||||
// sub-models are done as part of the main model
|
// sub-models are done as part of the main model
|
||||||
|
@ -421,30 +322,32 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
||||||
if (dm == brush->submodels + brush->numsubmodels) {
|
if (dm == brush->submodels + brush->numsubmodels) {
|
||||||
// limit the surfaces
|
// limit the surfaces
|
||||||
// probably never hit
|
// probably never hit
|
||||||
Sys_Printf ("R_BuildDisplayLists: too many surfaces\n");
|
Sys_Printf ("Vulkan_BuildDisplayLists: too many faces\n");
|
||||||
brush->numsurfaces = j;
|
brush->numsurfaces = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msurface_t *surf = brush->surfaces + j;
|
msurface_t *surf = brush->surfaces + j;
|
||||||
surf->model_index = dm - brush->submodels;
|
|
||||||
if (!surf->model_index && m != r_refdef.worldmodel) {
|
|
||||||
surf->model_index = -1 - i; // instanced model
|
|
||||||
}
|
|
||||||
// append surf to the texture chain
|
// append surf to the texture chain
|
||||||
vulktex_t *tex = surf->texinfo->texture->render;
|
vulktex_t *tex = surf->texinfo->texture->render;
|
||||||
CHAIN_SURF_F2B (surf, tex->tex_chain);
|
DARRAY_APPEND (&face_sets[tex->tex_id],
|
||||||
|
((faceref_t) { surf, m, face_base }));
|
||||||
}
|
}
|
||||||
|
face_base += brush->numsurfaces;
|
||||||
}
|
}
|
||||||
// All vertices from all brush models go into one giant vbo.
|
// All vertices from all brush models go into one giant vbo.
|
||||||
uint32_t vertex_count = 0;
|
uint32_t vertex_count = 0;
|
||||||
uint32_t index_count = 0;
|
uint32_t index_count = 0;
|
||||||
uint32_t poly_count = 0;
|
uint32_t poly_count = 0;
|
||||||
for (size_t i = 0; i < bctx->texture_chains.size; i++) {
|
// This is not optimal as counted vertices are not shared between faces,
|
||||||
vulktex_t *tex = bctx->texture_chains.a[i];
|
// however this greatly simplifies display list creation as no care needs
|
||||||
for (instsurf_t *is = tex->tex_chain; is; is = is->tex_chain) {
|
// to be taken when it comes to UVs, and every vertex needs a unique light
|
||||||
|
// map UV anyway (when lightmaps are used).
|
||||||
|
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||||
|
for (size_t j = 0; j < face_sets[i].size; j++) {
|
||||||
|
faceref_t *faceref = &face_sets[i].a[j];
|
||||||
uint32_t verts, inds;
|
uint32_t verts, inds;
|
||||||
count_verts_inds (models, is->surface, &verts, &inds);
|
count_verts_inds (faceref, &verts, &inds);
|
||||||
vertex_count += verts;
|
vertex_count += verts;
|
||||||
index_count += inds;
|
index_count += inds;
|
||||||
poly_count++;
|
poly_count++;
|
||||||
|
@ -464,44 +367,39 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
||||||
qfv_packet_t *packet = QFV_PacketAcquire (stage);
|
qfv_packet_t *packet = QFV_PacketAcquire (stage);
|
||||||
bspvert_t *vertices = QFV_PacketExtend (packet, vertex_buffer_size);
|
bspvert_t *vertices = QFV_PacketExtend (packet, vertex_buffer_size);
|
||||||
// holds all the polygon definitions: vertex indices + poly_count
|
// holds all the polygon definitions: vertex indices + poly_count
|
||||||
// primitive restart markers + poly_count index counts. The primitive
|
// primitive restart markers. The primitive restart markers are included
|
||||||
// restart markers are included in index_count, so poly_count below is
|
// in index_count.
|
||||||
// for the per-polygon index count.
|
|
||||||
// so each polygon within the list:
|
// so each polygon within the list:
|
||||||
// count includes the end of primitive marker
|
|
||||||
// index count-1 indices
|
// index count-1 indices
|
||||||
// index
|
// index
|
||||||
// ...
|
// ...
|
||||||
// "end of primitive" (~0u)
|
// "end of primitive" (~0u)
|
||||||
free (bctx->polys);
|
free (bctx->faces);
|
||||||
bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t));
|
free (bctx->poly_indices);
|
||||||
|
bctx->faces = malloc (face_base * sizeof (bsp_face_t));
|
||||||
|
bctx->poly_indices = malloc (index_count * sizeof (uint32_t));
|
||||||
|
|
||||||
// All usable surfaces have been chained to the (base) texture they use.
|
// All usable surfaces have been chained to the (base) texture they use.
|
||||||
// Run through the textures, using their chains to build display lists.
|
// Run through the textures, using their chains to build display lists.
|
||||||
// For animated textures, if a surface is on one texture of the group, it
|
// For animated textures, if a surface is on one texture of the group, it
|
||||||
// will effectively be on all (just one at a time).
|
// will effectively be on all (just one at a time).
|
||||||
int count = 0;
|
buildctx_t build = {
|
||||||
int vertex_index_base = 0;
|
.faces = bctx->faces,
|
||||||
bsppoly_t *poly = bctx->polys;
|
.indices = bctx->poly_indices,
|
||||||
for (size_t i = 0; i < bctx->texture_chains.size; i++) {
|
.vertices = vertices,
|
||||||
vulktex_t *tex = bctx->texture_chains.a[i];
|
.index_base = 0,
|
||||||
|
.vertex_base = 0,
|
||||||
for (instsurf_t *is = tex->tex_chain; is; is = is->tex_chain) {
|
};
|
||||||
msurface_t *surf = is->surface;
|
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||||
|
build.tex_id = i;
|
||||||
surf->polys = (glpoly_t *) poly;
|
for (size_t j = 0; j < face_sets[i].size; j++) {
|
||||||
poly = build_surf_displist (models, surf, vertex_index_base,
|
faceref_t *faceref = &face_sets[i].a[j];
|
||||||
&vertices);
|
build_surf_displist (faceref, &build);
|
||||||
vertex_index_base += surf->numedges;
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clear_texture_chains (bctx);
|
|
||||||
Sys_MaskPrintf (SYS_vulkan,
|
Sys_MaskPrintf (SYS_vulkan,
|
||||||
"R_BuildDisplayLists: verts:%u, inds:%u, "
|
"R_BuildDisplayLists: verts:%u, inds:%u, polys:%u\n",
|
||||||
"polys:%u (%d) %zd\n",
|
vertex_count, index_count, poly_count);
|
||||||
vertex_count, index_count, poly_count, count,
|
|
||||||
((size_t) poly - (size_t) bctx->polys) / sizeof(uint32_t));
|
|
||||||
if (index_buffer_size > bctx->index_buffer_size) {
|
if (index_buffer_size > bctx->index_buffer_size) {
|
||||||
if (bctx->index_buffer) {
|
if (bctx->index_buffer) {
|
||||||
dfunc->vkUnmapMemory (device->dev, bctx->index_memory);
|
dfunc->vkUnmapMemory (device->dev, bctx->index_memory);
|
||||||
|
@ -571,6 +469,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
||||||
0, 0, 0, 1, &bb.barrier, 0, 0);
|
0, 0, 0, 1, &bb.barrier, 0, 0);
|
||||||
QFV_PacketSubmit (packet);
|
QFV_PacketSubmit (packet);
|
||||||
QFV_DestroyStagingBuffer (stage);
|
QFV_DestroyStagingBuffer (stage);
|
||||||
|
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||||
|
DARRAY_CLEAR (&face_sets[i]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -629,7 +531,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx)
|
||||||
// enqueue the polygon
|
// enqueue the polygon
|
||||||
if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON))
|
if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON))
|
||||||
|| (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
|
|| (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
|
||||||
chain_surface (surf, ctx);
|
//chain_surface (surf, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,8 +558,9 @@ get_side (mnode_t *node)
|
||||||
static inline void
|
static inline void
|
||||||
visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
|
visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
|
bspctx_t *bctx = ctx->bsp_context;
|
||||||
|
bsp_pass_t *pass = &ctx->bsp_context->main_pass;
|
||||||
int c;
|
int c;
|
||||||
msurface_t *surf;
|
|
||||||
|
|
||||||
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
||||||
// seems to be microscopically faster even on modern hardware
|
// seems to be microscopically faster even on modern hardware
|
||||||
|
@ -665,19 +568,19 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
|
||||||
// chain any visible surfaces on the node that face the camera.
|
// chain any visible surfaces on the node that face the camera.
|
||||||
// not all nodes have any surfaces to draw (purely a split plane)
|
// not all nodes have any surfaces to draw (purely a split plane)
|
||||||
if ((c = node->numsurfaces)) {
|
if ((c = node->numsurfaces)) {
|
||||||
int surf_id = node->firstsurface;
|
const bsp_face_t *face = bctx->faces + node->firstsurface;
|
||||||
surf = brush->surfaces + surf_id;
|
const int *frame = pass->face_frames + node->firstsurface;
|
||||||
for (; c; c--, surf++, surf_id++) {
|
for (; c; c--, face++, frame++) {
|
||||||
if (r_face_visframes[surf_id] != r_visframecount)
|
if (*frame != r_visframecount)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// side is either 0 or SURF_PLANEBACK
|
// side is either 0 or SURF_PLANEBACK
|
||||||
// if side and the surface facing differ, then the camera is
|
// if side and the surface facing differ, then the camera is
|
||||||
// on backside of the surface
|
// on backside of the surface
|
||||||
if (side ^ (surf->flags & SURF_PLANEBACK))
|
if (side ^ (face->flags & SURF_PLANEBACK))
|
||||||
continue; // wrong side
|
continue; // wrong side
|
||||||
|
|
||||||
chain_surface (surf, ctx);
|
chain_surface (face, pass, bctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -799,32 +702,6 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout,
|
||||||
QFV_PushConstants (device, cmd, layout, 3, push_constants);
|
QFV_PushConstants (device, cmd, layout, 3, push_constants);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_device_t *device,
|
|
||||||
VkCommandBuffer cmd)
|
|
||||||
{
|
|
||||||
qfv_devfuncs_t *dfunc = device->funcs;
|
|
||||||
|
|
||||||
if (ec->transform) {
|
|
||||||
push_transform (ec->transform, layout, device, cmd);
|
|
||||||
} else {
|
|
||||||
//FIXME should cache current transform
|
|
||||||
push_transform (identity, layout, device, cmd);
|
|
||||||
}
|
|
||||||
if (ec->index_count) {
|
|
||||||
dfunc->vkCmdDrawIndexed (cmd, ec->index_count, 1, ec->first_index,
|
|
||||||
0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
reset_elechain (elechain_t *ec)
|
|
||||||
{
|
|
||||||
ec->first_index = 0;
|
|
||||||
ec->index_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
|
bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
|
||||||
VkPipelineLayout layout, qfv_renderframe_t *rFrame)
|
VkPipelineLayout layout, qfv_renderframe_t *rFrame)
|
||||||
|
@ -979,40 +856,32 @@ sky_end (vulkan_ctx_t *ctx)
|
||||||
bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx);
|
bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
add_surf_elements (vulktex_t *tex, instsurf_t *is, elechain_t **ec,
|
clear_queues (bspctx_t *bctx, bsp_pass_t *pass)
|
||||||
bspctx_t *bctx, bspframe_t *bframe)
|
|
||||||
{
|
{
|
||||||
bsppoly_t *poly = (bsppoly_t *) is->surface->polys;
|
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||||
|
DARRAY_RESIZE (&pass->face_queue[i], 0);
|
||||||
if (!tex->elechain) {
|
|
||||||
(*ec) = add_elechain (tex, bctx);
|
|
||||||
(*ec)->transform = is->transform;
|
|
||||||
(*ec)->color = is->color;
|
|
||||||
(*ec)->first_index = bframe->index_count;
|
|
||||||
}
|
}
|
||||||
if (is->transform != (*ec)->transform || is->color != (*ec)->color) {
|
for (int j = 0; j < pass->num_queues; j++) {
|
||||||
(*ec) = add_elechain (tex, bctx);
|
DARRAY_RESIZE (&pass->draw_queues[j], 0);
|
||||||
(*ec)->transform = is->transform;
|
|
||||||
(*ec)->color = is->color;
|
|
||||||
(*ec)->first_index = bframe->index_count;
|
|
||||||
}
|
}
|
||||||
memcpy (bframe->index_data + bframe->index_count,
|
pass->index_count = 0;
|
||||||
poly->indices, poly->count * sizeof (poly->indices[0]));
|
|
||||||
(*ec)->index_count += poly->count;
|
|
||||||
bframe->index_count += poly->count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe)
|
draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout,
|
||||||
|
qfv_device_t *device, VkCommandBuffer cmd)
|
||||||
{
|
{
|
||||||
instsurf_t *is;
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
elechain_t *ec = 0;
|
|
||||||
|
|
||||||
for (is = tex->tex_chain; is; is = is->tex_chain) {
|
for (size_t i = 0; i < pass->draw_queues[queue].size; i++) {
|
||||||
// emit the polygon indices for the surface to the texture's
|
__auto_type d = pass->draw_queues[queue].a[i];
|
||||||
// element chain
|
if (pass->textures) {
|
||||||
add_surf_elements (tex, is, &ec, bctx, bframe);
|
vulktex_t *tex = pass->textures->a[d.tex_id];
|
||||||
|
bind_texture (tex, 1, layout, dfunc, cmd);
|
||||||
|
}
|
||||||
|
dfunc->vkCmdDrawIndexed (cmd, d.index_count, d.instance_count,
|
||||||
|
d.first_index, 0, d.first_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,13 +890,17 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
|
||||||
{
|
{
|
||||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||||
qfv_device_t *device = ctx->device;
|
qfv_device_t *device = ctx->device;
|
||||||
qfv_devfuncs_t *dfunc = device->funcs;
|
//qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
bspctx_t *bctx = ctx->bsp_context;
|
bspctx_t *bctx = ctx->bsp_context;
|
||||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||||
entity_t worldent;
|
entity_t worldent;
|
||||||
mod_brush_t *brush;
|
mod_brush_t *brush;
|
||||||
|
|
||||||
clear_texture_chains (bctx); // do this first for water and skys
|
bctx->main_pass.face_frames = r_face_visframes;
|
||||||
|
bctx->main_pass.leaf_frames = r_leaf_visframes;
|
||||||
|
bctx->main_pass.node_frames = r_node_visframes;
|
||||||
|
|
||||||
|
clear_queues (bctx, &bctx->main_pass); // do this first for water and skys
|
||||||
bframe->index_count = 0;
|
bframe->index_count = 0;
|
||||||
|
|
||||||
memset (&worldent, 0, sizeof (worldent));
|
memset (&worldent, 0, sizeof (worldent));
|
||||||
|
@ -1058,27 +931,42 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
|
||||||
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
||||||
push_fragconst (&frag_constants, bctx->layout, device,
|
push_fragconst (&frag_constants, bctx->layout, device,
|
||||||
bframe->cmdSet.a[QFV_bspGBuffer]);
|
bframe->cmdSet.a[QFV_bspGBuffer]);
|
||||||
for (size_t i = 0; i < bctx->texture_chains.size; i++) {
|
__auto_type pass = &bctx->main_pass;
|
||||||
vulktex_t *tex;
|
pass->indices = bframe->index_data;
|
||||||
elechain_t *ec = 0;
|
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||||
|
__auto_type queue = &pass->face_queue[i];
|
||||||
tex = bctx->texture_chains.a[i];
|
if (!queue->size) {
|
||||||
|
continue;
|
||||||
build_tex_elechain (tex, bctx, bframe);
|
|
||||||
|
|
||||||
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
||||||
bframe->cmdSet.a[QFV_bspGBuffer]);
|
|
||||||
|
|
||||||
for (ec = tex->elechain; ec; ec = ec->next) {
|
|
||||||
draw_elechain (ec, bctx->layout, device,
|
|
||||||
bframe->cmdSet.a[QFV_bspDepth]);
|
|
||||||
draw_elechain (ec, bctx->layout, device,
|
|
||||||
bframe->cmdSet.a[QFV_bspGBuffer]);
|
|
||||||
reset_elechain (ec);
|
|
||||||
}
|
}
|
||||||
tex->elechain = 0;
|
//FIXME implement draw_queue selection correctly (per face)
|
||||||
tex->elechain_tail = &tex->elechain;
|
int dq = 0;
|
||||||
|
if (bctx->faces[queue->a[0].face].flags & SURF_DRAWSKY) {
|
||||||
|
dq = 1;
|
||||||
}
|
}
|
||||||
|
if (bctx->faces[queue->a[0].face].flags & SURF_DRAWTURB) {
|
||||||
|
dq = 2;
|
||||||
|
}
|
||||||
|
bsp_draw_t draw = {
|
||||||
|
.tex_id = i,
|
||||||
|
.instance_count = 1,
|
||||||
|
.first_index = pass->index_count,
|
||||||
|
};
|
||||||
|
for (size_t j = 0; j < queue->size; j++) {
|
||||||
|
__auto_type is = queue->a[j];
|
||||||
|
__auto_type f = bctx->faces[is.face];
|
||||||
|
memcpy (pass->indices + pass->index_count,
|
||||||
|
bctx->poly_indices + f.first_index,
|
||||||
|
f.index_count * sizeof (uint32_t));
|
||||||
|
draw.index_count += f.index_count;
|
||||||
|
pass->index_count += f.index_count;
|
||||||
|
}
|
||||||
|
DARRAY_APPEND (&pass->draw_queues[dq], draw);
|
||||||
|
}
|
||||||
|
VkPipelineLayout layout = bctx->layout;
|
||||||
|
pass->textures = 0;
|
||||||
|
draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspDepth]);
|
||||||
|
pass->textures = &bctx->registered_textures;
|
||||||
|
draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspGBuffer]);
|
||||||
bsp_end (ctx);
|
bsp_end (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,14 +1000,11 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame)
|
||||||
{
|
{
|
||||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||||
qfv_device_t *device = ctx->device;
|
qfv_device_t *device = ctx->device;
|
||||||
qfv_devfuncs_t *dfunc = device->funcs;
|
//qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
bspctx_t *bctx = ctx->bsp_context;
|
bspctx_t *bctx = ctx->bsp_context;
|
||||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||||
instsurf_t *is;
|
|
||||||
vulktex_t *tex = 0;
|
|
||||||
elechain_t *ec = 0;
|
|
||||||
|
|
||||||
if (!bctx->waterchain)
|
if (!bctx->main_pass.draw_queues[2].size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
turb_begin (rFrame);
|
turb_begin (rFrame);
|
||||||
|
@ -1131,41 +1016,13 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame)
|
||||||
};
|
};
|
||||||
push_fragconst (&frag_constants, bctx->layout, device,
|
push_fragconst (&frag_constants, bctx->layout, device,
|
||||||
bframe->cmdSet.a[QFV_bspTurb]);
|
bframe->cmdSet.a[QFV_bspTurb]);
|
||||||
for (is = bctx->waterchain; is; is = is->tex_chain) {
|
|
||||||
msurface_t *surf = is->surface;
|
|
||||||
if (tex != surf->texinfo->texture->render) {
|
|
||||||
if (tex) {
|
|
||||||
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
||||||
bframe->cmdSet.a[QFV_bspTurb]);
|
|
||||||
for (ec = tex->elechain; ec; ec = ec->next) {
|
|
||||||
draw_elechain (ec, bctx->layout, device,
|
|
||||||
bframe->cmdSet.a[QFV_bspTurb]);
|
|
||||||
reset_elechain (ec);
|
|
||||||
}
|
|
||||||
tex->elechain = 0;
|
|
||||||
tex->elechain_tail = &tex->elechain;
|
|
||||||
}
|
|
||||||
tex = surf->texinfo->texture->render;
|
|
||||||
}
|
|
||||||
// emit the polygon indices for the surface to the texture's
|
|
||||||
// element chain
|
|
||||||
add_surf_elements (tex, is, &ec, bctx, bframe);
|
|
||||||
}
|
|
||||||
if (tex) {
|
|
||||||
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
||||||
bframe->cmdSet.a[QFV_bspTurb]);
|
|
||||||
for (ec = tex->elechain; ec; ec = ec->next) {
|
|
||||||
draw_elechain (ec, bctx->layout, device,
|
|
||||||
bframe->cmdSet.a[QFV_bspTurb]);
|
|
||||||
reset_elechain (ec);
|
|
||||||
}
|
|
||||||
tex->elechain = 0;
|
|
||||||
tex->elechain_tail = &tex->elechain;
|
|
||||||
}
|
|
||||||
turb_end (ctx);
|
|
||||||
|
|
||||||
bctx->waterchain = 0;
|
VkPipelineLayout layout = bctx->layout;
|
||||||
bctx->waterchain_tail = &bctx->waterchain;
|
__auto_type pass = &bctx->main_pass;
|
||||||
|
pass->textures = &bctx->registered_textures;
|
||||||
|
draw_queue (pass, 2, layout, device, bframe->cmdSet.a[QFV_bspTurb]);
|
||||||
|
|
||||||
|
turb_end (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1176,11 +1033,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame)
|
||||||
qfv_devfuncs_t *dfunc = device->funcs;
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
bspctx_t *bctx = ctx->bsp_context;
|
bspctx_t *bctx = ctx->bsp_context;
|
||||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||||
instsurf_t *is;
|
|
||||||
vulktex_t *tex = 0;
|
|
||||||
elechain_t *ec = 0;
|
|
||||||
|
|
||||||
if (!bctx->sky_chain)
|
if (!bctx->main_pass.draw_queues[1].size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sky_begin (rFrame);
|
sky_begin (rFrame);
|
||||||
|
@ -1192,41 +1046,13 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame)
|
||||||
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
||||||
push_fragconst (&frag_constants, bctx->layout, device,
|
push_fragconst (&frag_constants, bctx->layout, device,
|
||||||
bframe->cmdSet.a[QFV_bspSky]);
|
bframe->cmdSet.a[QFV_bspSky]);
|
||||||
for (is = bctx->sky_chain; is; is = is->tex_chain) {
|
|
||||||
msurface_t *surf = is->surface;
|
|
||||||
if (tex != surf->texinfo->texture->render) {
|
|
||||||
if (tex) {
|
|
||||||
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
||||||
bframe->cmdSet.a[QFV_bspSky]);
|
|
||||||
for (ec = tex->elechain; ec; ec = ec->next) {
|
|
||||||
draw_elechain (ec, bctx->layout, device,
|
|
||||||
bframe->cmdSet.a[QFV_bspSky]);
|
|
||||||
reset_elechain (ec);
|
|
||||||
}
|
|
||||||
tex->elechain = 0;
|
|
||||||
tex->elechain_tail = &tex->elechain;
|
|
||||||
}
|
|
||||||
tex = surf->texinfo->texture->render;
|
|
||||||
}
|
|
||||||
// emit the polygon indices for the surface to the texture's
|
|
||||||
// element chain
|
|
||||||
add_surf_elements (tex, is, &ec, bctx, bframe);
|
|
||||||
}
|
|
||||||
if (tex) {
|
|
||||||
bind_texture (tex, 1, bctx->layout, dfunc,
|
|
||||||
bframe->cmdSet.a[QFV_bspSky]);
|
|
||||||
for (ec = tex->elechain; ec; ec = ec->next) {
|
|
||||||
draw_elechain (ec, bctx->layout, device,
|
|
||||||
bframe->cmdSet.a[QFV_bspSky]);
|
|
||||||
reset_elechain (ec);
|
|
||||||
}
|
|
||||||
tex->elechain = 0;
|
|
||||||
tex->elechain_tail = &tex->elechain;
|
|
||||||
}
|
|
||||||
sky_end (ctx);
|
|
||||||
|
|
||||||
bctx->sky_chain = 0;
|
VkPipelineLayout layout = bctx->layout;
|
||||||
bctx->sky_chain_tail = &bctx->sky_chain;
|
__auto_type pass = &bctx->main_pass;
|
||||||
|
pass->textures = &bctx->registered_textures;
|
||||||
|
draw_queue (pass, 1, layout, device, bframe->cmdSet.a[QFV_bspSky]);
|
||||||
|
|
||||||
|
sky_end (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1348,12 +1174,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
|
||||||
bspctx_t *bctx = calloc (1, sizeof (bspctx_t));
|
bspctx_t *bctx = calloc (1, sizeof (bspctx_t));
|
||||||
ctx->bsp_context = bctx;
|
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->instsurfs_tail = &bctx->instsurfs;
|
|
||||||
|
|
||||||
bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048,
|
bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048,
|
||||||
tex_frgba, ctx->staging);
|
tex_frgba, ctx->staging);
|
||||||
size_t size = QFV_ScrapSize (bctx->light_scrap);
|
size_t size = QFV_ScrapSize (bctx->light_scrap);
|
||||||
|
@ -1362,7 +1182,14 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
|
||||||
|
|
||||||
create_default_skys (ctx);
|
create_default_skys (ctx);
|
||||||
|
|
||||||
DARRAY_INIT (&bctx->texture_chains, 64);
|
DARRAY_INIT (&bctx->registered_textures, 64);
|
||||||
|
|
||||||
|
bctx->main_pass.num_queues = 3;
|
||||||
|
bctx->main_pass.draw_queues = malloc (bctx->main_pass.num_queues
|
||||||
|
* sizeof (bsp_drawset_t));
|
||||||
|
for (int i = 0; i < bctx->main_pass.num_queues; i++) {
|
||||||
|
DARRAY_INIT (&bctx->main_pass.draw_queues[i], 64);
|
||||||
|
}
|
||||||
|
|
||||||
size_t frames = ctx->frames.size;
|
size_t frames = ctx->frames.size;
|
||||||
DARRAY_INIT (&bctx->frames, frames);
|
DARRAY_INIT (&bctx->frames, frames);
|
||||||
|
@ -1418,7 +1245,11 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
|
||||||
dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0);
|
dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0);
|
||||||
dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0);
|
dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0);
|
||||||
dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0);
|
dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0);
|
||||||
DARRAY_CLEAR (&bctx->texture_chains);
|
DARRAY_CLEAR (&bctx->registered_textures);
|
||||||
|
for (int i = 0; i < bctx->main_pass.num_queues; i++) {
|
||||||
|
DARRAY_CLEAR (&bctx->main_pass.draw_queues[i]);
|
||||||
|
}
|
||||||
|
free (bctx->main_pass.draw_queues);
|
||||||
DARRAY_CLEAR (&bctx->frames);
|
DARRAY_CLEAR (&bctx->frames);
|
||||||
QFV_DestroyStagingBuffer (bctx->light_stage);
|
QFV_DestroyStagingBuffer (bctx->light_stage);
|
||||||
QFV_DestroyScrap (bctx->light_scrap);
|
QFV_DestroyScrap (bctx->light_scrap);
|
||||||
|
|
Loading…
Reference in a new issue