vk: clean up public rendering texture api

This commit is contained in:
Ivan Avdeev 2023-10-17 11:23:52 -04:00
parent aa44ab71e5
commit 806932b949
10 changed files with 105 additions and 79 deletions

View File

@ -635,3 +635,24 @@ For multiple replacements:
- mat_id
- name_to_material[] -- string "name" to mat_id
- hash table of some sorts
# 2023-10-16 E313
## Pre-next:
- validation crash
## Next:
- KTX2 PR against upstream
- texture leaks
- better texture storage
- hash map
- texture lifetimes/refcounts
- texture deletion
- mass (for single device wait idle)
# 2023-10-17 E314
- [x] imagelib/ktx2 PR to upstream
1. [x] Make a vulkan branch with the latest upstream merged in
2. [x] Make another branch `upstream-ktx2` from upstream/master with imagelib changes hand-picked
3. [x] Make a PR against upstream with ktx2
4. [x] Make a PR against vulkan with recentmost upstream
- [ ] Contemplate texture storage

View File

@ -227,7 +227,7 @@ void VK_UploadLightmap( void )
void VK_ClearLightmap( void )
{
for (int i = 0; i < gl_lms.current_lightmap_texture; ++i)
VK_FreeTexture(tglob.lightmapTextures[i]);
R_FreeTexture(tglob.lightmapTextures[i]);
gl_lms.current_lightmap_texture = 0;
LM_InitBlock();

View File

@ -500,7 +500,7 @@ r_vk_material_t R_VkMaterialGetForTextureWithFlags( int tex_index, uint32_t flag
r_vk_material_ref_t R_VkMaterialGetForName( const char *name ) {
// FIXME proper hash table here, don't depend on textures
const int dummy_tex_id_fixme = VK_FindTexture(name);
const int dummy_tex_id_fixme = R_FindTexture(name);
if (dummy_tex_id_fixme == 0) {
ERR("Material with name \"%s\" not found", name);
return (r_vk_material_ref_t){.index = -1,};

View File

@ -120,7 +120,7 @@ static void drawFill( float x, float y, float w, float h, int r, int g, int b, i
const int prev_blending = vk_renderstate.blending_mode;
vk_renderstate.blending_mode = blending_mode;
vk_renderstate.tri_color = (color_rgba8_t){r, g, b, a};
R_DrawStretchPic(x, y, w, h, 0, 0, 1, 1, VK_FindTexture(REF_WHITE_TEXTURE));
R_DrawStretchPic(x, y, w, h, 0, 0, 1, 1, R_FindTexture(REF_WHITE_TEXTURE));
vk_renderstate.tri_color = prev_color;
vk_renderstate.blending_mode = prev_blending;
}

View File

@ -38,14 +38,13 @@ static qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int x, int
return true;
}
// only called for GL contexts
static void GL_SetupAttributes( int safegl )
{
PRINT_NOT_IMPLEMENTED();
// Nothing to do for Vulkan
}
static void GL_ClearExtensions( void )
{
PRINT_NOT_IMPLEMENTED();
// Nothing to do for Vulkan
}
static void GL_BackendStartFrame_UNUSED( void )
{
@ -63,13 +62,13 @@ static void R_ShowTextures_UNUSED( void )
}
// texture management
static const byte *R_GetTextureOriginalBuffer( unsigned int idx )
static const byte *R_GetTextureOriginalBuffer_UNUSED( unsigned int idx )
{
PRINT_NOT_IMPLEMENTED();
return NULL;
}
static void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
static void GL_ProcessTexture_UNUSED( int texnum, float gamma, int topColor, int bottomColor )
{
PRINT_NOT_IMPLEMENTED();
}
@ -452,6 +451,32 @@ static int VGUI_GenerateTexture( void )
return 0;
}
static const byte* R_TextureData_UNUSED( unsigned int texnum )
{
PRINT_NOT_IMPLEMENTED_ARGS("texnum=%d", texnum);
// We don't store original texture data
// TODO do we need to?
return NULL;
}
int R_CreateTexture_UNUSED( const char *name, int width, int height, const void *buffer, texFlags_t flags )
{
PRINT_NOT_IMPLEMENTED_ARGS("name=%s width=%d height=%d buffer=%p flags=%08x", name, width, height, buffer, flags);
return 0;
}
static int R_LoadTextureArray_UNUSED( const char **names, int flags )
{
PRINT_NOT_IMPLEMENTED();
return 0;
}
int R_CreateTextureArray_UNUSED( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags )
{
PRINT_NOT_IMPLEMENTED_ARGS("name=%s width=%d height=%d buffer=%p flags=%08x", name, width, height, buffer, flags);
return 0;
}
static const ref_device_t *pfnGetRenderDevice( unsigned int idx )
{
if( idx >= vk_core.num_devices )
@ -467,6 +492,7 @@ static const ref_interface_t gReffuncs =
R_GetConfigName,
R_SetDisplayTransform,
// only called for GL contexts
GL_SetupAttributes,
.GL_InitExtensions = NULL, // Unused in Vulkan renderer
GL_ClearExtensions,
@ -487,13 +513,16 @@ static const ref_interface_t gReffuncs =
CL_AddCustomBeam,
R_ProcessEntData,
// debug
.R_ShowTextures = R_ShowTextures_UNUSED,
R_GetTextureOriginalBuffer,
VK_LoadTextureFromBuffer,
GL_ProcessTexture,
XVK_SetupSky,
// texture management
.R_GetTextureOriginalBuffer = R_GetTextureOriginalBuffer_UNUSED,
.GL_LoadTextureFromBuffer = R_LoadTextureFromBuffer,
.GL_ProcessTexture = GL_ProcessTexture_UNUSED,
.R_SetupSky = R_SetupSky,
// 2D
R_Set2DMode,
R_DrawStretchRaw,
R_DrawStretchPic,
@ -502,11 +531,14 @@ static const ref_interface_t gReffuncs =
CL_FillRGBABlend,
R_WorldToScreen,
// screenshot, cubemapshot
VID_ScreenShot,
VID_CubemapShot,
// light
R_LightPoint,
// decals
R_DecalShoot,
R_DecalRemoveAll,
R_CreateDecalList,
@ -540,15 +572,17 @@ static const ref_interface_t gReffuncs =
R_SetCurrentEntity,
R_SetCurrentModel,
VK_FindTexture,
VK_TextureName,
VK_TextureData,
VK_LoadTextureExternal,
VK_CreateTexture,
VK_LoadTextureArray,
VK_CreateTextureArray,
VK_FreeTexture,
// Texture tools
.GL_FindTexture = R_FindTexture,
.GL_TextureName = R_TextureName,
.GL_TextureData = R_TextureData_UNUSED,
.GL_LoadTexture = R_LoadTexture,
.GL_CreateTexture = R_CreateTexture_UNUSED,
.GL_LoadTextureArray = R_LoadTextureArray_UNUSED,
.GL_CreateTextureArray = R_CreateTextureArray_UNUSED,
.GL_FreeTexture = R_FreeTexture,
// Decals manipulating (draw & remove)
DrawSingleDecal,
R_DecalSetupVerts,
R_EntityRemoveDecals,

View File

@ -258,7 +258,7 @@ 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));
XVK_SetupSky( gEngine.pfnGetMoveVars()->skyName );
R_SetupSky( gEngine.pfnGetMoveVars()->skyName );
loadMap(map);

View File

@ -242,12 +242,12 @@ static const dframetype_t *VK_SpriteLoadFrame( model_t *mod, const void *pin, ms
if( FBitSet( mod->flags, MODEL_CLIENT )) // it's a HUD sprite
{
Q_snprintf( texname, sizeof( texname ), "#HUD/%s(%s:%i%i).spr", ctx->sprite_name, ctx->group_suffix, num / 10, num % 10 );
gl_texturenum = VK_LoadTextureExternal( texname, pin, pinframe.width * pinframe.height * bytes, ctx->r_texFlags );
gl_texturenum = R_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, ctx->r_texFlags );
}
else
{
Q_snprintf( texname, sizeof( texname ), "#%s(%s:%i%i).spr", ctx->sprite_name, ctx->group_suffix, num / 10, num % 10 );
gl_texturenum = VK_LoadTextureExternal( texname, pin, pinframe.width * pinframe.height * bytes, ctx->r_texFlags );
gl_texturenum = R_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, ctx->r_texFlags );
}
// setup frame description

