From 3168550935fdced444615b0c63f7ea458ca4c134 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Jan 2024 11:02:29 +0900 Subject: [PATCH] [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. --- include/QF/Vulkan/qf_bsp.h | 1 + include/QF/Vulkan/qf_lightmap.h | 2 +- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/rp_main_fwd.plist | 63 ++++++------------ .../renderer/vulkan/shader/quakebsp.frag | 4 +- libs/video/renderer/vulkan/vulkan_bsp.c | 8 +++ libs/video/renderer/vulkan/vulkan_lightmap.c | 64 ++++++++++++++----- libs/video/renderer/vulkan/vulkan_scene.c | 5 +- 8 files changed, 85 insertions(+), 63 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 64c82ace1..1c7824967 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -355,6 +355,7 @@ typedef struct bspctx_s { struct scrap_s *light_scrap; struct qfv_stagebuf_s *light_stage; + VkDescriptorSet lightmap_descriptor; int num_models; ///< number of loaded brush models bsp_model_t *models; ///< all loaded brush models diff --git a/include/QF/Vulkan/qf_lightmap.h b/include/QF/Vulkan/qf_lightmap.h index d9371dbaa..ea455aafd 100644 --- a/include/QF/Vulkan/qf_lightmap.h +++ b/include/QF/Vulkan/qf_lightmap.h @@ -43,7 +43,7 @@ struct transform_s; 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_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)); void Vulkan_FlushLightmaps (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 3292e794a..069e49797 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -250,6 +250,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_iqm.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_output.c \ libs/video/renderer/vulkan/vulkan_palette.c \ diff --git a/libs/video/renderer/vulkan/rp_main_fwd.plist b/libs/video/renderer/vulkan/rp_main_fwd.plist index 957e8a645..cc971a0af 100644 --- a/libs/video/renderer/vulkan/rp_main_fwd.plist +++ b/libs/video/renderer/vulkan/rp_main_fwd.plist @@ -223,22 +223,17 @@ properties = { brush = { shader = { - depth_vertex = { - stage = vertex; - name = main; - module = $builtin/bsp_depth.vert; - }; - gbuf_vertex = { + vertex = { stage = vertex; name = main; module = $builtin/bsp_gbuf.vert; }; - gbuf_geometry = { + geometry = { stage = geometry; name = main; module = $builtin/bsp_gbuf.geom; }; - gbuf_fragment = { + fragment = { stage = fragment; name = main; module = $builtin/quakebsp.frag; @@ -299,7 +294,7 @@ properties = { }; layout = { descriptorSets = (matrix_set, entity_set, oit_set, - // surface skybox + // surface skybox/lightmap texture_set, texture_set); pushConstants = { fragment = { @@ -313,17 +308,12 @@ properties = { }; alias = { shader = { - depth_vertex = { - stage = vertex; - name = main; - module = $builtin/alias_depth.vert; - }; - gbuf_vertex = { + vertex = { stage = vertex; name = main; module = $builtin/alias.vert; }; - gbuf_fragment = { + fragment = { stage = fragment; name = main; module = $builtin/alias.frag; @@ -364,17 +354,7 @@ properties = { { size = 4; offset = 0; constantID = 0; }, ); }; - depth_vertex = { - stage = vertex; - name = main; - module = $builtin/iqm.vert; - specializationInfo = { - @inherit = $iqm.shader.specialization; - // IQMDepthOnly - data = "array(1, 0)"; - }; - }; - gbuf_vertex = { + vertex = { stage = vertex; name = main; module = $builtin/iqm.vert; @@ -384,7 +364,7 @@ properties = { data = "array(0, 0)"; }; }; - gbuf_fragment = { + fragment = { stage = fragment; name = main; module = $builtin/iqm_fwd.frag; @@ -431,22 +411,17 @@ properties = { }; sprite = { shader = { - depth_vertex = { - stage = vertex; - name = main; - module = $builtin/sprite_depth.vert; - }; depth_fragment = { stage = fragment; name = main; module = $builtin/sprite_depth.frag; }; - gbuf_vertex = { + vertex = { stage = vertex; name = main; module = $builtin/sprite_gbuf.vert; }; - gbuf_fragment = { + fragment = { stage = fragment; name = main; module = $builtin/sprite.frag; @@ -1112,9 +1087,9 @@ renderpasses = { ); stages = ( - $brush.shader.gbuf_vertex, - $brush.shader.gbuf_geometry, - $brush.shader.gbuf_fragment, + $brush.shader.vertex, + $brush.shader.geometry, + $brush.shader.fragment, ); vertexInput = $brush.vertexInput; inputAssembly = $brush.inputAssembly; @@ -1128,8 +1103,8 @@ renderpasses = { ); stages = ( - $alias.shader.gbuf_vertex, - $alias.shader.gbuf_fragment, + $alias.shader.vertex, + $alias.shader.fragment, ); vertexInput = $alias.vertexInput; inputAssembly = $alias.inputAssembly; @@ -1143,8 +1118,8 @@ renderpasses = { ); stages = ( - $iqm.shader.gbuf_vertex, - $iqm.shader.gbuf_fragment, + $iqm.shader.vertex, + $iqm.shader.fragment, ); vertexInput = $iqm.vertexInput; inputAssembly = $iqm.inputAssembly; @@ -1157,8 +1132,8 @@ renderpasses = { ); stages = ( - $sprite.shader.gbuf_vertex, - $sprite.shader.gbuf_fragment, + $sprite.shader.vertex, + $sprite.shader.fragment, ); vertexInput = $sprite.vertexInput; inputAssembly = $sprite.inputAssembly; diff --git a/libs/video/renderer/vulkan/shader/quakebsp.frag b/libs/video/renderer/vulkan/shader/quakebsp.frag index 71aede2ab..32942539e 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.frag +++ b/libs/video/renderer/vulkan/shader/quakebsp.frag @@ -1,6 +1,7 @@ #version 450 layout (set = 3, binding = 0) uniform sampler2DArray Texture; +layout (set = 4, binding = 0) uniform sampler2D Lightmap; layout (push_constant) uniform PushConstants { vec4 fog; @@ -35,6 +36,7 @@ main (void) vec4 c = texture (Texture, t_st) * color; vec4 e = texture (Texture, e_st); + vec4 l = texture (Lightmap, l_st); - frag_color = c;//fogBlend (c); + frag_color = c * l + e;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index c9b71fad3..3f11fe0d0 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -74,6 +74,7 @@ #define TEX_SET 3 #define SKYBOX_SET 4 +#define LIGHTMAP_SET 4 typedef struct bsp_push_constants_s { quat_t fog; @@ -1270,6 +1271,9 @@ bsp_draw_queue (const exprval_t **params, exprval_t *result, exprctx_t *ectx) if (queue == QFV_bspSky) { vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; 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; @@ -1506,6 +1510,10 @@ Vulkan_Bsp_Setup (vulkan_ctx_t *ctx) bframe->entid_offset = i * entid_size; } + bctx->lightmap_descriptor + = Vulkan_CreateCombinedImageSampler (ctx, + Vulkan_LightmapImageView (ctx), + bctx->sampler); bctx->skybox_descriptor = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, bctx->sampler); diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 9eecc8616..894bec381 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -45,7 +45,6 @@ #include "QF/sys.h" #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" -#include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/scrap.h" #include "QF/scene/entity.h" @@ -57,9 +56,10 @@ #define LUXEL_SIZE 4 static inline void -add_dynamic_lights (const transform_t *transform, msurface_t *surf, +add_dynamic_lights (transform_t transform, msurface_t *surf, float *block) { +#if 0 unsigned lnum; int sd, td; float dist, rad, minlight; @@ -128,10 +128,11 @@ add_dynamic_lights (const transform_t *transform, msurface_t *surf, } } } +#endif } 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) { 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 @@ -224,25 +259,22 @@ void Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; - int i, j; - model_t *m; - mod_brush_t *brush; QFV_ScrapClear (bctx->light_scrap); r_framecount = 1; // no dlightcache - for (j = 1; j < num_models; j++) { - m = models[j]; + for (int j = 1; j < num_models; j++) { + auto m = models[j]; if (!m) break; if (m->path[0] == '*' || m->type != mod_brush) { // sub model surfaces are processed as part of the main model continue; } - brush = &m->brush; + auto brush = &m->brush; // 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; surf->lightpic = 0; // paranoia if (surf->flags & SURF_DRAWTURB) { @@ -252,11 +284,13 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) continue; } vulkan_create_surf_lightmap (surf, ctx); + vulkan_build_lightmap (brush, surf, ctx); } } + QFV_ScrapFlush (bctx->light_scrap); - for (j = 1; j < num_models; j++) { - m = models[j]; + for (int j = 1; j < num_models; j++) { + auto m = models[j]; if (!m) { 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 continue; } - brush = &m->brush; + auto brush = &m->brush; // 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; if (surf->lightpic) { - Vulkan_BuildLightMap (0, brush, surf, ctx); + Vulkan_BuildLightMap (nulltransform, brush, surf, ctx); } } } diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 57aabaf3f..0d2569546 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -41,6 +41,7 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lighting.h" +#include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" @@ -286,7 +287,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) R_ClearParticles (); 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_LoadLights (scene, ctx); + //Vulkan_LoadLights (scene, ctx); }