vk: rt: optimize hires skybox loading
- Do not load skybox at all if there are no SURF_DRAWSKY, #706, #579 - Do not reload the same skybox, #706 Also refactor skybox loading a bit. Prepare for KTX2 skyboxes.
This commit is contained in:
parent
f3f14ac968
commit
3cbc11a8f0
|
@ -1011,3 +1011,23 @@ This would need the same as above, plus:
|
|||
- A: probably should still do it on GPU lol
|
||||
|
||||
This would also allow passing arbitrary per-pixel data from shaders, which would make shader debugging much much easier.
|
||||
|
||||
# 2023-12-12 E346
|
||||
## Skyboxes
|
||||
### Current state
|
||||
- `R_TextureSetupSky()`
|
||||
- called from:
|
||||
← `vk_scene.c`/`R_NewMap()`
|
||||
← engine ?? -- seems optional, r_soft doesn't implement it. Set on:
|
||||
- `skybox` console command
|
||||
- certain movevars change, whatever that is
|
||||
- `unloadSkybox()`
|
||||
- for [pbr/, old/] do
|
||||
- `CheckSkybox()`
|
||||
- make sidenames and check whether files exist
|
||||
- `loadSkybox()`
|
||||
- `unloadSkybox()`
|
||||
- make sidenames
|
||||
- `FS_LoadImage()` and `ImageProcess()`
|
||||
- `R_VkTextureSkyboxUpload(sides)`
|
||||
- if failed and not default already: `R_TextureSetupSky(default)` (recurse)
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
# 2023-12-14 E346
|
||||
- [x] Optimize skybox loading, #706
|
||||
- [x] Do not load skybox when there are no SURF_DRAWSKY, #579
|
||||
- [x] Do not reload the same skybox
|
||||
- [ ] Load skyboxes from KTX2
|
||||
- [ ] do not generate mips for skybox
|
||||
- [ ] add skybox test
|
||||
|
||||
# 2023-12-11 E345
|
||||
- [x] fix incorrect basecolor brdf multiplication, #666
|
||||
- [x] fix black dielectrics, #666
|
||||
- [x] fix incorrect basecolor brdf multiplication, #666
|
||||
- [x] fixup skybox glitches caused by #666 fix
|
||||
- [ ] Patch overlay textures (#696) → turned out to be much more difficult than expected.
|
||||
- [x] Do not patch sprite textures for traditional raster, #695
|
||||
- [x] fixup skybox glitches caused by #666 fix
|
||||
|
||||
# 2023-12-05 E342
|
||||
- [x] tone down the specular indirect blur
|
||||
|
@ -17,7 +26,6 @@ Longer-term agenda for current season:
|
|||
- [ ] Tools:
|
||||
- [ ] Shader profiling. Measure impact of changes. Regressions.
|
||||
- [ ] Better PBR math, e.g.:
|
||||
- [ ] fix black dielectrics, #666
|
||||
- [ ] Transparency:
|
||||
- [ ] Figure out why additive transparency differs visibly from raster
|
||||
- [ ] Extract and specialize effects, e.g.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "vk_framectl.h"
|
||||
#include "vk_cvar.h"
|
||||
#include "vk_combuf.h"
|
||||
#include "stringview.h"
|
||||
|
||||
#include "profiler.h"
|
||||
|
||||
|
@ -302,23 +303,9 @@ static void handlePause( uint32_t prev_frame_index ) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO move this to vk_common or something
|
||||
int stringViewCmp(const_string_view_t sv, const char* s) {
|
||||
for (int i = 0; i < sv.len; ++i) {
|
||||
const int d = sv.s[i] - s[i];
|
||||
if (d != 0)
|
||||
return d;
|
||||
if (s[i] == '\0')
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check that both strings end the same
|
||||
return '\0' - s[sv.len];
|
||||
}
|
||||
|
||||
static int findMetricIndexByName( const_string_view_t name) {
|
||||
for (int i = 0; i < g_speeds.metrics_count; ++i) {
|
||||
if (stringViewCmp(name, g_speeds.metrics[i].name) == 0)
|
||||
if (svCmp(name, g_speeds.metrics[i].name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -327,7 +314,7 @@ static int findMetricIndexByName( const_string_view_t name) {
|
|||
|
||||
static int findGraphIndexByName( const_string_view_t name) {
|
||||
for (int i = 0; i < g_speeds.graphs_count; ++i) {
|
||||
if (stringViewCmp(name, g_speeds.graphs[i].name) == 0)
|
||||
if (svCmp(name, g_speeds.graphs[i].name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "r_speeds.h"
|
||||
#include "profiler.h"
|
||||
#include "unordered_roadmap.h"
|
||||
#include "stringview.h"
|
||||
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "crtlib.h"
|
||||
|
@ -28,10 +29,9 @@ static struct {
|
|||
|
||||
vk_texture_t all[MAX_TEXTURES];
|
||||
urmom_desc_t all_desc;
|
||||
} g_textures;
|
||||
|
||||
// FIXME imported from vk_textures.h
|
||||
void unloadSkybox( void );
|
||||
char current_skybox_name[MAX_STRING];
|
||||
} g_textures;
|
||||
|
||||
static void createDefaultTextures( void );
|
||||
static void destroyDefaultTextures( void );
|
||||
|
@ -287,7 +287,7 @@ static void createDefaultTextures( void )
|
|||
rgbdata_t *sides[6];
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFFFFFFFF;
|
||||
((uint *)pic->buffer)[x] = 0;
|
||||
|
||||
sides[0] = pic;
|
||||
sides[1] = pic;
|
||||
|
@ -296,7 +296,8 @@ static void createDefaultTextures( void )
|
|||
sides[4] = pic;
|
||||
sides[5] = pic;
|
||||
|
||||
R_VkTexturesSkyboxUpload( "skybox_placeholder", sides, kColorspaceGamma, true );
|
||||
const qboolean is_placeholder = true;
|
||||
R_VkTexturesSkyboxUpload( "skybox_placeholder", sides, kColorspaceGamma, is_placeholder );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -808,10 +809,10 @@ int R_TextureUploadFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flag
|
|||
return insert.index;
|
||||
}
|
||||
|
||||
static struct {
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
uint flags;
|
||||
} g_skybox_info[6] = {
|
||||
} k_skybox_info[6] = {
|
||||
{"rt", IMAGE_ROT_90},
|
||||
{"lf", IMAGE_FLIP_Y | IMAGE_ROT_90 | IMAGE_FLIP_X},
|
||||
{"bk", IMAGE_FLIP_Y},
|
||||
|
@ -824,7 +825,7 @@ static struct {
|
|||
#define SKYBOX_HLSTYLE 1
|
||||
#define SKYBOX_Q1STYLE 2
|
||||
|
||||
static int CheckSkybox( const char *name )
|
||||
static int CheckSkyboxSides( const char *name )
|
||||
{
|
||||
const char *skybox_ext[] = { "png", "dds", "tga", "bmp" };
|
||||
int i, j, num_checked_sides;
|
||||
|
@ -837,10 +838,9 @@ static int CheckSkybox( const char *name )
|
|||
for( j = 0; j < 6; j++ )
|
||||
{
|
||||
// build side name
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s%s.%s", name, g_skybox_info[j].suffix, skybox_ext[i] );
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s%s.%s", name, k_skybox_info[j].suffix, skybox_ext[i] );
|
||||
if( gEngine.fsapi->FileExists( sidename, false ))
|
||||
num_checked_sides++;
|
||||
|
||||
}
|
||||
|
||||
if( num_checked_sides == 6 )
|
||||
|
@ -849,7 +849,7 @@ static int CheckSkybox( const char *name )
|
|||
for( j = 0; j < 6; j++ )
|
||||
{
|
||||
// build side name
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s_%s.%s", name, g_skybox_info[j].suffix, skybox_ext[i] );
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s_%s.%s", name, k_skybox_info[j].suffix, skybox_ext[i] );
|
||||
if( gEngine.fsapi->FileExists( sidename, false ))
|
||||
num_checked_sides++;
|
||||
}
|
||||
|
@ -861,91 +861,150 @@ static int CheckSkybox( const char *name )
|
|||
return SKYBOX_MISSED;
|
||||
}
|
||||
|
||||
static qboolean loadSkybox( const char *prefix, int style ) {
|
||||
static qboolean loadSkyboxSides( const char *prefix, int style ) {
|
||||
if( !checkTextureName( prefix ))
|
||||
return false;
|
||||
|
||||
int i;
|
||||
rgbdata_t *sides[6];
|
||||
qboolean success = false;
|
||||
int i;
|
||||
|
||||
// release old skybox
|
||||
unloadSkybox();
|
||||
DEBUG( "SKY: " );
|
||||
|
||||
for( i = 0; i < 6; i++ ) {
|
||||
char sidename[MAX_STRING];
|
||||
if( style == SKYBOX_HLSTYLE )
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s%s", prefix, g_skybox_info[i].suffix );
|
||||
else Q_snprintf( sidename, sizeof( sidename ), "%s_%s", prefix, g_skybox_info[i].suffix );
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s%s", prefix, k_skybox_info[i].suffix );
|
||||
else Q_snprintf( sidename, sizeof( sidename ), "%s_%s", prefix, k_skybox_info[i].suffix );
|
||||
|
||||
sides[i] = gEngine.FS_LoadImage( sidename, NULL, 0);
|
||||
if (!sides[i] || !sides[i]->buffer)
|
||||
break;
|
||||
|
||||
{
|
||||
uint img_flags = g_skybox_info[i].flags;
|
||||
uint img_flags = k_skybox_info[i].flags;
|
||||
// we need to expand image into RGBA buffer
|
||||
if( sides[i]->type == PF_INDEXED_24 || sides[i]->type == PF_INDEXED_32 )
|
||||
img_flags |= IMAGE_FORCE_RGBA;
|
||||
gEngine.Image_Process( &sides[i], 0, 0, img_flags, 0.f );
|
||||
}
|
||||
DEBUG( "%s%s%s", prefix, g_skybox_info[i].suffix, i != 5 ? ", " : ". " );
|
||||
DEBUG( "%s%s%s", prefix, k_skybox_info[i].suffix, i != 5 ? ", " : ". " );
|
||||
}
|
||||
|
||||
if( i != 6 )
|
||||
goto cleanup;
|
||||
|
||||
if( !checkTextureName( prefix ))
|
||||
goto cleanup;
|
||||
|
||||
success = R_VkTexturesSkyboxUpload( prefix, sides, kColorspaceGamma, false );
|
||||
{
|
||||
const qboolean is_placeholder = false;
|
||||
success = R_VkTexturesSkyboxUpload( prefix, sides, kColorspaceGamma, is_placeholder );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
for (int j = 0; j < i; ++j)
|
||||
gEngine.FS_FreeImage( sides[j] ); // release source texture
|
||||
|
||||
if (success) {
|
||||
tglob.fCustomSkybox = true;
|
||||
DEBUG( "Skybox done" );
|
||||
} else {
|
||||
ERR( "Skybox failed" );
|
||||
unloadSkybox();
|
||||
}
|
||||
if (success)
|
||||
DEBUG( "Loaded sided skybox %s", prefix );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static const char *skybox_default = "desert";
|
||||
static const char *skybox_prefixes[] = { "pbr/env/%s", "gfx/env/%s" };
|
||||
static void makeSkyboxPath(const char *skyboxname, const char *skybox_prefix, char *out_name, int out_length ) {
|
||||
Q_snprintf( out_name, out_length, skybox_prefix, skyboxname );
|
||||
COM_StripExtension( out_name );
|
||||
|
||||
void R_TextureSetupSky( const char *skyboxname ) {
|
||||
if( !COM_CheckString( skyboxname ))
|
||||
// kill the underline suffix to find them manually later
|
||||
const int len = Q_strlen( out_name );
|
||||
|
||||
if( out_name[len - 1] == '_' )
|
||||
out_name[len - 1] = '\0';
|
||||
}
|
||||
|
||||
static qboolean skyboxLoadSides(const_string_view_t base, const char *prefix) {
|
||||
char loadname[MAX_STRING];
|
||||
Q_snprintf( loadname, sizeof( loadname ), prefix, base.len, base.s );
|
||||
|
||||
// TODO merge together as in gl_warp.c
|
||||
const int style = CheckSkyboxSides( loadname );
|
||||
return loadSkyboxSides(loadname, style);
|
||||
}
|
||||
|
||||
static void skyboxUnload( void ) {
|
||||
R_VkTexturesSkyboxUnload();
|
||||
g_textures.current_skybox_name[0] = '\0';
|
||||
}
|
||||
|
||||
static qboolean skyboxTryLoad( const char *skyboxname, qboolean force_reload ) {
|
||||
// Check whether we even need skybox
|
||||
if (!tglob.current_map_has_surf_sky) {
|
||||
DEBUG("No SURF_DRAWSKY surfaces in this map, skipping loading skybox");
|
||||
skyboxUnload();
|
||||
return true;
|
||||
}
|
||||
|
||||
const_string_view_t basename = svStripExtension(svFromNullTerminated(skyboxname));
|
||||
if (basename.len > 0 && basename.s[basename.len - 1] == '_')
|
||||
basename.len--;
|
||||
|
||||
if( !basename.len )
|
||||
{
|
||||
unloadSkybox();
|
||||
return; // clear old skybox
|
||||
skyboxUnload();
|
||||
return true; // clear old skybox
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(skybox_prefixes); ++i) {
|
||||
char loadname[MAX_STRING];
|
||||
int style, len;
|
||||
// Do not reload the same skybox
|
||||
// TODO except explicit patches reload
|
||||
if (!force_reload && svCmp(basename, g_textures.current_skybox_name) == 0)
|
||||
return true;
|
||||
|
||||
Q_snprintf( loadname, sizeof( loadname ), skybox_prefixes[i], skyboxname );
|
||||
COM_StripExtension( loadname );
|
||||
// Try loading skybox in this sequence:
|
||||
// 1. Single pbr/env/<sky>.ktx2 cubemap
|
||||
{
|
||||
char ktx_path[MAX_STRING];
|
||||
Q_snprintf(ktx_path, sizeof(ktx_path), "pbr/env/%.*s.ktx2", basename.len, basename.s);
|
||||
|
||||
// kill the underline suffix to find them manually later
|
||||
len = Q_strlen( loadname );
|
||||
|
||||
if( loadname[len - 1] == '_' )
|
||||
loadname[len - 1] = '\0';
|
||||
style = CheckSkybox( loadname );
|
||||
|
||||
if (loadSkybox(loadname, style))
|
||||
return;
|
||||
if (R_VkTexturesSkyboxUploadKTX(ktx_path))
|
||||
goto success;
|
||||
}
|
||||
|
||||
// Try default skybox if failed
|
||||
if (Q_stricmp(skyboxname, skybox_default) != 0) {
|
||||
WARN("missed or incomplete skybox '%s', trying default '%s'", skyboxname, skybox_default);
|
||||
R_TextureSetupSky( skybox_default );
|
||||
// 2. pbr/env/<sky>_<side>.{png, ...} sides
|
||||
if (skyboxLoadSides(basename, "pbr/env/%.*s"))
|
||||
goto success;
|
||||
|
||||
// 3. Old gfx/env/<sky>_<side>.{png, ...} sides
|
||||
if (skyboxLoadSides(basename, "gfx/env/%.*s"))
|
||||
goto success;
|
||||
|
||||
return false;
|
||||
|
||||
success:
|
||||
svStrncpy(basename, g_textures.current_skybox_name, sizeof(g_textures.current_skybox_name));
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *k_skybox_default = "desert";
|
||||
|
||||
void skyboxLoad( const char *skyboxname, qboolean is_custom, qboolean force_reload ) {
|
||||
DEBUG("%s: skyboxname='%s' is_custom=%d force_reload=%d", __FUNCTION__, skyboxname, is_custom, force_reload);
|
||||
|
||||
if (!skyboxTryLoad(skyboxname, force_reload)) {
|
||||
WARN("missed or incomplete skybox '%s', trying default '%s'", skyboxname, k_skybox_default);
|
||||
if (!skyboxTryLoad(k_skybox_default, force_reload)) {
|
||||
ERR("Failed to load default skybox \"%s\"", k_skybox_default);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tglob.fCustomSkybox = is_custom;
|
||||
}
|
||||
|
||||
void R_TextureSetupCustomSky( const char *skyboxname ) {
|
||||
const qboolean is_custom = true;
|
||||
const qboolean force_reload = false;
|
||||
skyboxLoad(skyboxname, is_custom, force_reload);
|
||||
}
|
||||
|
||||
void R_TextureSetupSky( const char *skyboxname, qboolean force_reload ) {
|
||||
const qboolean is_custom = false;
|
||||
skyboxLoad(skyboxname, is_custom, force_reload);
|
||||
}
|
||||
|
||||
// FIXME move to r_textures_extra.h
|
||||
|
|
|
@ -23,6 +23,8 @@ typedef struct vk_textures_global_s
|
|||
|
||||
// TODO wire it up for ref_interface_t return
|
||||
qboolean fCustomSkybox;
|
||||
|
||||
qboolean current_map_has_surf_sky;
|
||||
} vk_textures_global_t;
|
||||
|
||||
// TODO rename this consistently
|
||||
|
@ -37,7 +39,7 @@ void R_TexturesShutdown( void );
|
|||
int R_TextureFindByName( const char *name );
|
||||
const char* R_TextureGetNameByIndex( unsigned int texnum );
|
||||
|
||||
void R_TextureSetupSky( const char *skyboxname );
|
||||
void R_TextureSetupCustomSky( const char *skyboxname );
|
||||
|
||||
int R_TextureUploadFromFile( const char *name, const byte *buf, size_t size, int flags );
|
||||
int R_TextureUploadFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update_only );
|
||||
|
@ -67,3 +69,5 @@ int R_TextureFindByNameLike( const char *texture_name );
|
|||
|
||||
struct vk_texture_s;
|
||||
struct vk_texture_s *R_TextureGetByIndex( uint index );
|
||||
|
||||
void R_TextureSetupSky( const char *skyboxname, qboolean force_reload );
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#include "stringview.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
const_string_view_t svFromNullTerminated( const char *s ) {
|
||||
return (const_string_view_t){.len = s?strlen(s):0, .s = s};
|
||||
}
|
||||
|
||||
int svCmp(const_string_view_t sv, const char* s) {
|
||||
for (int i = 0; i < sv.len; ++i) {
|
||||
const int d = sv.s[i] - s[i];
|
||||
if (d != 0)
|
||||
return d;
|
||||
if (s[i] == '\0')
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check that both strings end the same
|
||||
return '\0' - s[sv.len];
|
||||
}
|
||||
|
||||
const_string_view_t svStripExtension(const_string_view_t sv) {
|
||||
for (int i = sv.len - 1; i >= 0; --i) {
|
||||
const char c = sv.s[i];
|
||||
if (c == '.')
|
||||
return (const_string_view_t){ .len = i, .s = sv.s };
|
||||
|
||||
if (c == '/' || c == '\\' || c == ':')
|
||||
break;
|
||||
}
|
||||
|
||||
return sv;
|
||||
}
|
||||
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
void svStrncpy(const_string_view_t sv, char *dest, int size) {
|
||||
const int to_copy = MIN(sv.len, size - 1);
|
||||
memcpy(dest, sv.s, to_copy);
|
||||
dest[to_copy] = '\0';
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
const char *s;
|
||||
int len;
|
||||
} const_string_view_t;
|
||||
|
||||
const_string_view_t svFromNullTerminated( const char *s );
|
||||
|
||||
int svCmp(const_string_view_t sv, const char* s);
|
||||
void svStrncpy(const_string_view_t sv, char *dest, int size);
|
||||
|
||||
const_string_view_t svStripExtension(const_string_view_t sv);
|
|
@ -83,6 +83,7 @@ typedef struct {
|
|||
int animated_count;
|
||||
int conveyors_count;
|
||||
int conveyors_vertices_count;
|
||||
int sky_surfaces_count;
|
||||
|
||||
water_model_sizes_t water, side_water;
|
||||
} model_sizes_t;
|
||||
|
@ -992,8 +993,10 @@ static model_sizes_t computeSizes( const model_t *mod, qboolean is_worldmodel )
|
|||
sizes.conveyors_count++;
|
||||
sizes.conveyors_vertices_count += surf->numedges;
|
||||
break;
|
||||
case BrushSurface_Regular:
|
||||
case BrushSurface_Sky:
|
||||
sizes.sky_surfaces_count++;
|
||||
break;
|
||||
case BrushSurface_Regular:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1610,6 +1613,11 @@ qboolean R_BrushModelLoad( model_t *mod, qboolean is_worldmodel ) {
|
|||
|
||||
const model_sizes_t sizes = computeSizes( mod, is_worldmodel );
|
||||
|
||||
if (is_worldmodel) {
|
||||
tglob.current_map_has_surf_sky = sizes.sky_surfaces_count != 0;
|
||||
DEBUG("sky_surfaces_count=%d, current_map_has_surf_sky=%d", sizes.sky_surfaces_count, tglob.current_map_has_surf_sky);
|
||||
}
|
||||
|
||||
if (sizes.num_surfaces != 0) {
|
||||
if (!createRenderModel(mod, bmodel, sizes, is_worldmodel)) {
|
||||
ERR("Could not load brush model %s", mod->name);
|
||||
|
|
|
@ -28,12 +28,5 @@ inline static int clampi32(int v, int min, int max) {
|
|||
return v;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *s;
|
||||
int len;
|
||||
} const_string_view_t;
|
||||
|
||||
int stringViewCmp(const_string_view_t sv, const char* s);
|
||||
|
||||
extern ref_api_t gEngine;
|
||||
extern ref_globals_t *gpGlobals;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "vk_logs.h"
|
||||
#include "vk_cvar.h"
|
||||
#include "stringview.h"
|
||||
|
||||
uint32_t g_log_debug_bits = 0;
|
||||
|
||||
|
@ -21,7 +22,7 @@ void R_LogSetVerboseModules( const char *p ) {
|
|||
|
||||
for (int i = 0; i < COUNTOF(g_log_module_pairs); ++i) {
|
||||
const struct log_pair_t *const pair = g_log_module_pairs + i;
|
||||
if (stringViewCmp(name, pair->name) == 0) {
|
||||
if (svCmp(name, pair->name) == 0) {
|
||||
gEngine.Con_Reportf("Enabling verbose logs for module \"%.*s\"\n", name.len, name.s);
|
||||
bit = pair->bit;
|
||||
break;
|
||||
|
|
|
@ -559,7 +559,7 @@ static const ref_interface_t gReffuncs =
|
|||
.R_GetTextureOriginalBuffer = R_GetTextureOriginalBuffer_UNUSED,
|
||||
.GL_LoadTextureFromBuffer = R_TextureUploadFromBuffer,
|
||||
.GL_ProcessTexture = GL_ProcessTexture_UNUSED,
|
||||
.R_SetupSky = R_TextureSetupSky,
|
||||
.R_SetupSky = R_TextureSetupCustomSky,
|
||||
|
||||
// 2D
|
||||
R_Set2DMode,
|
||||
|
|
|
@ -118,13 +118,14 @@ static int findResourceOrEmptySlot(const char *name) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void VK_RayNewMap( void ) {
|
||||
void VK_RayNewMapBegin( void ) {
|
||||
RT_VkAccelNewMap();
|
||||
RT_RayModel_Clear();
|
||||
}
|
||||
|
||||
void VK_RayNewMapEnd( void ) {
|
||||
g_rtx.res[ExternalResource_skybox].resource = (vk_resource_t){
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
// FIXME we should pick tglob.dii_all_textures here directly
|
||||
.value = (vk_descriptor_value_t){
|
||||
.image = R_VkTexturesGetSkyboxDescriptorImageInfo(),
|
||||
},
|
||||
|
@ -132,7 +133,6 @@ void VK_RayNewMap( void ) {
|
|||
|
||||
g_rtx.res[ExternalResource_blue_noise_texture].resource = (vk_resource_t){
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
// FIXME we should pick tglob.dii_all_textures here directly
|
||||
.value = (vk_descriptor_value_t){
|
||||
.image = R_VkTexturesGetBlueNoiseImageInfo(),
|
||||
},
|
||||
|
|
|
@ -27,7 +27,8 @@ typedef struct {
|
|||
} vk_ray_frame_render_args_t;
|
||||
void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args);
|
||||
|
||||
void VK_RayNewMap( void );
|
||||
void VK_RayNewMapBegin( void );
|
||||
void VK_RayNewMapEnd( void );
|
||||
|
||||
qboolean VK_RayInit( void );
|
||||
void VK_RayShutdown( void );
|
||||
|
|
|
@ -87,30 +87,6 @@ static void loadLights( const model_t *const map ) {
|
|||
RT_LightsLoadEnd();
|
||||
}
|
||||
|
||||
// Clears all old map data
|
||||
static void mapLoadBegin( const model_t *const map ) {
|
||||
VK_EntityDataClear();
|
||||
|
||||
// Depends on VK_EntityDataClear()
|
||||
R_StudioCacheClear();
|
||||
R_GeometryBuffer_MapClear();
|
||||
|
||||
VK_ClearLightmap();
|
||||
|
||||
// This is to ensure that we have computed lightstyles properly
|
||||
VK_RunLightStyles();
|
||||
|
||||
if (vk_core.rtx)
|
||||
VK_RayNewMap();
|
||||
|
||||
RT_LightsNewMap(map);
|
||||
}
|
||||
|
||||
static void mapLoadEnd(const model_t *const map) {
|
||||
// TODO should we do something like R_BrushEndLoad?
|
||||
VK_UploadLightmap();
|
||||
}
|
||||
|
||||
static void preloadModels( void ) {
|
||||
const int num_models = gEngine.EngineGetParm( PARM_NUMMODELS, 0 );
|
||||
|
||||
|
@ -145,8 +121,22 @@ static void preloadModels( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
static void loadMap(const model_t* const map) {
|
||||
mapLoadBegin(map);
|
||||
static void loadMap(const model_t* const map, qboolean force_reload) {
|
||||
VK_EntityDataClear();
|
||||
|
||||
// Depends on VK_EntityDataClear()
|
||||
R_StudioCacheClear();
|
||||
R_GeometryBuffer_MapClear();
|
||||
|
||||
VK_ClearLightmap();
|
||||
|
||||
// This is to ensure that we have computed lightstyles properly
|
||||
VK_RunLightStyles();
|
||||
|
||||
if (vk_core.rtx)
|
||||
VK_RayNewMapBegin();
|
||||
|
||||
RT_LightsNewMap(map);
|
||||
|
||||
R_SpriteNewMapFIXME();
|
||||
|
||||
|
@ -162,8 +152,22 @@ static void loadMap(const model_t* const map) {
|
|||
|
||||
preloadModels();
|
||||
|
||||
// Can only do after preloadModels(), as we need to know whether there are SURF_DRAWSKY
|
||||
R_TextureSetupSky( gEngine.pfnGetMoveVars()->skyName, force_reload );
|
||||
|
||||
loadLights(map);
|
||||
mapLoadEnd(map);
|
||||
|
||||
// TODO should we do something like R_BrushEndLoad?
|
||||
VK_UploadLightmap();
|
||||
|
||||
// This is needed mainly for picking up skybox only after it has been loaded
|
||||
// Most of the things here could be simplified if we had less imperative style for this renderer:
|
||||
// - Group everything into modules with explicit dependencies, then init/shutdown/newmap order could
|
||||
// be automatic and correct.
|
||||
// - "Rendergraph"-like dependencies for resources (like textures, materials, skybox, ...). Then they
|
||||
// could be loaded lazily when needed, and after all the needed info for them has been collected.
|
||||
if (vk_core.rtx)
|
||||
VK_RayNewMapEnd();
|
||||
}
|
||||
|
||||
static void reloadPatches( void ) {
|
||||
|
@ -176,7 +180,8 @@ static void reloadPatches( void ) {
|
|||
R_BrushModelDestroyAll();
|
||||
|
||||
const model_t *const map = gEngine.pfnGetModelByIndex( 1 );
|
||||
loadMap(map);
|
||||
const qboolean force_reload = true;
|
||||
loadMap(map, force_reload);
|
||||
|
||||
R_VkStagingFlushSync();
|
||||
}
|
||||
|
@ -260,9 +265,8 @@ void R_NewMap( void ) {
|
|||
|
||||
// Make sure that we're not rendering anything before starting to mess with GPU objects
|
||||
XVK_CHECK(vkDeviceWaitIdle(vk_core.device));
|
||||
R_TextureSetupSky( gEngine.pfnGetMoveVars()->skyName );
|
||||
|
||||
loadMap(map);
|
||||
const qboolean force_reload = false;
|
||||
loadMap(map, force_reload);
|
||||
|
||||
R_StudioResetPlayerModels();
|
||||
}
|
||||
|
|
|
@ -58,9 +58,6 @@ void BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, int flags
|
|||
static VkSampler pickSamplerForFlags( texFlags_t flags );
|
||||
static qboolean uploadTexture(int index, vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint);
|
||||
|
||||
// FIXME should be static
|
||||
void unloadSkybox( void );
|
||||
|
||||
// Hardcode blue noise texture size to 64x64x64
|
||||
#define BLUE_NOISE_SIZE 64
|
||||
#define BLUE_NOISE_NAME_F "bluenoise/LDR_RGBA_%d.png"
|
||||
|
@ -189,7 +186,7 @@ qboolean R_VkTexturesInit( void ) {
|
|||
static void textureDestroy( unsigned int index );
|
||||
|
||||
void R_VkTexturesShutdown( void ) {
|
||||
unloadSkybox();
|
||||
R_VkTexturesSkyboxUnload();
|
||||
R_VkTextureDestroy(-1, &g_vktextures.cubemap_placeholder);
|
||||
R_VkTextureDestroy(-1, &g_vktextures.blue_noise);
|
||||
|
||||
|
@ -581,13 +578,12 @@ void R_VkTextureDestroy( int index, vk_texture_t *tex ) {
|
|||
// TODO tex->vk.descriptor_unorm = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void unloadSkybox( void ) {
|
||||
void R_VkTexturesSkyboxUnload(void) {
|
||||
DEBUG("%s", __FUNCTION__);
|
||||
if (g_vktextures.skybox_cube.vk.image.image) {
|
||||
R_VkTextureDestroy( -1, &g_vktextures.skybox_cube );
|
||||
memset(&g_vktextures.skybox_cube, 0, sizeof(g_vktextures.skybox_cube));
|
||||
}
|
||||
|
||||
tglob.fCustomSkybox = false;
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo R_VkTexturesGetSkyboxDescriptorImageInfo( void ) {
|
||||
|
@ -606,6 +602,11 @@ qboolean R_VkTexturesSkyboxUpload( const char *name, rgbdata_t *const sides[6],
|
|||
return uploadTexture(-1, dest, sides, 6, true, colorspace_hint);
|
||||
}
|
||||
|
||||
qboolean R_VkTexturesSkyboxUploadKTX( const char *filename ) {
|
||||
ERR("%s(%s): not implemented", __FUNCTION__, filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
VkDescriptorSet R_VkTextureGetDescriptorUnorm( uint index ) {
|
||||
ASSERT( index < MAX_TEXTURES );
|
||||
// TODO make an array of unorm descriptors
|
||||
|
|
|
@ -35,6 +35,8 @@ qboolean R_VkTexturesInit( void );
|
|||
void R_VkTexturesShutdown( void );
|
||||
|
||||
qboolean R_VkTexturesSkyboxUpload( const char *name, rgbdata_t *const sides[6], colorspace_hint_e colorspace_hint, qboolean placeholder);
|
||||
qboolean R_VkTexturesSkyboxUploadKTX( const char *filename );
|
||||
void R_VkTexturesSkyboxUnload(void);
|
||||
|
||||
qboolean R_VkTextureUpload(int index, vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, colorspace_hint_e colorspace_hint);
|
||||
void R_VkTextureDestroy(int index, vk_texture_t *tex);
|
||||
|
|
Loading…
Reference in New Issue