[vulkan] Upload lightmap data to the gpu and use it

The lightmaps aren't updated at all yet, so everything is static.
Figuring out how lightmap data gets to the gpu was a chore thanks to the
spaghetti in the bsp data, and then I'd forgotten that I was
pre-expanding the light data to rgb so wound up with weird lightmaps,
but without water or particles, demo1 is getting 5000fps at 800x450, and
it seems to be CPU limited.
This commit is contained in:
Bill Currie 2024-01-16 11:02:29 +09:00
parent 329c08b934
commit 3168550935
8 changed files with 85 additions and 63 deletions

View file

@ -355,6 +355,7 @@ 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;
VkDescriptorSet lightmap_descriptor;
int num_models; ///< number of loaded brush models int num_models; ///< number of loaded brush models
bsp_model_t *models; ///< all loaded brush models bsp_model_t *models; ///< all loaded brush models

View file

@ -43,7 +43,7 @@ struct transform_s;
void Vulkan_lightmap_init (struct vulkan_ctx_s *ctx); void Vulkan_lightmap_init (struct vulkan_ctx_s *ctx);
void Vulkan_BuildLightmaps (struct model_s **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_BuildLightmaps (struct model_s **models, int num_models, struct vulkan_ctx_s *ctx);
void Vulkan_CalcLightmaps (struct vulkan_ctx_s *ctx); void Vulkan_CalcLightmaps (struct vulkan_ctx_s *ctx);
void Vulkan_BuildLightMap (const struct transform_s *transform, struct mod_brush_s *brush, struct msurface_s *surf, struct vulkan_ctx_s *ctx); void Vulkan_BuildLightMap (struct transform_s transform, struct mod_brush_s *brush, struct msurface_s *surf, struct vulkan_ctx_s *ctx);
VkImageView Vulkan_LightmapImageView (struct vulkan_ctx_s *ctx) __attribute__((pure)); VkImageView Vulkan_LightmapImageView (struct vulkan_ctx_s *ctx) __attribute__((pure));
void Vulkan_FlushLightmaps (struct vulkan_ctx_s *ctx); void Vulkan_FlushLightmaps (struct vulkan_ctx_s *ctx);

View file

@ -250,6 +250,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_draw.c \
libs/video/renderer/vulkan/vulkan_iqm.c \ libs/video/renderer/vulkan/vulkan_iqm.c \
libs/video/renderer/vulkan/vulkan_lighting.c \ libs/video/renderer/vulkan/vulkan_lighting.c \
libs/video/renderer/vulkan/vulkan_lightmap.c \
libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_matrices.c \
libs/video/renderer/vulkan/vulkan_output.c \ libs/video/renderer/vulkan/vulkan_output.c \
libs/video/renderer/vulkan/vulkan_palette.c \ libs/video/renderer/vulkan/vulkan_palette.c \

View file

@ -223,22 +223,17 @@ properties = {
brush = { brush = {
shader = { shader = {
depth_vertex = { vertex = {
stage = vertex;
name = main;
module = $builtin/bsp_depth.vert;
};
gbuf_vertex = {
stage = vertex; stage = vertex;
name = main; name = main;
module = $builtin/bsp_gbuf.vert; module = $builtin/bsp_gbuf.vert;
}; };
gbuf_geometry = { geometry = {
stage = geometry; stage = geometry;
name = main; name = main;
module = $builtin/bsp_gbuf.geom; module = $builtin/bsp_gbuf.geom;
}; };
gbuf_fragment = { fragment = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/quakebsp.frag; module = $builtin/quakebsp.frag;
@ -299,7 +294,7 @@ properties = {
}; };
layout = { layout = {
descriptorSets = (matrix_set, entity_set, oit_set, descriptorSets = (matrix_set, entity_set, oit_set,
// surface skybox // surface skybox/lightmap
texture_set, texture_set); texture_set, texture_set);
pushConstants = { pushConstants = {
fragment = { fragment = {
@ -313,17 +308,12 @@ properties = {
}; };
alias = { alias = {
shader = { shader = {
depth_vertex = { vertex = {
stage = vertex;
name = main;
module = $builtin/alias_depth.vert;
};
gbuf_vertex = {
stage = vertex; stage = vertex;
name = main; name = main;
module = $builtin/alias.vert; module = $builtin/alias.vert;
}; };
gbuf_fragment = { fragment = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/alias.frag; module = $builtin/alias.frag;
@ -364,17 +354,7 @@ properties = {
{ size = 4; offset = 0; constantID = 0; }, { size = 4; offset = 0; constantID = 0; },
); );
}; };
depth_vertex = { vertex = {
stage = vertex;
name = main;
module = $builtin/iqm.vert;
specializationInfo = {
@inherit = $iqm.shader.specialization;
// IQMDepthOnly
data = "array(1, 0)";
};
};
gbuf_vertex = {
stage = vertex; stage = vertex;
name = main; name = main;
module = $builtin/iqm.vert; module = $builtin/iqm.vert;
@ -384,7 +364,7 @@ properties = {
data = "array(0, 0)"; data = "array(0, 0)";
}; };
}; };
gbuf_fragment = { fragment = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/iqm_fwd.frag; module = $builtin/iqm_fwd.frag;
@ -431,22 +411,17 @@ properties = {
}; };
sprite = { sprite = {
shader = { shader = {
depth_vertex = {
stage = vertex;
name = main;
module = $builtin/sprite_depth.vert;
};
depth_fragment = { depth_fragment = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/sprite_depth.frag; module = $builtin/sprite_depth.frag;
}; };
gbuf_vertex = { vertex = {
stage = vertex; stage = vertex;
name = main; name = main;
module = $builtin/sprite_gbuf.vert; module = $builtin/sprite_gbuf.vert;
}; };
gbuf_fragment = { fragment = {
stage = fragment; stage = fragment;
name = main; name = main;
module = $builtin/sprite.frag; module = $builtin/sprite.frag;
@ -1112,9 +1087,9 @@ renderpasses = {
); );
stages = ( stages = (
$brush.shader.gbuf_vertex, $brush.shader.vertex,
$brush.shader.gbuf_geometry, $brush.shader.geometry,
$brush.shader.gbuf_fragment, $brush.shader.fragment,
); );
vertexInput = $brush.vertexInput; vertexInput = $brush.vertexInput;
inputAssembly = $brush.inputAssembly; inputAssembly = $brush.inputAssembly;
@ -1128,8 +1103,8 @@ renderpasses = {
); );
stages = ( stages = (
$alias.shader.gbuf_vertex, $alias.shader.vertex,
$alias.shader.gbuf_fragment, $alias.shader.fragment,
); );
vertexInput = $alias.vertexInput; vertexInput = $alias.vertexInput;
inputAssembly = $alias.inputAssembly; inputAssembly = $alias.inputAssembly;
@ -1143,8 +1118,8 @@ renderpasses = {
); );
stages = ( stages = (
$iqm.shader.gbuf_vertex, $iqm.shader.vertex,
$iqm.shader.gbuf_fragment, $iqm.shader.fragment,
); );
vertexInput = $iqm.vertexInput; vertexInput = $iqm.vertexInput;
inputAssembly = $iqm.inputAssembly; inputAssembly = $iqm.inputAssembly;
@ -1157,8 +1132,8 @@ renderpasses = {
); );
stages = ( stages = (
$sprite.shader.gbuf_vertex, $sprite.shader.vertex,
$sprite.shader.gbuf_fragment, $sprite.shader.fragment,
); );
vertexInput = $sprite.vertexInput; vertexInput = $sprite.vertexInput;
inputAssembly = $sprite.inputAssembly; inputAssembly = $sprite.inputAssembly;

View file

@ -1,6 +1,7 @@
#version 450 #version 450
layout (set = 3, binding = 0) uniform sampler2DArray Texture; layout (set = 3, binding = 0) uniform sampler2DArray Texture;
layout (set = 4, binding = 0) uniform sampler2D Lightmap;
layout (push_constant) uniform PushConstants { layout (push_constant) uniform PushConstants {
vec4 fog; vec4 fog;
@ -35,6 +36,7 @@ main (void)
vec4 c = texture (Texture, t_st) * color; vec4 c = texture (Texture, t_st) * color;
vec4 e = texture (Texture, e_st); vec4 e = texture (Texture, e_st);
vec4 l = texture (Lightmap, l_st);
frag_color = c;//fogBlend (c); frag_color = c * l + e;//fogBlend (c);
} }

View file

@ -74,6 +74,7 @@
#define TEX_SET 3 #define TEX_SET 3
#define SKYBOX_SET 4 #define SKYBOX_SET 4
#define LIGHTMAP_SET 4
typedef struct bsp_push_constants_s { typedef struct bsp_push_constants_s {
quat_t fog; quat_t fog;
@ -1270,6 +1271,9 @@ bsp_draw_queue (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
if (queue == QFV_bspSky) { if (queue == QFV_bspSky) {
vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; vulktex_t skybox = { .descriptor = bctx->skybox_descriptor };
bind_texture (&skybox, SKYBOX_SET, layout, dfunc, cmd); bind_texture (&skybox, SKYBOX_SET, layout, dfunc, cmd);
} else {
vulktex_t lightmap = { .descriptor = bctx->lightmap_descriptor };
bind_texture (&lightmap, LIGHTMAP_SET, layout, dfunc, cmd);
} }
pass->textures = textured ? &bctx->registered_textures : 0; pass->textures = textured ? &bctx->registered_textures : 0;
@ -1506,6 +1510,10 @@ Vulkan_Bsp_Setup (vulkan_ctx_t *ctx)
bframe->entid_offset = i * entid_size; bframe->entid_offset = i * entid_size;
} }
bctx->lightmap_descriptor
= Vulkan_CreateCombinedImageSampler (ctx,
Vulkan_LightmapImageView (ctx),
bctx->sampler);
bctx->skybox_descriptor bctx->skybox_descriptor
= Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox,
bctx->sampler); bctx->sampler);

View file

@ -45,7 +45,6 @@
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_bsp.h"
#include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_lightmap.h"
#include "QF/Vulkan/qf_main.h"
#include "QF/Vulkan/scrap.h" #include "QF/Vulkan/scrap.h"
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
@ -57,9 +56,10 @@
#define LUXEL_SIZE 4 #define LUXEL_SIZE 4
static inline void static inline void
add_dynamic_lights (const transform_t *transform, msurface_t *surf, add_dynamic_lights (transform_t transform, msurface_t *surf,
float *block) float *block)
{ {
#if 0
unsigned lnum; unsigned lnum;
int sd, td; int sd, td;
float dist, rad, minlight; float dist, rad, minlight;
@ -128,10 +128,11 @@ add_dynamic_lights (const transform_t *transform, msurface_t *surf,
} }
} }
} }
#endif
} }
void void
Vulkan_BuildLightMap (const transform_t *transform, mod_brush_t *brush, Vulkan_BuildLightMap (transform_t transform, mod_brush_t *brush,
msurface_t *surf, vulkan_ctx_t *ctx) msurface_t *surf, vulkan_ctx_t *ctx)
{ {
bspctx_t *bctx = ctx->bsp_context; bspctx_t *bctx = ctx->bsp_context;
@ -215,6 +216,40 @@ vulkan_create_surf_lightmap (msurface_t *surf, vulkan_ctx_t *ctx)
} }
} }
static void
vulkan_build_lightmap (mod_brush_t *brush, msurface_t *surf, vulkan_ctx_t *ctx)
{
int smax = (surf->extents[0] >> 4) + 1;
int tmax = (surf->extents[1] >> 4) + 1;
int size = smax * tmax;
vec4f_t *blocklights = QFV_SubpicBatch (surf->lightpic, ctx->staging);
if (!brush->lightdata) {
for (int i = 0; i < size; i++) {
blocklights[i] = (vec4f_t) {1, 1, 1, 1};
}
return;
}
memset (blocklights, 0, sizeof (vec4f_t[size]));
if (surf->samples) {
byte *lightmap = surf->samples;
for (int map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255;
map++) {
surf->cached_light[map] = d_lightstylevalue[surf->styles[map]];
float scale = surf->cached_light[map] / 65536.0;
auto bl = blocklights;
for (int i = 0; i < size; i++) {
vec4f_t val = { VectorExpand (lightmap), 0 };
val *= scale;
val[3] = 1;
lightmap += 3;
*bl++ = val;
}
}
}
}
/* /*
GL_BuildLightmaps GL_BuildLightmaps
@ -224,25 +259,22 @@ void
Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx)
{ {
bspctx_t *bctx = ctx->bsp_context; bspctx_t *bctx = ctx->bsp_context;
int i, j;
model_t *m;
mod_brush_t *brush;
QFV_ScrapClear (bctx->light_scrap); QFV_ScrapClear (bctx->light_scrap);
r_framecount = 1; // no dlightcache r_framecount = 1; // no dlightcache
for (j = 1; j < num_models; j++) { for (int j = 1; j < num_models; j++) {
m = models[j]; auto m = models[j];
if (!m) if (!m)
break; break;
if (m->path[0] == '*' || m->type != mod_brush) { if (m->path[0] == '*' || m->type != mod_brush) {
// sub model surfaces are processed as part of the main model // sub model surfaces are processed as part of the main model
continue; continue;
} }
brush = &m->brush; auto brush = &m->brush;
// non-bsp models don't have surfaces. // non-bsp models don't have surfaces.
for (i = 0; i < brush->numsurfaces; i++) { for (uint32_t i = 0; i < brush->numsurfaces; i++) {
msurface_t *surf = brush->surfaces + i; msurface_t *surf = brush->surfaces + i;
surf->lightpic = 0; // paranoia surf->lightpic = 0; // paranoia
if (surf->flags & SURF_DRAWTURB) { if (surf->flags & SURF_DRAWTURB) {
@ -252,11 +284,13 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx)
continue; continue;
} }
vulkan_create_surf_lightmap (surf, ctx); vulkan_create_surf_lightmap (surf, ctx);
vulkan_build_lightmap (brush, surf, ctx);
} }
} }
QFV_ScrapFlush (bctx->light_scrap);
for (j = 1; j < num_models; j++) { for (int j = 1; j < num_models; j++) {
m = models[j]; auto m = models[j];
if (!m) { if (!m) {
break; break;
} }
@ -264,12 +298,12 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx)
// sub model surfaces are processed as part of the main model // sub model surfaces are processed as part of the main model
continue; continue;
} }
brush = &m->brush; auto brush = &m->brush;
// non-bsp models don't have surfaces. // non-bsp models don't have surfaces.
for (i = 0; i < brush->numsurfaces; i++) { for (uint32_t i = 0; i < brush->numsurfaces; i++) {
msurface_t *surf = brush->surfaces + i; msurface_t *surf = brush->surfaces + i;
if (surf->lightpic) { if (surf->lightpic) {
Vulkan_BuildLightMap (0, brush, surf, ctx); Vulkan_BuildLightMap (nulltransform, brush, surf, ctx);
} }
} }
} }

View file

@ -41,6 +41,7 @@
#include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_bsp.h"
#include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lighting.h"
#include "QF/Vulkan/qf_lightmap.h"
#include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_scene.h"
#include "QF/Vulkan/debug.h" #include "QF/Vulkan/debug.h"
#include "QF/Vulkan/device.h" #include "QF/Vulkan/device.h"
@ -286,7 +287,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx)
R_ClearParticles (); R_ClearParticles ();
Vulkan_RegisterTextures (scene->models, scene->num_models, ctx); Vulkan_RegisterTextures (scene->models, scene->num_models, ctx);
//Vulkan_BuildLightmaps (scene->models, scene->num_models, ctx); Vulkan_BuildLightmaps (scene->models, scene->num_models, ctx);
Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx); Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx);
Vulkan_LoadLights (scene, ctx); //Vulkan_LoadLights (scene, ctx);
} }