mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-05 00:11:05 +01:00
vk: remove direct dependence on vk_textures[] from vk_textures.c
also fixup textures shutdown
This commit is contained in:
parent
c36080c982
commit
beddef8831
@ -6,6 +6,7 @@
|
||||
#include "vk_mapents.h" // wadlist
|
||||
#include "vk_logs.h"
|
||||
#include "r_speeds.h"
|
||||
#include "profiler.h"
|
||||
|
||||
#define PCG_IMPLEMENT
|
||||
#include "pcg.h"
|
||||
@ -30,10 +31,6 @@ uint vk_numTextures;
|
||||
|
||||
vk_textures_global_t tglob = {0};
|
||||
|
||||
extern vk_texture_t vk_textures[MAX_TEXTURES];
|
||||
extern vk_texture_t* vk_texturesHashTable[TEXTURES_HASH_SIZE];
|
||||
extern uint vk_numTextures;
|
||||
|
||||
static struct {
|
||||
poolhandle_t mempool;
|
||||
} g_textures;
|
||||
@ -68,6 +65,9 @@ qboolean R_TexturesInit( void ) {
|
||||
|
||||
void R_TexturesShutdown( void )
|
||||
{
|
||||
for( unsigned int i = 0; i < vk_numTextures; i++ )
|
||||
R_TextureFree( i );
|
||||
|
||||
R_VkTexturesShutdown();
|
||||
|
||||
//memset( tglob.lightmapTextures, 0, sizeof( tglob.lightmapTextures ));
|
||||
@ -627,7 +627,8 @@ static int loadTextureInternal( const char *name, const byte *buf, size_t size,
|
||||
// upload texture
|
||||
VK_ProcessImage( tex, pic );
|
||||
|
||||
if( !R_VkTextureUpload( tex, &pic, 1, false, colorspace_hint ))
|
||||
const int index = (tex - vk_textures);
|
||||
if( !R_VkTextureUpload( index, tex, &pic, 1, colorspace_hint ))
|
||||
{
|
||||
// FIXME remove from hash table
|
||||
memset( tex, 0, sizeof( vk_texture_t ));
|
||||
@ -641,7 +642,7 @@ static int loadTextureInternal( const char *name, const byte *buf, size_t size,
|
||||
gEngine.FS_FreeImage( pic ); // release source texture
|
||||
|
||||
// NOTE: always return texnum as index in array or engine will stop work !!!
|
||||
return tex - vk_textures;
|
||||
return index;
|
||||
}
|
||||
|
||||
int R_TextureUploadFromFile( const char *name, const byte *buf, size_t size, int flags ) {
|
||||
@ -699,7 +700,7 @@ static int loadTextureFromBuffers( const char *name, rgbdata_t *const *const pic
|
||||
for (int i = 0; i < pic_count; ++i)
|
||||
VK_ProcessImage( tex, pic[i] );
|
||||
|
||||
if( !R_VkTextureUpload( tex, pic, pic_count, false, kColorspaceGamma ))
|
||||
if( !R_VkTextureUpload( (int)(tex - vk_textures), tex, pic, pic_count, kColorspaceGamma ))
|
||||
{
|
||||
memset( tex, 0, sizeof( vk_texture_t ));
|
||||
return 0;
|
||||
@ -910,7 +911,7 @@ int R_TextureCreateDummy_FIXME( const char *name ) {
|
||||
return R_TextureUploadFromBufferNew(name, pic, TF_NOMIPMAP);
|
||||
}
|
||||
|
||||
vk_texture_t *R_TextureGetByIndex(int index)
|
||||
struct vk_texture_s *R_TextureGetByIndex( uint index)
|
||||
{
|
||||
ASSERT(index >= 0);
|
||||
ASSERT(index < MAX_TEXTURES);
|
||||
@ -946,3 +947,72 @@ int R_TexturesGetParm( int parm, int arg ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void R_TextureAcquire( unsigned int texnum ) {
|
||||
ASSERT(texnum < vk_numTextures);
|
||||
vk_texture_t *const tex = vk_textures + texnum;
|
||||
++tex->refcount;
|
||||
|
||||
DEBUG("Acquiring existing texture %s(%d) refcount=%d", tex->name, (int)(tex-vk_textures), tex->refcount);
|
||||
}
|
||||
|
||||
void R_TextureRelease( unsigned int texnum ) {
|
||||
vk_texture_t *tex;
|
||||
vk_texture_t **prev;
|
||||
vk_texture_t *cur;
|
||||
|
||||
APROF_SCOPE_DECLARE_BEGIN(free, __FUNCTION__);
|
||||
|
||||
if( texnum <= 0 )
|
||||
goto end;
|
||||
|
||||
tex = vk_textures + texnum;
|
||||
|
||||
// already freed?
|
||||
if( !tex->vk.image.image )
|
||||
goto end;
|
||||
|
||||
// debug
|
||||
if( !tex->name[0] )
|
||||
{
|
||||
ERR("R_TextureRelease: trying to free unnamed texture with index %u", texnum );
|
||||
goto end;
|
||||
}
|
||||
|
||||
DEBUG("Releasing texture=%d(%s) refcount=%d", texnum, tex->name, tex->refcount);
|
||||
ASSERT(tex->refcount > 0);
|
||||
--tex->refcount;
|
||||
|
||||
if (tex->refcount > 0)
|
||||
goto end;
|
||||
|
||||
DEBUG("Freeing texture=%d(%s)", texnum, tex->name);
|
||||
|
||||
// remove from hash table
|
||||
prev = &vk_texturesHashTable[tex->hashValue];
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
cur = *prev;
|
||||
if( !cur ) break;
|
||||
|
||||
if( cur == tex )
|
||||
{
|
||||
*prev = cur->nextHash;
|
||||
break;
|
||||
}
|
||||
prev = &cur->nextHash;
|
||||
}
|
||||
|
||||
/*
|
||||
// release source
|
||||
if( tex->original )
|
||||
gEngine.FS_FreeImage( tex->original );
|
||||
*/
|
||||
|
||||
R_VkTextureDestroy( texnum, tex );
|
||||
memset(tex, 0, sizeof(*tex));
|
||||
|
||||
end:
|
||||
APROF_SCOPE_END(free);
|
||||
}
|
||||
|
@ -65,3 +65,6 @@ int R_TextureFindByNameF( const char *fmt, ...);
|
||||
// Full names depend on map name, wad name, etc. This function tries them all.
|
||||
// Returns -1 if not found
|
||||
int R_TextureFindByNameLike( const char *texture_name );
|
||||
|
||||
struct vk_texture_s;
|
||||
struct vk_texture_s *R_TextureGetByIndex( uint index );
|
||||
|
@ -833,6 +833,8 @@ void R_VkShutdown( void ) {
|
||||
|
||||
VK_FrameCtlShutdown();
|
||||
|
||||
R_VkMaterialsShutdown();
|
||||
|
||||
R_TexturesShutdown();
|
||||
|
||||
VK_PipelineShutdown();
|
||||
|
@ -573,3 +573,8 @@ qboolean R_VkMaterialGetEx( int tex_id, int rendermode, r_vk_material_t *out_mat
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void R_VkMaterialsShutdown( void ) {
|
||||
materialsReleaseTextures();
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,8 @@ typedef struct { int index; } r_vk_material_ref_t;
|
||||
// TODO: track "version" in high bits?
|
||||
void R_VkMaterialsReload( void );
|
||||
|
||||
void R_VkMaterialsShutdown( void );
|
||||
|
||||
struct model_s;
|
||||
void R_VkMaterialsLoadForModel( const struct model_s* mod );
|
||||
|
||||
|
@ -46,21 +46,15 @@ static struct {
|
||||
|
||||
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
|
||||
|
||||
extern vk_texture_t vk_textures[MAX_TEXTURES];
|
||||
extern vk_texture_t* vk_texturesHashTable[TEXTURES_HASH_SIZE];
|
||||
extern uint vk_numTextures;
|
||||
|
||||
size_t CalcImageSize( pixformat_t format, int width, int height, int depth );
|
||||
int CalcMipmapCount( vk_texture_t *tex, qboolean haveBuffer );
|
||||
qboolean validatePicLayers(const char* const name, rgbdata_t *const *const layers, int num_layers);
|
||||
void BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, int flags );
|
||||
|
||||
static VkSampler pickSamplerForFlags( texFlags_t flags );
|
||||
static void textureDestroyVkImage( vk_texture_t *tex );
|
||||
|
||||
// FIXME should be static
|
||||
void unloadSkybox( void );
|
||||
qboolean R_VkTextureUpload(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint);
|
||||
|
||||
qboolean R_VkTexturesInit( void ) {
|
||||
R_SPEEDS_METRIC(g_vktextures.stats.count, "count", kSpeedsMetricCount);
|
||||
@ -83,10 +77,10 @@ qboolean R_VkTexturesInit( void ) {
|
||||
|
||||
// Fill empty texture with references to the default texture
|
||||
{
|
||||
const VkImageView default_view = vk_textures[tglob.defaultTexture].vk.image.view;
|
||||
const VkImageView default_view = R_TextureGetByIndex(tglob.defaultTexture)->vk.image.view;
|
||||
ASSERT(default_view != VK_NULL_HANDLE);
|
||||
for (int i = 0; i < MAX_TEXTURES; ++i) {
|
||||
const vk_texture_t *const tex = vk_textures + i;
|
||||
const vk_texture_t *const tex = R_TextureGetByIndex(i);
|
||||
if (tex->vk.image.view)
|
||||
continue;
|
||||
|
||||
@ -104,17 +98,8 @@ qboolean R_VkTexturesInit( void ) {
|
||||
static void textureDestroy( unsigned int index );
|
||||
|
||||
void R_VkTexturesShutdown( void ) {
|
||||
/* for( unsigned int i = 0; i < COUNTOF(g_vktextures.textures); i++ ) */
|
||||
/* textureDestroy( i ); */
|
||||
|
||||
unloadSkybox();
|
||||
|
||||
textureDestroyVkImage(&g_vktextures.cubemap_placeholder);
|
||||
|
||||
// FIXME g_vktextures.stats.size_total -= g_vktextures.cubemap_placeholder.total_size;
|
||||
|
||||
g_vktextures.stats.count--;
|
||||
|
||||
R_VkTextureDestroy(-1, &g_vktextures.cubemap_placeholder);
|
||||
|
||||
for (int i = 0; i < COUNTOF(g_vktextures.samplers); ++i) {
|
||||
if (g_vktextures.samplers[i].sampler != VK_NULL_HANDLE)
|
||||
@ -220,16 +205,15 @@ static VkSampler pickSamplerForFlags( texFlags_t flags ) {
|
||||
return g_vktextures.default_sampler;
|
||||
}
|
||||
|
||||
static void setDescriptorSet(vk_texture_t* const tex, colorspace_hint_e colorspace_hint) {
|
||||
// FIXME detect skybox some other way
|
||||
if (tex->vk.image.layers > 1)
|
||||
static void setDescriptorSet(int index, vk_texture_t* const tex, colorspace_hint_e colorspace_hint) {
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
const int index = tex - vk_textures;
|
||||
ASSERT(index >= 0);
|
||||
ASSERT(index < MAX_TEXTURES);
|
||||
|
||||
const VkImageView view = tex->vk.image.view != VK_NULL_HANDLE ? tex->vk.image.view : vk_textures[tglob.defaultTexture].vk.image.view;
|
||||
const VkImageView view = tex->vk.image.view != VK_NULL_HANDLE
|
||||
? tex->vk.image.view
|
||||
: R_TextureGetByIndex(tglob.defaultTexture)->vk.image.view;
|
||||
|
||||
if (view == VK_NULL_HANDLE)
|
||||
return;
|
||||
@ -268,8 +252,8 @@ static void setDescriptorSet(vk_texture_t* const tex, colorspace_hint_e colorspa
|
||||
tex->vk.descriptor_unorm = ds;
|
||||
}
|
||||
|
||||
static qboolean uploadRawKtx2( vk_texture_t *tex, const rgbdata_t* pic ) {
|
||||
DEBUG("Uploading raw KTX2 texture[%d] %s", (int)(tex-vk_textures), tex->name);
|
||||
static qboolean uploadRawKtx2( int tex_index, vk_texture_t *tex, const rgbdata_t* pic ) {
|
||||
DEBUG("Uploading raw KTX2 texture[%d] %s", tex_index, tex->name);
|
||||
|
||||
const byte *const data = pic->buffer;
|
||||
const int size = pic->size;
|
||||
@ -355,13 +339,12 @@ static qboolean uploadRawKtx2( vk_texture_t *tex, const rgbdata_t* pic ) {
|
||||
// KTX2 textures are inaccessible from trad renderer (for now)
|
||||
tex->vk.descriptor_unorm = VK_NULL_HANDLE;
|
||||
|
||||
const int index = tex - vk_textures;
|
||||
const VkDescriptorImageInfo dii = {
|
||||
.imageView = tex->vk.image.view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.sampler = pickSamplerForFlags( tex->flags ),
|
||||
};
|
||||
g_vktextures.dii_all_textures[index] = dii;
|
||||
g_vktextures.dii_all_textures[tex_index] = dii;
|
||||
}
|
||||
|
||||
g_vktextures.stats.size_total += tex->total_size;
|
||||
@ -373,11 +356,12 @@ static qboolean uploadRawKtx2( vk_texture_t *tex, const rgbdata_t* pic ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean R_VkTextureUpload(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint) {
|
||||
|
||||
static qboolean uploadTexture(int index, vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint) {
|
||||
tex->total_size = 0;
|
||||
|
||||
if (num_layers == 1 && layers[0]->type == PF_KTX2_RAW) {
|
||||
if (!uploadRawKtx2(tex, layers[0]))
|
||||
if (!uploadRawKtx2(index, tex, layers[0]))
|
||||
return false;
|
||||
} else {
|
||||
const qboolean compute_mips = layers[0]->type == PF_RGBA_32 && layers[0]->numMips < 2;
|
||||
@ -395,14 +379,15 @@ qboolean R_VkTextureUpload(vk_texture_t *tex, rgbdata_t *const *const layers, in
|
||||
tex->width = layers[0]->width;
|
||||
tex->height = layers[0]->height;
|
||||
|
||||
DEBUG("Uploading texture[%d] %s, mips=%d(build=%d), layers=%d", (int)(tex-vk_textures), tex->name, mipCount, compute_mips, num_layers);
|
||||
DEBUG("Uploading texture[%d] %s, mips=%d(build=%d), layers=%d", index, tex->name, mipCount, compute_mips, num_layers);
|
||||
|
||||
// TODO (not sure why, but GL does this)
|
||||
// if( !ImageCompressed( layers->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( layers->flags, IMAGE_ONEBIT_ALPHA ))
|
||||
// data = GL_ApplyFilter( data, tex->width, tex->height );
|
||||
|
||||
// TODO optimize: do not destroy if size+format+mips+... haven't changed
|
||||
if (tex->vk.image.image != VK_NULL_HANDLE)
|
||||
textureDestroyVkImage( tex );
|
||||
R_VkTextureDestroy( index, tex );
|
||||
|
||||
{
|
||||
const r_vk_image_create_t create = {
|
||||
@ -451,14 +436,18 @@ qboolean R_VkTextureUpload(vk_texture_t *tex, rgbdata_t *const *const layers, in
|
||||
}
|
||||
}
|
||||
|
||||
setDescriptorSet(tex, colorspace_hint);
|
||||
setDescriptorSet(index, tex, colorspace_hint);
|
||||
|
||||
g_vktextures.stats.size_total += tex->total_size;
|
||||
g_vktextures.stats.count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void textureDestroyVkImage( vk_texture_t *tex ) {
|
||||
qboolean R_VkTextureUpload(int index, vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, colorspace_hint_e colorspace_hint) {
|
||||
return uploadTexture( index, tex, layers, num_layers, false, colorspace_hint );
|
||||
}
|
||||
|
||||
void R_VkTextureDestroy( int index, vk_texture_t *tex ) {
|
||||
// Need to make sure that there are no references to this texture anywhere.
|
||||
// It might have been added to staging and then immediately deleted, leaving references to its vkimage
|
||||
// in the staging command buffer. See https://github.com/w23/xash3d-fwgs/issues/464
|
||||
@ -469,91 +458,24 @@ static void textureDestroyVkImage( vk_texture_t *tex ) {
|
||||
g_vktextures.stats.size_total -= tex->total_size;
|
||||
g_vktextures.stats.count--;
|
||||
|
||||
tex->total_size = 0;
|
||||
}
|
||||
|
||||
void R_TextureRelease( unsigned int texnum ) {
|
||||
vk_texture_t *tex;
|
||||
vk_texture_t **prev;
|
||||
vk_texture_t *cur;
|
||||
|
||||
APROF_SCOPE_DECLARE_BEGIN(free, __FUNCTION__);
|
||||
|
||||
if( texnum <= 0 )
|
||||
goto end;
|
||||
|
||||
tex = vk_textures + texnum;
|
||||
|
||||
// already freed?
|
||||
if( !tex->vk.image.image )
|
||||
goto end;
|
||||
|
||||
// debug
|
||||
if( !tex->name[0] )
|
||||
{
|
||||
ERR("R_TextureRelease: trying to free unnamed texture with index %u", texnum );
|
||||
goto end;
|
||||
}
|
||||
|
||||
DEBUG("Releasing texture=%d(%s) refcount=%d", texnum, tex->name, tex->refcount);
|
||||
ASSERT(tex->refcount > 0);
|
||||
--tex->refcount;
|
||||
|
||||
if (tex->refcount > 0)
|
||||
goto end;
|
||||
|
||||
DEBUG("Freeing texture=%d(%s)", texnum, tex->name);
|
||||
|
||||
// remove from hash table
|
||||
prev = &vk_texturesHashTable[tex->hashValue];
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
cur = *prev;
|
||||
if( !cur ) break;
|
||||
|
||||
if( cur == tex )
|
||||
{
|
||||
*prev = cur->nextHash;
|
||||
break;
|
||||
}
|
||||
prev = &cur->nextHash;
|
||||
}
|
||||
|
||||
/*
|
||||
// release source
|
||||
if( tex->original )
|
||||
gEngine.FS_FreeImage( tex->original );
|
||||
*/
|
||||
|
||||
textureDestroyVkImage( tex );
|
||||
|
||||
memset(tex, 0, sizeof(*tex));
|
||||
|
||||
// Reset descriptor sets to default texture
|
||||
setDescriptorSet(tex, kColorspaceNative);
|
||||
setDescriptorSet(index, tex, kColorspaceNative);
|
||||
|
||||
end:
|
||||
APROF_SCOPE_END(free);
|
||||
tex->total_size = 0;
|
||||
|
||||
// TODO: currently cannot do this because vk_render depends on all textures having some descriptor regardless of their alive-ness
|
||||
// TODO tex->vk.descriptor_unorm = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void unloadSkybox( void ) {
|
||||
if (g_vktextures.skybox_cube.vk.image.image) {
|
||||
textureDestroyVkImage( &g_vktextures.skybox_cube );
|
||||
R_VkTextureDestroy( -1, &g_vktextures.skybox_cube );
|
||||
memset(&g_vktextures.skybox_cube, 0, sizeof(g_vktextures.skybox_cube));
|
||||
}
|
||||
|
||||
tglob.fCustomSkybox = false;
|
||||
}
|
||||
|
||||
void R_TextureAcquire( unsigned int texnum ) {
|
||||
ASSERT(texnum < vk_numTextures);
|
||||
vk_texture_t *const tex = vk_textures + texnum;
|
||||
++tex->refcount;
|
||||
|
||||
DEBUG("Acquiring existing texture %s(%d) refcount=%d", tex->name, (int)(tex-vk_textures), tex->refcount);
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo R_VkTextureGetSkyboxDescriptorImageInfo( void ) {
|
||||
return (VkDescriptorImageInfo){
|
||||
.sampler = g_vktextures.default_sampler,
|
||||
@ -567,12 +489,13 @@ VkDescriptorImageInfo R_VkTextureGetSkyboxDescriptorImageInfo( void ) {
|
||||
qboolean R_VkTexturesSkyboxUpload( const char *name, rgbdata_t *const sides[6], colorspace_hint_e colorspace_hint, qboolean placeholder) {
|
||||
vk_texture_t *const dest = placeholder ? &g_vktextures.cubemap_placeholder : &g_vktextures.skybox_cube;
|
||||
Q_strncpy( dest->name, name, sizeof( dest->name ));
|
||||
return R_VkTextureUpload(dest, sides, 6, true, colorspace_hint);
|
||||
return uploadTexture(-1, dest, sides, 6, true, colorspace_hint);
|
||||
}
|
||||
|
||||
VkDescriptorSet R_VkTextureGetDescriptorUnorm( uint index ) {
|
||||
ASSERT( index < MAX_TEXTURES );
|
||||
return vk_textures[index].vk.descriptor_unorm;
|
||||
// TODO make an array of unorm descriptors
|
||||
return R_TextureGetByIndex(index)->vk.descriptor_unorm;
|
||||
}
|
||||
|
||||
const VkDescriptorImageInfo* R_VkTexturesGetAllDescriptorsArray( void ) {
|
||||
|
@ -41,7 +41,8 @@ void R_VkTexturesShutdown( void );
|
||||
|
||||
qboolean R_VkTexturesSkyboxUpload( const char *name, rgbdata_t *const sides[6], colorspace_hint_e colorspace_hint, qboolean placeholder);
|
||||
|
||||
qboolean R_VkTextureUpload(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint);
|
||||
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);
|
||||
|
||||
// FIXME s/R_/R_Vk/
|
||||
void R_TextureAcquire( unsigned int texnum );
|
||||
|
Loading…
Reference in New Issue
Block a user