vk: move textures to urmom

Known issues:
- pbr materials are completely broken. They end up not being able to
  find textures, seemingly due to memory corruption on materials side,
  not textures.
- There are still places that try to get texture=1
This commit is contained in:
Ivan Avdeev 2023-10-24 14:02:32 -04:00
parent beddef8831
commit 718d6d2592
6 changed files with 231 additions and 189 deletions

View File

@ -7,6 +7,7 @@
#include "vk_logs.h"
#include "r_speeds.h"
#include "profiler.h"
#include "unordered_roadmap.h"
#define PCG_IMPLEMENT
#include "pcg.h"
@ -23,16 +24,13 @@
#define LOG_MODULE LogModule_Textures
#define MODULE_NAME "textures"
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
vk_texture_t vk_textures[MAX_TEXTURES];
vk_texture_t* vk_texturesHashTable[TEXTURES_HASH_SIZE];
uint vk_numTextures;
vk_textures_global_t tglob = {0};
static struct {
poolhandle_t mempool;
vk_texture_t all[MAX_TEXTURES];
urmom_desc_t all_desc;
} g_textures;
// FIXME imported from vk_textures.h
@ -44,16 +42,18 @@ static int textureLoadFromFileF(int flags, colorspace_hint_e colorspace, const c
qboolean R_TexturesInit( void ) {
g_textures.mempool = Mem_AllocPool( "vktextures" );
memset( vk_textures, 0, sizeof( vk_textures ));
memset( vk_texturesHashTable, 0, sizeof( vk_texturesHashTable ));
vk_numTextures = 0;
g_textures.all_desc = (urmom_desc_t){
.array = g_textures.all,
.count = COUNTOF(g_textures.all),
.item_size = sizeof(g_textures.all[0]),
};
// create unused 0-entry
Q_strncpy( vk_textures->name, "*unused*", sizeof( vk_textures->name ));
vk_textures->hashValue = COM_HashKey( vk_textures->name, TEXTURES_HASH_SIZE );
vk_textures->nextHash = vk_texturesHashTable[vk_textures->hashValue];
vk_texturesHashTable[vk_textures->hashValue] = vk_textures;
vk_numTextures = 1;
urmomInit(&g_textures.all_desc);
// Mark index 0 as occupied to have a special "no texture" value
g_textures.all[0].hdr_.hash = 0x7fffffff;
g_textures.all[0].hdr_.state = 1;
Q_strncpy( g_textures.all[0].hdr_.key, "*unused*", sizeof(g_textures.all[0].hdr_.key));
createDefaultTextures();
@ -65,17 +65,13 @@ qboolean R_TexturesInit( void ) {
void R_TexturesShutdown( void )
{
for( unsigned int i = 0; i < vk_numTextures; i++ )
for( int i = 0; i < COUNTOF(g_textures.all); i++ )
R_TextureFree( i );
R_VkTexturesShutdown();
//memset( tglob.lightmapTextures, 0, sizeof( tglob.lightmapTextures ));
memset( vk_texturesHashTable, 0, sizeof( vk_texturesHashTable ));
memset( vk_textures, 0, sizeof( vk_textures ));
vk_numTextures = 0;
}
/* OBSOLETE
static vk_texture_t *Common_AllocTexture( const char *name, texFlags_t flags )
{
vk_texture_t *tex;
@ -109,25 +105,6 @@ static vk_texture_t *Common_AllocTexture( const char *name, texFlags_t flags )
return tex;
}
/* FIXME static */ qboolean Common_CheckTexName( const char *name )
{
int len;
if( !COM_CheckString( name ))
return false;
len = Q_strlen( name );
// because multi-layered textures can exceed name string
if( len >= sizeof( vk_textures->name ))
{
ERR("LoadTexture: too long name %s (%d)", name, len );
return false;
}
return true;
}
static vk_texture_t *Common_TextureForName( const char *name )
{
vk_texture_t *tex;
@ -144,6 +121,26 @@ static vk_texture_t *Common_TextureForName( const char *name )
return NULL;
}
*/
static qboolean checkTextureName( const char *name )
{
int len;
if( !COM_CheckString( name ))
return false;
len = Q_strlen( name );
// because multi-layered textures can exceed name string
if( len >= sizeof( g_textures.all[0].hdr_.key ))
{
ERR("LoadTexture: too long name %s (%d)", name, len );
return false;
}
return true;
}
static rgbdata_t *Common_FakeImage( int width, int height, int depth, int flags )
{
@ -311,7 +308,7 @@ static void createDefaultTextures( void )
R_VkTexturesSkyboxUpload( "skybox_placeholder", sides, kColorspaceGamma, true );
}
loadBlueNoiseTextures();
// FIXME convert to 3d texture loadBlueNoiseTextures();
}
@ -577,31 +574,35 @@ int R_TextureFindByName( const char *name )
{
vk_texture_t *tex;
if( !Common_CheckTexName( name ))
if( !checkTextureName( name ))
return 0;
// see if already loaded
if(( tex = Common_TextureForName( name )))
return (tex - vk_textures);
return 0;
const int index = urmomFind(&g_textures.all_desc, name);
return index ? index > 0 : 0;
}
const char* R_TextureGetNameByIndex( unsigned int texnum )
{
ASSERT( texnum >= 0 && texnum < MAX_TEXTURES );
return vk_textures[texnum].name;
return g_textures.all[texnum].hdr_.key;
}
static int loadTextureInternal( const char *name, const byte *buf, size_t size, int flags, colorspace_hint_e colorspace_hint, qboolean force_update ) {
if( !Common_CheckTexName( name ))
if( !checkTextureName( name ))
return 0;
const urmom_insert_t insert = urmomInsert(&g_textures.all_desc, name);
if (insert.index < 0)
ERR("Cannot allocate texture slot for \"%s\"", name);
ASSERT(insert.index < COUNTOF(g_textures.all));
vk_texture_t *const tex = g_textures.all + insert.index;
// see if already loaded
vk_texture_t * tex = Common_TextureForName( name );
if( tex && !force_update ) {
DEBUG("Found existing texture %s(%d) refcount=%d", tex->name, (int)(tex-vk_textures), tex->refcount);
return (tex - vk_textures);
if (!insert.created && !force_update) {
DEBUG("Found existing texture %s(%d) refcount=%d",
TEX_NAME(tex), insert.index, tex->refcount);
return insert.index;
}
uint picFlags = 0;
@ -616,33 +617,37 @@ static int loadTextureInternal( const char *name, const byte *buf, size_t size,
gEngine.Image_SetForceFlags( picFlags );
rgbdata_t *const pic = gEngine.FS_LoadImage( name, buf, size );
if( !pic ) return 0; // couldn't loading image
if( !pic ) {
if (insert.created)
urmomRemoveByIndex(&g_textures.all_desc, insert.index);
return 0; // couldn't loading image
}
// allocate the new one if needed
if (!tex)
tex = Common_AllocTexture( name, flags );
else
tex->flags = flags;
tex->flags = flags;
// upload texture
VK_ProcessImage( tex, pic );
const int index = (tex - vk_textures);
if( !R_VkTextureUpload( index, tex, &pic, 1, colorspace_hint ))
if( !R_VkTextureUpload( insert.index, tex, &pic, 1, colorspace_hint ))
{
// FIXME remove from hash table
memset( tex, 0, sizeof( vk_texture_t ));
if (insert.created)
urmomRemoveByIndex(&g_textures.all_desc, insert.index);
gEngine.FS_FreeImage( pic ); // release source texture
return 0;
}
gEngine.FS_FreeImage( pic ); // release source texture
// FIXME this is not strictly correct. Refcount management should be done differently wrt public ref_interface_t
// TODO where did we come from?
if (insert.created)
tex->refcount = 1;
tex->width = pic->width;
tex->height = pic->height;
gEngine.FS_FreeImage( pic ); // release source texture
// NOTE: always return texnum as index in array or engine will stop work !!!
return index;
return insert.index;
}
int R_TextureUploadFromFile( const char *name, const byte *buf, size_t size, int flags ) {
@ -672,43 +677,55 @@ void R_TextureFree( unsigned int texnum ) {
}
static int loadTextureFromBuffers( const char *name, rgbdata_t *const *const pic, int pic_count, texFlags_t flags, qboolean update_only ) {
vk_texture_t *tex;
if( !Common_CheckTexName( name ))
// couldn't loading image
if( !pic )
return 0;
// see if already loaded
if(( tex = Common_TextureForName( name )) && !update_only )
return (tex - vk_textures);
if( !checkTextureName( name ))
return 0;
// couldn't loading image
if( !pic ) return 0;
urmom_insert_t insert = {0};
if (update_only)
insert.index = urmomFind(&g_textures.all_desc, name);
else
insert = urmomInsert(&g_textures.all_desc, name);
if (insert.index < 0) {
if (update_only) {
gEngine.Host_Error( "%s: couldn't find texture %s for update\n", __FUNCTION__, name );
} else {
ERR("Cannot allocate texture slot for \"%s\"", name);
}
return 0;
}
ASSERT(insert.index < COUNTOF(g_textures.all));
vk_texture_t *const tex = g_textures.all + insert.index;
// see if already loaded
if (!insert.created && !update_only)
return insert.index;
if( update_only )
{
if( tex == NULL )
gEngine.Host_Error( "loadTextureFromBuffer: couldn't find texture %s for update\n", name );
SetBits( tex->flags, flags );
}
else
{
// allocate the new one
ASSERT(!tex);
tex = Common_AllocTexture( name, flags );
}
for (int i = 0; i < pic_count; ++i)
VK_ProcessImage( tex, pic[i] );
if( !R_VkTextureUpload( (int)(tex - vk_textures), tex, pic, pic_count, kColorspaceGamma ))
if( !R_VkTextureUpload( insert.index, tex, pic, pic_count, kColorspaceGamma ))
{
memset( tex, 0, sizeof( vk_texture_t ));
if (!update_only)
urmomRemoveByIndex(&g_textures.all_desc, insert.index);
return 0;
}
return (tex - vk_textures);
}
// FIXME this is not strictly correct. Refcount management should be done differently wrt public ref_interface_t
// TODO where did we come from?
if (insert.created)
tex->refcount = 1;
return insert.index;
}
int R_TextureUploadFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update_only ) {
return loadTextureFromBuffers(name, &pic, 1, flags, update_only);
}
@ -798,7 +815,7 @@ static qboolean loadSkybox( const char *prefix, int style ) {
if( i != 6 )
goto cleanup;
if( !Common_CheckTexName( prefix ))
if( !checkTextureName( prefix ))
goto cleanup;
@ -911,12 +928,16 @@ int R_TextureCreateDummy_FIXME( const char *name ) {
return R_TextureUploadFromBufferNew(name, pic, TF_NOMIPMAP);
}
struct vk_texture_s *R_TextureGetByIndex( uint index)
struct vk_texture_s *R_TextureGetByIndex( uint index )
{
ASSERT(index >= 0);
ASSERT(index < MAX_TEXTURES);
//return g_vktextures.textures + index;
return vk_textures + index;
vk_texture_t *const tex = g_textures.all + index;
if (!URMOM_IS_OCCUPIED(tex->hdr_))
WARN("Accessing empty texture %d", index);
return tex;
}
int R_TexturesGetParm( int parm, int arg ) {
@ -949,11 +970,10 @@ int R_TexturesGetParm( int parm, int arg ) {
}
void R_TextureAcquire( unsigned int texnum ) {
ASSERT(texnum < vk_numTextures);
vk_texture_t *const tex = vk_textures + texnum;
vk_texture_t *const tex = R_TextureGetByIndex(texnum);
++tex->refcount;
DEBUG("Acquiring existing texture %s(%d) refcount=%d", tex->name, (int)(tex-vk_textures), tex->refcount);
DEBUG("Acquiring existing texture %s(%d) refcount=%d", TEX_NAME(tex), texnum, tex->refcount);
}
void R_TextureRelease( unsigned int texnum ) {
@ -966,43 +986,34 @@ void R_TextureRelease( unsigned int texnum ) {
if( texnum <= 0 )
goto end;
tex = vk_textures + texnum;
ASSERT(texnum < COUNTOF(g_textures.all));
tex = g_textures.all + texnum;
// already freed?
if( !tex->vk.image.image )
goto end;
// debug
if( !tex->name[0] )
if( !TEX_NAME(tex)[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);
DEBUG("Releasing texture=%d(%s) refcount=%d", texnum, TEX_NAME(tex), tex->refcount);
ASSERT(tex->refcount > 0);
--tex->refcount;
if (tex->refcount > 0)
goto end;
DEBUG("Freeing texture=%d(%s)", texnum, tex->name);
DEBUG("Freeing texture=%d(%s)", texnum, TEX_NAME(tex));
ASSERT(URMOM_IS_OCCUPIED(tex->hdr_));
// 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;
}
urmomRemoveByIndex(&g_textures.all_desc, texnum);
/*
// release source
@ -1011,7 +1022,6 @@ void R_TextureRelease( unsigned int texnum ) {
*/
R_VkTextureDestroy( texnum, tex );
memset(tex, 0, sizeof(*tex));
end:
APROF_SCOPE_END(free);

View File

@ -51,16 +51,22 @@ typedef struct {
static int test_insert_find_remove( void ) {
PREAMBLE(4);
const int i = urmomInsert(&desc, "bidonchik");
CHECK_NOT_EQUAL_I(i, -1);
CHECK_EQUAL_S(items[i].hdr_.key, "bidonchik");
const urmom_insert_t i = urmomInsert(&desc, "bidonchik");
CHECK_NOT_EQUAL_I(i.index, -1);
CHECK_EQUAL_I(i.created, 1);
CHECK_EQUAL_S(items[i.index].hdr_.key, "bidonchik");
const int found = urmomFind(&desc, "bidonchik");
CHECK_EQUAL_I(found, i);
CHECK_EQUAL_I(found, i.index);
const urmom_insert_t i2 = urmomInsert(&desc, "bidonchik");
CHECK_EQUAL_I(i2.index, i.index);
CHECK_EQUAL_I(i2.created, 0);
CHECK_EQUAL_S(items[i.index].hdr_.key, "bidonchik");
const int removed = urmomRemove(&desc, "bidonchik");
CHECK_EQUAL_I(removed, i);
CHECK_EQUAL_I(items[i].hdr_.key[0], '\0');
CHECK_EQUAL_I(removed, i.index);
CHECK_EQUAL_I(items[i.index].hdr_.key[0], '\0');
const int not_found = urmomFind(&desc, "bidonchik");
CHECK_EQUAL_I(not_found, -1);
@ -79,20 +85,22 @@ static int test_find_nonexistent( void ) {
static int test_insert_find_many( void ) {
PREAMBLE(4);
const int a = urmomInsert(&desc, "smetanka");
CHECK_NOT_EQUAL_I(a, -1);
CHECK_EQUAL_S(items[a].hdr_.key, "smetanka");
const urmom_insert_t a = urmomInsert(&desc, "smetanka");
CHECK_NOT_EQUAL_I(a.index, -1);
CHECK_EQUAL_I(a.created, 1);
CHECK_EQUAL_S(items[a.index].hdr_.key, "smetanka");
const int b = urmomInsert(&desc, "tworog");
CHECK_NOT_EQUAL_I(b, -1);
CHECK_NOT_EQUAL_I(a, b);
CHECK_EQUAL_S(items[b].hdr_.key, "tworog");
const urmom_insert_t b = urmomInsert(&desc, "tworog");
CHECK_NOT_EQUAL_I(b.index, -1);
CHECK_EQUAL_I(b.created, 1);
CHECK_NOT_EQUAL_I(a.index, b.index);
CHECK_EQUAL_S(items[b.index].hdr_.key, "tworog");
const int a_found = urmomFind(&desc, "smetanka");
const int b_found = urmomFind(&desc, "tworog");
CHECK_EQUAL_I(a_found, a);
CHECK_EQUAL_I(b_found, b);
CHECK_EQUAL_I(a_found, a.index);
CHECK_EQUAL_I(b_found, b.index);
return 1;
}
@ -100,46 +108,52 @@ static int test_insert_find_many( void ) {
static int test_overflow( void ) {
PREAMBLE(4);
const int a = urmomInsert(&desc, "smetanka");
CHECK_NOT_EQUAL_I(a, -1);
CHECK_EQUAL_S(items[a].hdr_.key, "smetanka");
const urmom_insert_t a = urmomInsert(&desc, "smetanka");
CHECK_NOT_EQUAL_I(a.index, -1);
CHECK_EQUAL_I(a.created, 1);
CHECK_EQUAL_S(items[a.index].hdr_.key, "smetanka");
const int b = urmomInsert(&desc, "tworog");
CHECK_NOT_EQUAL_I(b, -1);
CHECK_NOT_EQUAL_I(a, b);
CHECK_EQUAL_S(items[b].hdr_.key, "tworog");
const urmom_insert_t b = urmomInsert(&desc, "tworog");
CHECK_NOT_EQUAL_I(b.index, -1);
CHECK_EQUAL_I(b.created, 1);
CHECK_NOT_EQUAL_I(a.index, b.index);
CHECK_EQUAL_S(items[b.index].hdr_.key, "tworog");
const int c = urmomInsert(&desc, "kefirushka");
CHECK_NOT_EQUAL_I(c, -1);
CHECK_NOT_EQUAL_I(a, c);
CHECK_NOT_EQUAL_I(b, c);
CHECK_EQUAL_S(items[c].hdr_.key, "kefirushka");
const urmom_insert_t c = urmomInsert(&desc, "kefirushka");
CHECK_NOT_EQUAL_I(c.index, -1);
CHECK_EQUAL_I(c.created, 1);
CHECK_NOT_EQUAL_I(a.index, c.index);
CHECK_NOT_EQUAL_I(b.index, c.index);
CHECK_EQUAL_S(items[c.index].hdr_.key, "kefirushka");
const int d = urmomInsert(&desc, "ryazhenka");
CHECK_NOT_EQUAL_I(d, -1);
CHECK_NOT_EQUAL_I(a, d);
CHECK_NOT_EQUAL_I(b, d);
CHECK_NOT_EQUAL_I(c, d);
CHECK_EQUAL_S(items[d].hdr_.key, "ryazhenka");
const urmom_insert_t d = urmomInsert(&desc, "ryazhenka");
CHECK_NOT_EQUAL_I(d.index, -1);
CHECK_EQUAL_I(d.created, 1);
CHECK_NOT_EQUAL_I(a.index, d.index);
CHECK_NOT_EQUAL_I(b.index, d.index);
CHECK_NOT_EQUAL_I(c.index, d.index);
CHECK_EQUAL_S(items[d.index].hdr_.key, "ryazhenka");
{
const int e = urmomInsert(&desc, "riajenka");
CHECK_EQUAL_I(e, -1);
const urmom_insert_t e = urmomInsert(&desc, "riajenka");
CHECK_EQUAL_I(e.index, -1);
CHECK_EQUAL_I(e.created, 0);
}
const int d_remove = urmomRemove(&desc, "ryazhenka");
CHECK_EQUAL_I(d_remove, d);
CHECK_EQUAL_I(d_remove, d.index);
CHECK_EQUAL_I(items[d_remove].hdr_.state, 0);
CHECK_NOT_EQUAL_I(items[d_remove].hdr_.hash, 0);
CHECK_EQUAL_I(items[d_remove].hdr_.key[0], '\0');
const int e = urmomInsert(&desc, "riajenka");
CHECK_NOT_EQUAL_I(e, -1);
CHECK_NOT_EQUAL_I(a, e);
CHECK_NOT_EQUAL_I(b, e);
CHECK_NOT_EQUAL_I(c, e);
CHECK_EQUAL_S(items[e].hdr_.key, "riajenka");
const urmom_insert_t e = urmomInsert(&desc, "riajenka");
CHECK_NOT_EQUAL_I(e.index, -1);
CHECK_EQUAL_I(e.created, 1);
CHECK_NOT_EQUAL_I(a.index, e.index);
CHECK_NOT_EQUAL_I(b.index, e.index);
CHECK_NOT_EQUAL_I(c.index, e.index);
CHECK_EQUAL_S(items[e.index].hdr_.key, "riajenka");
return 1;
}
@ -148,20 +162,22 @@ static int test_overflow( void ) {
static int test_hash_collision( void ) {
PREAMBLE(4);
const int a = urmomInsert(&desc, "costarring");
CHECK_NOT_EQUAL_I(a, -1);
const urmom_insert_t a = urmomInsert(&desc, "costarring");
CHECK_NOT_EQUAL_I(a.index, -1);
CHECK_EQUAL_I(a.created, 1);
const int b = urmomInsert(&desc, "liquid");
CHECK_NOT_EQUAL_I(b, -1);
CHECK_NOT_EQUAL_I(b, a);
const urmom_insert_t b = urmomInsert(&desc, "liquid");
CHECK_NOT_EQUAL_I(b.index, -1);
CHECK_EQUAL_I(b.created, 1);
CHECK_NOT_EQUAL_I(b.index, a.index);
CHECK_EQUAL_I(items[a].hdr_.hash, items[b].hdr_.hash);
CHECK_EQUAL_I(items[a.index].hdr_.hash, items[b.index].hdr_.hash);
const int a_found = urmomFind(&desc, "costarring");
CHECK_EQUAL_I(a_found, a);
CHECK_EQUAL_I(a_found, a.index);
const int b_found = urmomFind(&desc, "liquid");
CHECK_EQUAL_I(b_found, b);
CHECK_EQUAL_I(b_found, b.index);
return 1;
}

View File

@ -68,50 +68,61 @@ int urmomFind(const urmom_desc_t* desc, const char* key) {
}
// Returns index of the element either found or empty slot where this could be inserted. If full, -1.
int urmomInsert(const urmom_desc_t* desc, const char *key) {
urmom_insert_t urmomInsert(const urmom_desc_t* desc, const char *key) {
char *ptr = desc->array;
const uint32_t hash = hash32FNV1aStr(key) & 0x7fffffffu;
const uint32_t mask = (desc->count - 1);
const int start_index = hash & mask;
int index = start_index;
int first_available = -1;
for (;;) {
const urmom_header_t *hdr = (urmom_header_t*)(ptr + desc->item_size * index);
if (URMOM_IS_OCCUPIED(*hdr)) {
if (hdr->hash == hash && strcmp(key, hdr->key) == 0)
// Return existing item
return index;
} else
return (urmom_insert_t){.index = index, .created = 0};
} else {
// Remember the very first item that wasn't occupied
if (first_available < 0)
first_available = index;
// Reached the end of occupied chain, return the available slot
break;
if (URMOM_IS_EMPTY(*hdr))
break;
}
index = (index + 1) & mask;
// Searched through the entire thing
if (index == start_index)
return -1;
break;
}
urmom_header_t *hdr = (urmom_header_t*)(ptr + desc->item_size * index);
// If no slots were encountered, exit with error
if (first_available < 0)
return (urmom_insert_t){.index = -1, .created = 0};
urmom_header_t *hdr = (urmom_header_t*)(ptr + desc->item_size * first_available);
hdr->hash = hash;
hdr->state = 1;
// TODO check for key length
strncpy(hdr->key, key, sizeof(hdr->key));
return index;
return (urmom_insert_t){.index = first_available, .created = 1};
}
// Return the index of item deleted (if found), -1 otherwise
int urmomRemove(const urmom_desc_t* desc, const char *key) {
const int index = urmomFind(desc, key);
if (index >= 0)
urmomDeleteByIndex(desc, index);
urmomRemoveByIndex(desc, index);
return index;
}
void urmomDeleteByIndex(const urmom_desc_t* desc, int index) {
void urmomRemoveByIndex(const urmom_desc_t* desc, int index) {
char *ptr = desc->array;
urmom_header_t *hdr = (urmom_header_t*)(ptr + desc->item_size * index);

View File

@ -40,9 +40,13 @@ void urmomInit(const urmom_desc_t* desc);
int urmomFind(const urmom_desc_t* desc, const char* key);
// Returns index of the element either found or empty slot where this could be inserted. If full, -1.
int urmomInsert(const urmom_desc_t* desc, const char *key);
void urmomDeleteByIndex(const urmom_desc_t* desc, int index);
typedef struct urmom_insert_s {
int index;
int created;
} urmom_insert_t;
urmom_insert_t urmomInsert(const urmom_desc_t* desc, const char *key);
// Return the index of item deleted (if found), -1 otherwise
int urmomRemove(const urmom_desc_t* desc, const char *key);
void urmomRemoveByIndex(const urmom_desc_t* desc, int index);

View File

@ -253,7 +253,7 @@ static void setDescriptorSet(int index, vk_texture_t* const tex, colorspace_hint
}
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);
DEBUG("Uploading raw KTX2 texture[%d] %s", tex_index, TEX_NAME(tex));
const byte *const data = pic->buffer;
const int size = pic->size;
@ -303,7 +303,7 @@ static qboolean uploadRawKtx2( int tex_index, vk_texture_t *tex, const rgbdata_t
{
const r_vk_image_create_t create = {
.debug_name = tex->name,
.debug_name = TEX_NAME(tex),
.width = header->pixelWidth,
.height = header->pixelHeight,
.mips = header->levelCount,
@ -373,13 +373,13 @@ static qboolean uploadTexture(int index, vk_texture_t *tex, rgbdata_t *const *co
return false;
}
if (!validatePicLayers(tex->name, layers, num_layers))
if (!validatePicLayers(TEX_NAME(tex), layers, num_layers))
return false;
tex->width = layers[0]->width;
tex->height = layers[0]->height;
DEBUG("Uploading texture[%d] %s, mips=%d(build=%d), layers=%d", index, tex->name, mipCount, compute_mips, num_layers);
DEBUG("Uploading texture[%d] %s, mips=%d(build=%d), layers=%d", index, TEX_NAME(tex), 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 ))
@ -391,7 +391,7 @@ static qboolean uploadTexture(int index, vk_texture_t *tex, rgbdata_t *const *co
{
const r_vk_image_create_t create = {
.debug_name = tex->name,
.debug_name = TEX_NAME(tex),
.width = tex->width,
.height = tex->height,
.mips = mipCount,
@ -462,6 +462,7 @@ void R_VkTextureDestroy( int index, vk_texture_t *tex ) {
setDescriptorSet(index, tex, kColorspaceNative);
tex->total_size = 0;
tex->width = tex->height = 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;
@ -488,7 +489,7 @@ 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 ));
Q_strncpy( TEX_NAME(dest), name, sizeof( TEX_NAME(dest) ));
return uploadTexture(-1, dest, sides, 6, true, colorspace_hint);
}

View File

@ -1,14 +1,17 @@
#pragma once
#include "r_textures.h"
#include "vk_core.h"
#include "vk_image.h"
#include "vk_const.h"
#include "unordered_roadmap.h"
typedef struct vk_texture_s
{
char name[256];
urmom_header_t hdr_;
//char name[256];
int width, height;
uint32_t flags;
@ -19,17 +22,14 @@ typedef struct vk_texture_s
VkDescriptorSet descriptor_unorm;
} vk;
// Internals for hash table
uint texnum;
uint hashValue;
struct vk_texture_s *nextHash;
int refcount;
// TODO "cache" eviction
// int used_maps_ago;
} vk_texture_t;
#define TEX_NAME(tex) ((tex)->hdr_.key)
typedef enum {
kColorspaceNative,
kColorspaceLinear,