View File

@ -3332,7 +3332,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
// build the texname
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );
ptexture->index = VK_LoadTextureExternal( texname, (byte *)ptexture, size, flags );
ptexture->index = R_LoadTexture( texname, (byte *)ptexture, size, flags );
if( !ptexture->index )
{
@ -3378,7 +3378,7 @@ void Mod_StudioUnloadTextures( void *data )
{
if( ptexture[i].index == tglob.defaultTexture )
continue;
VK_FreeTexture( ptexture[i].index );
R_FreeTexture( ptexture[i].index );
}
}

View File

@ -46,7 +46,7 @@ static VkSampler pickSamplerForFlags( texFlags_t flags );
void initTextures( void ) {
R_SPEEDS_METRIC(g_textures.stats.count, "count", kSpeedsMetricCount);
R_SPEEDS_METRIC(g_textures.stats.size_total, "size_total", kSpeedsMetricBytes);
tglob.mempool = Mem_AllocPool( "vktextures" );
memset( vk_textures, 0, sizeof( vk_textures ));
@ -100,7 +100,7 @@ static void unloadSkybox( void );
void destroyTextures( void )
{
for( unsigned int i = 0; i < vk_numTextures; i++ )
VK_FreeTexture( i );
R_FreeTexture( i );
unloadSkybox();
@ -205,7 +205,7 @@ static rgbdata_t *Common_FakeImage( int width, int height, int depth, int flags
r_image->depth = Q_max( 1, depth );
r_image->flags = flags;
r_image->type = PF_RGBA_32;
r_image->size = r_image->width * r_image->height * r_image->depth * 4;
if( FBitSet( r_image->flags, IMAGE_CUBEMAP )) r_image->size *= 6;
@ -998,7 +998,7 @@ static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers,
///////////// Render API funcs /////////////
// Texture tools
int VK_FindTexture( const char *name )
int R_FindTexture( const char *name )
{
vk_texture_t *tex;
@ -1011,20 +1011,12 @@ int VK_FindTexture( const char *name )
return 0;
}
const char* VK_TextureName( unsigned int texnum )
const char* R_TextureName( unsigned int texnum )
{
ASSERT( texnum >= 0 && texnum < MAX_TEXTURES );
return vk_textures[texnum].name;
}
const byte* VK_TextureData( unsigned int texnum )
{
PRINT_NOT_IMPLEMENTED_ARGS("texnum=%d", texnum);
// We don't store original texture data
// TODO do we need to?
return NULL;
}
static int loadTextureInternal( const char *name, const byte *buf, size_t size, int flags, colorspace_hint_e colorspace_hint ) {
if( !Common_CheckTexName( name ))
return 0;
@ -1072,7 +1064,7 @@ static int loadTextureInternal( const char *name, const byte *buf, size_t size,
return tex - vk_textures;
}
int VK_LoadTextureExternal( const char *name, const byte *buf, size_t size, int flags ) {
int R_LoadTexture( const char *name, const byte *buf, size_t size, int flags ) {
return loadTextureInternal(name, buf, size, flags, kColorspaceGamma);
}
@ -1085,32 +1077,14 @@ int R_VkLoadTexture( const char *filename, colorspace_hint_e colorspace, qboolea
// free if already loaded
// TODO consider leaving intact if loading failed
if(( tex = Common_TextureForName( filename ))) {
VK_FreeTexture( tex - vk_textures );
R_FreeTexture( tex - vk_textures );
}
}
return loadTextureInternal( filename, NULL, 0, 0, colorspace );
}
int VK_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags )
{
PRINT_NOT_IMPLEMENTED_ARGS("name=%s width=%d height=%d buffer=%p flags=%08x", name, width, height, buffer, flags);
return 0;
}
int VK_LoadTextureArray( const char **names, int flags )
{
PRINT_NOT_IMPLEMENTED();
return 0;
}
int VK_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags )
{
PRINT_NOT_IMPLEMENTED_ARGS("name=%s width=%d height=%d buffer=%p flags=%08x", name, width, height, buffer, flags);
return 0;
}
void VK_FreeTexture( unsigned int texnum ) {
void R_FreeTexture( unsigned int texnum ) {
vk_texture_t *tex;
vk_texture_t **prev;
vk_texture_t *cur;
@ -1126,7 +1100,7 @@ void VK_FreeTexture( unsigned int texnum ) {
// debug
if( !tex->name[0] )
{
ERR("VK_FreeTexture: trying to free unnamed texture with index %u", texnum );
ERR("R_FreeTexture: trying to free unnamed texture with index %u", texnum );
return;
}
@ -1186,7 +1160,7 @@ static int loadTextureFromBuffers( const char *name, rgbdata_t *const *const pic
if( update )
{
if( tex == NULL )
gEngine.Host_Error( "VK_LoadTextureFromBuffer: couldn't find texture %s for update\n", name );
gEngine.Host_Error( "loadTextureFromBuffer: couldn't find texture %s for update\n", name );
SetBits( tex->flags, flags );
}
else
@ -1207,7 +1181,7 @@ static int loadTextureFromBuffers( const char *name, rgbdata_t *const *const pic
return (tex - vk_textures);
}
int VK_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) {
int R_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) {
return loadTextureFromBuffers(name, &pic, 1, flags, update);
}
@ -1219,7 +1193,7 @@ int XVK_TextureLookupF( const char *fmt, ...) {
vsnprintf( buffer, sizeof buffer, fmt, argptr );
va_end( argptr );
tex_id = VK_FindTexture(buffer);
tex_id = R_FindTexture(buffer);
//DEBUG("Looked up texture %s -> %d", buffer, tex_id);
return tex_id;
}
@ -1345,7 +1319,7 @@ cleanup:
static const char *skybox_default = "desert";
static const char *skybox_prefixes[] = { "pbr/env/%s", "gfx/env/%s" };
void XVK_SetupSky( const char *skyboxname ) {
void R_SetupSky( const char *skyboxname ) {
if( !COM_CheckString( skyboxname ))
{
unloadSkybox();
@ -1372,7 +1346,8 @@ void XVK_SetupSky( const char *skyboxname ) {
if (Q_stricmp(skyboxname, skybox_default) != 0) {
WARN("missed or incomplete skybox '%s'", skyboxname);
XVK_SetupSky( "desert" ); // force to default
// FIXME infinite recursion
R_SetupSky( "desert" ); // force to default
}
}

View File

@ -33,7 +33,7 @@ typedef struct vk_texture_s
typedef struct vk_textures_global_s
{
poolhandle_t mempool;
int defaultTexture; // use for bad textures
int particleTexture;
int whiteTexture;
@ -84,24 +84,20 @@ typedef enum {
kColorspaceGamma,
} colorspace_hint_e;
// Public API functions
int VK_FindTexture( const char *name );
const char* VK_TextureName( unsigned int texnum );
const byte* VK_TextureData( unsigned int texnum );
int VK_LoadTextureExternal( const char *name, const byte *buf, size_t size, int flags );
int VK_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags );
int VK_LoadTextureArray( const char **names, int flags );
int VK_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags );
void VK_FreeTexture( unsigned int texnum );
int VK_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
// Ref interface functions
int R_FindTexture( const char *name );
const char* R_TextureName( unsigned int texnum );
int R_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
void R_FreeTexture( unsigned int texnum );
int R_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
int R_VkLoadTexture( const char *filename, colorspace_hint_e colorspace, qboolean force_reload);
int XVK_TextureLookupF( const char *fmt, ...);
#define VK_LoadTextureInternal( name, pic, flags ) VK_LoadTextureFromBuffer( name, pic, flags, false )
#define VK_LoadTextureInternal( name, pic, flags ) R_LoadTextureFromBuffer( name, pic, flags, false )
void XVK_SetupSky( const char *skyboxname );
void R_SetupSky( const char *skyboxname );
// Tries to find a texture by its short name
// Full names depend on map name, wad name, etc. This function tries them all.