vk: move things around between {r,vk}_texture
Another step in preparation for new hash table and better lifetime management
This commit is contained in:
parent
b016de0c83
commit
c36080c982
|
@ -1,3 +1,27 @@
|
|||
# 2023-10-24 E318
|
||||
- [ ] use new hashmap for textures
|
||||
- [ ] use vk_texure array directly as open addressing hash table
|
||||
- [ ] Completely hide `struct vk_texture`
|
||||
- [ ] just try
|
||||
- [ ] texture indexes are no longer consecutive
|
||||
- [ ] blue noise texture breaks => make it a separate (3d) thing
|
||||
- [ ] index=0 is now valid
|
||||
- I. mark 0 as occupied to avoid allocating it
|
||||
- II. Increase all returned indexes by 1. Then dec it back wherever it is passed back
|
||||
- (SAD): cannot make builtin textures have stable indexes anymore
|
||||
|
||||
# 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)
|
||||
|
||||
# Programmable render
|
||||
- [ ] what if new meatpipe has different image format for a creatable image?
|
||||
- [ ] implicit dependency tracking. pass defines:
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "vk_logs.h"
|
||||
#include "r_speeds.h"
|
||||
|
||||
#define PCG_IMPLEMENT
|
||||
#include "pcg.h"
|
||||
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "crtlib.h"
|
||||
#include "crclib.h" // COM_HashKey
|
||||
|
@ -25,12 +28,24 @@ vk_texture_t vk_textures[MAX_TEXTURES];
|
|||
vk_texture_t* vk_texturesHashTable[TEXTURES_HASH_SIZE];
|
||||
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;
|
||||
|
||||
// FIXME imported from vk_textures.h
|
||||
qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint);
|
||||
void unloadSkybox( void );
|
||||
|
||||
static void createDefaultTextures( void );
|
||||
static int textureLoadFromFileF(int flags, colorspace_hint_e colorspace, const char *fmt, ...);
|
||||
|
||||
qboolean R_TexturesInit( void ) {
|
||||
tglob.mempool = Mem_AllocPool( "vktextures" );
|
||||
g_textures.mempool = Mem_AllocPool( "vktextures" );
|
||||
|
||||
memset( vk_textures, 0, sizeof( vk_textures ));
|
||||
memset( vk_texturesHashTable, 0, sizeof( vk_texturesHashTable ));
|
||||
|
@ -43,7 +58,12 @@ qboolean R_TexturesInit( void ) {
|
|||
vk_texturesHashTable[vk_textures->hashValue] = vk_textures;
|
||||
vk_numTextures = 1;
|
||||
|
||||
return R_VkTexturesInit();
|
||||
createDefaultTextures();
|
||||
|
||||
if (!R_VkTexturesInit())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_TexturesShutdown( void )
|
||||
|
@ -125,10 +145,10 @@ static vk_texture_t *Common_TextureForName( const char *name )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* FIXME static*/ rgbdata_t *Common_FakeImage( int width, int height, int depth, int flags )
|
||||
static rgbdata_t *Common_FakeImage( int width, int height, int depth, int flags )
|
||||
{
|
||||
// TODO: Fix texture and it's buffer leaking.
|
||||
rgbdata_t *r_image = Mem_Malloc( tglob.mempool, sizeof( rgbdata_t ) );
|
||||
rgbdata_t *r_image = Mem_Malloc( g_textures.mempool, sizeof( rgbdata_t ) );
|
||||
|
||||
// also use this for bad textures, but without alpha
|
||||
r_image->width = Q_max( 1, width );
|
||||
|
@ -140,7 +160,7 @@ static vk_texture_t *Common_TextureForName( const char *name )
|
|||
r_image->size = r_image->width * r_image->height * r_image->depth * 4;
|
||||
if( FBitSet( r_image->flags, IMAGE_CUBEMAP )) r_image->size *= 6;
|
||||
|
||||
r_image->buffer = Mem_Malloc( tglob.mempool, r_image->size);
|
||||
r_image->buffer = Mem_Malloc( g_textures.mempool, r_image->size);
|
||||
r_image->palette = NULL;
|
||||
r_image->numMips = 1;
|
||||
r_image->encode = 0;
|
||||
|
@ -150,6 +170,151 @@ static vk_texture_t *Common_TextureForName( const char *name )
|
|||
return r_image;
|
||||
}
|
||||
|
||||
#define BLUE_NOISE_NAME_F "bluenoise/LDR_RGBA_%d.png"
|
||||
|
||||
static void generateFallbackNoiseTextures(void) {
|
||||
pcg32_random_t pcg_state = {
|
||||
BLUE_NOISE_SIZE * BLUE_NOISE_SIZE - 1,
|
||||
17,
|
||||
};
|
||||
uint32_t scratch[BLUE_NOISE_SIZE * BLUE_NOISE_SIZE];
|
||||
rgbdata_t pic = {
|
||||
.width = BLUE_NOISE_SIZE,
|
||||
.height = BLUE_NOISE_SIZE,
|
||||
.depth = 1,
|
||||
.flags = 0,
|
||||
.type = PF_RGBA_32,
|
||||
.size = BLUE_NOISE_SIZE * BLUE_NOISE_SIZE * 4,
|
||||
.buffer = (byte*)&scratch,
|
||||
.palette = NULL,
|
||||
.numMips = 1,
|
||||
.encode = 0,
|
||||
};
|
||||
|
||||
int blueNoiseTexturesBegin = -1;
|
||||
for (int i = 0; i < BLUE_NOISE_SIZE; ++i) {
|
||||
for (int j = 0; j < COUNTOF(scratch); ++j) {
|
||||
scratch[j] = pcg32_random_r(&pcg_state);
|
||||
}
|
||||
|
||||
char name[256];
|
||||
snprintf(name, sizeof(name), BLUE_NOISE_NAME_F, i);
|
||||
const int texid = R_TextureUploadFromBufferNew(name, &pic, TF_NOMIPMAP);
|
||||
ASSERT(texid > 0);
|
||||
|
||||
if (blueNoiseTexturesBegin == -1) {
|
||||
ASSERT(texid == BLUE_NOISE_TEXTURE_ID);
|
||||
blueNoiseTexturesBegin = texid;
|
||||
} else {
|
||||
ASSERT(blueNoiseTexturesBegin + i == texid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void loadBlueNoiseTextures(void) {
|
||||
int blueNoiseTexturesBegin = -1;
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
const int texid = textureLoadFromFileF(TF_NOMIPMAP, kColorspaceLinear, BLUE_NOISE_NAME_F, i);
|
||||
|
||||
if (blueNoiseTexturesBegin == -1) {
|
||||
if (texid <= 0) {
|
||||
ERR("Couldn't find precomputed blue noise textures. Generating bad quality regular noise textures as a fallback");
|
||||
generateFallbackNoiseTextures();
|
||||
return;
|
||||
}
|
||||
|
||||
blueNoiseTexturesBegin = texid;
|
||||
} else {
|
||||
ASSERT(texid > 0);
|
||||
ASSERT(blueNoiseTexturesBegin + i == texid);
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Base blue noise texture is %d", blueNoiseTexturesBegin);
|
||||
ASSERT(blueNoiseTexturesBegin == BLUE_NOISE_TEXTURE_ID);
|
||||
}
|
||||
|
||||
static void createDefaultTextures( void )
|
||||
{
|
||||
int dx2, dy, d;
|
||||
int x, y;
|
||||
rgbdata_t *pic;
|
||||
|
||||
// emo-texture from quake1
|
||||
pic = Common_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR );
|
||||
|
||||
for( y = 0; y < 16; y++ )
|
||||
{
|
||||
for( x = 0; x < 16; x++ )
|
||||
{
|
||||
if(( y < 8 ) ^ ( x < 8 ))
|
||||
((uint *)pic->buffer)[y*16+x] = 0xFFFF00FF;
|
||||
else ((uint *)pic->buffer)[y*16+x] = 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
||||
tglob.defaultTexture = R_TextureUploadFromBufferNew( REF_DEFAULT_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// particle texture from quake1
|
||||
pic = Common_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA );
|
||||
|
||||
for( x = 0; x < 16; x++ )
|
||||
{
|
||||
dx2 = x - 8;
|
||||
dx2 = dx2 * dx2;
|
||||
|
||||
for( y = 0; y < 16; y++ )
|
||||
{
|
||||
dy = y - 8;
|
||||
d = 255 - 35 * sqrt( dx2 + dy * dy );
|
||||
pic->buffer[( y * 16 + x ) * 4 + 3] = bound( 0, d, 255 );
|
||||
}
|
||||
}
|
||||
|
||||
tglob.particleTexture = R_TextureUploadFromBufferNew( REF_PARTICLE_TEXTURE, pic, TF_CLAMP );
|
||||
|
||||
// white texture
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFFFFFFFF;
|
||||
tglob.whiteTexture = R_TextureUploadFromBufferNew( REF_WHITE_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// gray texture
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFF7F7F7F;
|
||||
tglob.grayTexture = R_TextureUploadFromBufferNew( REF_GRAY_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// black texture
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFF000000;
|
||||
tglob.blackTexture = R_TextureUploadFromBufferNew( REF_BLACK_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// cinematic dummy
|
||||
pic = Common_FakeImage( 640, 100, 1, IMAGE_HAS_COLOR );
|
||||
tglob.cinTexture = R_TextureUploadFromBufferNew( "*cintexture", pic, TF_NOMIPMAP|TF_CLAMP );
|
||||
|
||||
{
|
||||
rgbdata_t *sides[6];
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFFFFFFFF;
|
||||
|
||||
sides[0] = pic;
|
||||
sides[1] = pic;
|
||||
sides[2] = pic;
|
||||
sides[3] = pic;
|
||||
sides[4] = pic;
|
||||
sides[5] = pic;
|
||||
|
||||
R_VkTexturesSkyboxUpload( "skybox_placeholder", sides, kColorspaceGamma, true );
|
||||
}
|
||||
|
||||
loadBlueNoiseTextures();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_ProcessImage
|
||||
|
@ -428,7 +593,7 @@ const char* R_TextureGetNameByIndex( unsigned int texnum )
|
|||
return vk_textures[texnum].name;
|
||||
}
|
||||
|
||||
/* FIXME static */ int loadTextureInternal( const char *name, const byte *buf, size_t size, int flags, colorspace_hint_e colorspace_hint, qboolean force_update ) {
|
||||
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 ))
|
||||
return 0;
|
||||
|
||||
|
@ -462,7 +627,7 @@ const char* R_TextureGetNameByIndex( unsigned int texnum )
|
|||
// upload texture
|
||||
VK_ProcessImage( tex, pic );
|
||||
|
||||
if( !uploadTexture( tex, &pic, 1, false, colorspace_hint ))
|
||||
if( !R_VkTextureUpload( tex, &pic, 1, false, colorspace_hint ))
|
||||
{
|
||||
// FIXME remove from hash table
|
||||
memset( tex, 0, sizeof( vk_texture_t ));
|
||||
|
@ -484,6 +649,22 @@ int R_TextureUploadFromFile( const char *name, const byte *buf, size_t size, int
|
|||
return loadTextureInternal(name, buf, size, flags, kColorspaceGamma, force_update);
|
||||
}
|
||||
|
||||
int R_TextureUploadFromFileEx( const char *filename, colorspace_hint_e colorspace, qboolean force_reload) {
|
||||
return loadTextureInternal( filename, NULL, 0, 0, colorspace, force_reload );
|
||||
}
|
||||
|
||||
static int textureLoadFromFileF(int flags, colorspace_hint_e colorspace, const char *fmt, ...) {
|
||||
int tex_id = 0;
|
||||
char buffer[1024];
|
||||
va_list argptr;
|
||||
va_start( argptr, fmt );
|
||||
vsnprintf( buffer, sizeof buffer, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
const qboolean force_update = false;
|
||||
return loadTextureInternal(buffer, NULL, 0, flags, colorspace, force_update);
|
||||
}
|
||||
|
||||
void R_TextureFree( unsigned int texnum ) {
|
||||
// FIXME this is incorrect and leads to missing textures
|
||||
R_TextureRelease( texnum );
|
||||
|
@ -518,7 +699,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( !uploadTexture( tex, pic, pic_count, false, kColorspaceGamma ))
|
||||
if( !R_VkTextureUpload( tex, pic, pic_count, false, kColorspaceGamma ))
|
||||
{
|
||||
memset( tex, 0, sizeof( vk_texture_t ));
|
||||
return 0;
|
||||
|
@ -619,8 +800,8 @@ static qboolean loadSkybox( const char *prefix, int style ) {
|
|||
if( !Common_CheckTexName( prefix ))
|
||||
goto cleanup;
|
||||
|
||||
Q_strncpy( tglob.skybox_cube.name, prefix, sizeof( tglob.skybox_cube.name ));
|
||||
success = uploadTexture(&tglob.skybox_cube, sides, 6, true, kColorspaceGamma);
|
||||
|
||||
R_VkTexturesSkyboxUpload( prefix, sides, kColorspaceGamma, false );
|
||||
|
||||
cleanup:
|
||||
for (int j = 0; j < i; ++j)
|
||||
|
@ -630,7 +811,6 @@ cleanup:
|
|||
tglob.fCustomSkybox = true;
|
||||
DEBUG( "Skybox done" );
|
||||
} else {
|
||||
tglob.skybox_cube.name[0] = '\0';
|
||||
ERR( "Skybox failed" );
|
||||
unloadSkybox();
|
||||
}
|
||||
|
@ -666,10 +846,10 @@ void R_TextureSetupSky( const char *skyboxname ) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Try default skybox if failed
|
||||
if (Q_stricmp(skyboxname, skybox_default) != 0) {
|
||||
WARN("missed or incomplete skybox '%s'", skyboxname);
|
||||
// FIXME infinite recursion
|
||||
R_TextureSetupSky( "desert" ); // force to default
|
||||
WARN("missed or incomplete skybox '%s', trying default '%s'", skyboxname, skybox_default);
|
||||
R_TextureSetupSky( skybox_default );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -729,3 +909,40 @@ int R_TextureCreateDummy_FIXME( const char *name ) {
|
|||
|
||||
return R_TextureUploadFromBufferNew(name, pic, TF_NOMIPMAP);
|
||||
}
|
||||
|
||||
vk_texture_t *R_TextureGetByIndex(int index)
|
||||
{
|
||||
ASSERT(index >= 0);
|
||||
ASSERT(index < MAX_TEXTURES);
|
||||
//return g_vktextures.textures + index;
|
||||
return vk_textures + index;
|
||||
}
|
||||
|
||||
int R_TexturesGetParm( int parm, int arg ) {
|
||||
const vk_texture_t *const tex = R_TextureGetByIndex( arg );
|
||||
|
||||
switch(parm){
|
||||
case PARM_TEX_WIDTH:
|
||||
case PARM_TEX_SRC_WIDTH: // TODO why is this separate?
|
||||
return tex->width;
|
||||
case PARM_TEX_HEIGHT:
|
||||
case PARM_TEX_SRC_HEIGHT:
|
||||
return tex->height;
|
||||
case PARM_TEX_FLAGS:
|
||||
return tex->flags;
|
||||
// TODO
|
||||
case PARM_TEX_SKYBOX:
|
||||
case PARM_TEX_SKYTEXNUM:
|
||||
case PARM_TEX_LIGHTMAP:
|
||||
case PARM_TEX_TARGET:
|
||||
case PARM_TEX_TEXNUM:
|
||||
case PARM_TEX_DEPTH:
|
||||
case PARM_TEX_GLFORMAT:
|
||||
case PARM_TEX_ENCODE:
|
||||
case PARM_TEX_MIPCOUNT:
|
||||
case PARM_TEX_MEMORY:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,47 @@
|
|||
#include "com_model.h" // required for ref_api.h
|
||||
#include "ref_api.h" // texFlags_t
|
||||
|
||||
#define MAX_LIGHTMAPS 256
|
||||
|
||||
typedef struct vk_textures_global_s
|
||||
{
|
||||
// TODO Fix these at compile time statically, akin to BLUE_NOISE_TEXTURE_ID
|
||||
int defaultTexture; // use for bad textures
|
||||
int particleTexture;
|
||||
int whiteTexture;
|
||||
int grayTexture;
|
||||
int blackTexture;
|
||||
int solidskyTexture; // quake1 solid-sky layer
|
||||
int alphaskyTexture; // quake1 alpha-sky layer
|
||||
int lightmapTextures[MAX_LIGHTMAPS];
|
||||
int dlightTexture; // custom dlight texture
|
||||
int cinTexture; // cinematic texture
|
||||
|
||||
// Hardcoded expected blue noise texture slot
|
||||
// TODO consider moving it into a separate resource bindable by request
|
||||
// TODO make it a 3D texture. Currently it's just a sequence of BLUE_NOISE_SIZE textures, loaded into consecutive slots.
|
||||
#define BLUE_NOISE_TEXTURE_ID 7
|
||||
|
||||
// Hardcode blue noise texture size to 64x64x64
|
||||
#define BLUE_NOISE_SIZE 64
|
||||
|
||||
// TODO wire it up for ref_interface_t return
|
||||
qboolean fCustomSkybox;
|
||||
|
||||
// TODO:
|
||||
//1. vk_texture_t blue_noise; 3d texture
|
||||
//2. separate binding similar to skybox in vk_rtx.c and shaders
|
||||
//3. patch shader function
|
||||
} vk_textures_global_t;
|
||||
|
||||
// TODO rename this consistently
|
||||
extern vk_textures_global_t tglob;
|
||||
|
||||
qboolean R_TexturesInit( void );
|
||||
void R_TexturesShutdown( void );
|
||||
|
||||
// Ref interface functions, exported
|
||||
// TODO mark names somehow, ie. R_TextureApi... ?
|
||||
int R_TextureFindByName( const char *name );
|
||||
const char* R_TextureGetNameByIndex( unsigned int texnum );
|
||||
|
||||
|
@ -18,4 +55,13 @@ int R_TextureUploadFromFile( const char *name, const byte *buf, size_t size, int
|
|||
int R_TextureUploadFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update_only );
|
||||
void R_TextureFree( unsigned int texnum );
|
||||
|
||||
#include "vk_textures.h"
|
||||
int R_TexturesGetParm( int parm, int arg );
|
||||
|
||||
// Extra functions used in ref_vk
|
||||
|
||||
int R_TextureFindByNameF( const char *fmt, ...);
|
||||
|
||||
// Tries to find a texture by its short name
|
||||
// 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 );
|
||||
|
|
|
@ -80,6 +80,7 @@ int urmomInsert(const urmom_desc_t* desc, const char *key) {
|
|||
|
||||
if (URMOM_IS_OCCUPIED(*hdr)) {
|
||||
if (hdr->hash == hash && strcmp(key, hdr->key) == 0)
|
||||
// Return existing item
|
||||
return index;
|
||||
} else
|
||||
// Reached the end of occupied chain, return the available slot
|
||||
|
|
|
@ -582,7 +582,8 @@ static void brushDrawWater(vk_brush_model_t *bmodel, const cl_entity_t *ent, int
|
|||
APROF_SCOPE_END(brush_draw_water);
|
||||
}
|
||||
|
||||
// FIXME use this
|
||||
#if 0
|
||||
// TODO use this
|
||||
static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_t speed) {
|
||||
float sy, cy;
|
||||
float flConveyorSpeed = 0.0f;
|
||||
|
@ -610,6 +611,7 @@ static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_
|
|||
speed[0] = cy * flRate;
|
||||
speed[1] = sy * flRate;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
===============
|
||||
|
@ -644,9 +646,10 @@ const texture_t *R_TextureAnimation( const cl_entity_t *ent, const msurface_t *s
|
|||
int speed;
|
||||
|
||||
// Quake1 textures uses 10 frames per second
|
||||
/* TODO
|
||||
if( FBitSet( R_TextureGetByIndex( base->gl_texturenum )->flags, TF_QUAKEPAL ))
|
||||
speed = 10;
|
||||
else speed = 20;
|
||||
else */ speed = 20;
|
||||
|
||||
reletive = (int)(gpGlobals->time * speed) % base->anim_total;
|
||||
}
|
||||
|
@ -1566,7 +1569,7 @@ void VK_BrushUnloadTextures( model_t *mod )
|
|||
if( !tx || tx->gl_texturenum == tglob.defaultTexture )
|
||||
continue; // free slot
|
||||
|
||||
R_TextureRelease( tx->gl_texturenum ); // main texture
|
||||
R_TextureRelease( tx->fb_texturenum ); // luma texture
|
||||
R_TextureFree( tx->gl_texturenum ); // main texture
|
||||
R_TextureFree( tx->fb_texturenum ); // luma texture
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ struct xvk_image_s;
|
|||
typedef union {
|
||||
VkDescriptorBufferInfo buffer;
|
||||
VkDescriptorImageInfo image;
|
||||
VkDescriptorImageInfo *image_array;
|
||||
const VkDescriptorImageInfo *image_array;
|
||||
VkWriteDescriptorSetAccelerationStructureKHR accel;
|
||||
const struct r_vk_image_s *image_object;
|
||||
} vk_descriptor_value_t;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "vk_materials.h"
|
||||
#include "r_textures.h"
|
||||
#include "vk_textures.h"
|
||||
#include "vk_mapents.h"
|
||||
#include "vk_const.h"
|
||||
#include "profiler.h"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "vk_buffer.h"
|
||||
#include "vk_core.h"
|
||||
#include "vk_common.h"
|
||||
#include "r_textures.h"
|
||||
#include "vk_textures.h"
|
||||
#include "vk_framectl.h"
|
||||
#include "vk_renderstate.h"
|
||||
#include "vk_pipeline.h"
|
||||
|
@ -264,12 +264,12 @@ static void drawOverlay( VkCommandBuffer cmdbuf ) {
|
|||
|
||||
for (int i = 0; i < g2d.batch_count && g2d.batch[i].vertex_count > 0; ++i)
|
||||
{
|
||||
vk_texture_t *texture = R_TextureGetByIndex(g2d.batch[i].texture);
|
||||
const VkDescriptorSet tex_unorm = R_VkTextureGetDescriptorUnorm( g2d.batch[i].texture );
|
||||
const VkPipeline pipeline = g2d.pipelines[g2d.batch[i].blending_mode];
|
||||
if (texture->vk.descriptor_unorm)
|
||||
if (tex_unorm)
|
||||
{
|
||||
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, g2d.pipeline_layout, 0, 1, &texture->vk.descriptor_unorm, 0, NULL);
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, g2d.pipeline_layout, 0, 1, &tex_unorm, 0, NULL);
|
||||
vkCmdDraw(cmdbuf, g2d.batch[i].vertex_count, 1, g2d.batch[i].vertex_offset, 0);
|
||||
} // FIXME else what?
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "vk_const.h"
|
||||
#include "vk_common.h"
|
||||
#include "vk_pipeline.h"
|
||||
#include "r_textures.h"
|
||||
#include "vk_textures.h"
|
||||
#include "vk_math.h"
|
||||
#include "vk_rtx.h"
|
||||
#include "vk_descriptor.h"
|
||||
|
@ -589,14 +589,16 @@ void VK_RenderEnd( VkCommandBuffer cmdbuf, qboolean draw )
|
|||
|
||||
if (lightmap != draw->draw.lightmap) {
|
||||
lightmap = draw->draw.lightmap;
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 2, 1, &R_TextureGetByIndex(lightmap)->vk.descriptor_unorm, 0, NULL);
|
||||
const VkDescriptorSet lm_unorm = R_VkTextureGetDescriptorUnorm(lightmap);
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 2, 1, &lm_unorm, 0, NULL);
|
||||
}
|
||||
|
||||
if (texture != draw->draw.texture)
|
||||
{
|
||||
texture = draw->draw.texture;
|
||||
const VkDescriptorSet tex_unorm = R_VkTextureGetDescriptorUnorm(texture);
|
||||
// TODO names/enums for binding points
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 1, 1, &R_TextureGetByIndex(texture)->vk.descriptor_unorm, 0, NULL);
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 1, 1, &tex_unorm, 0, NULL);
|
||||
}
|
||||
|
||||
// Only indexed mode is supported
|
||||
|
|
|
@ -245,20 +245,26 @@ static const char *getParmName(int parm)
|
|||
|
||||
static int VK_RefGetParm( int parm, int arg )
|
||||
{
|
||||
vk_texture_t *tex = NULL;
|
||||
|
||||
// TODO all PARM_TEX handle in r_texture internally
|
||||
switch(parm){
|
||||
case PARM_TEX_WIDTH:
|
||||
case PARM_TEX_SRC_WIDTH: // TODO why is this separate?
|
||||
tex = R_TextureGetByIndex(arg);
|
||||
return tex->width;
|
||||
case PARM_TEX_HEIGHT:
|
||||
case PARM_TEX_SRC_WIDTH: // TODO why is this separate?
|
||||
case PARM_TEX_SRC_HEIGHT:
|
||||
tex = R_TextureGetByIndex(arg);
|
||||
return tex->height;
|
||||
case PARM_TEX_FLAGS:
|
||||
tex = R_TextureGetByIndex(arg);
|
||||
return tex->flags;
|
||||
/* TODO
|
||||
case PARM_TEX_SKYBOX:
|
||||
case PARM_TEX_SKYTEXNUM:
|
||||
case PARM_TEX_LIGHTMAP:
|
||||
case PARM_TEX_TARGET:
|
||||
case PARM_TEX_TEXNUM:
|
||||
case PARM_TEX_DEPTH:
|
||||
case PARM_TEX_GLFORMAT:
|
||||
case PARM_TEX_ENCODE:
|
||||
case PARM_TEX_MIPCOUNT:
|
||||
case PARM_TEX_MEMORY:
|
||||
*/
|
||||
return R_TexturesGetParm( parm, arg );
|
||||
case PARM_MODERNFLASHLIGHT:
|
||||
if (CVAR_TO_BOOL( vk_rtx )) {
|
||||
return true;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "vk_pipeline.h"
|
||||
#include "vk_ray_internal.h"
|
||||
#include "vk_staging.h"
|
||||
#include "r_textures.h"
|
||||
#include "vk_textures.h"
|
||||
#include "vk_combuf.h"
|
||||
#include "vk_logs.h"
|
||||
|
||||
|
@ -610,7 +610,7 @@ qboolean VK_RayInit( void )
|
|||
g_rtx.res[ExternalResource_textures].resource = (vk_resource_t){
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.value = (vk_descriptor_value_t){
|
||||
.image_array = tglob.dii_all_textures,
|
||||
.image_array = R_VkTexturesGetAllDescriptorsArray(),
|
||||
}
|
||||
};
|
||||
g_rtx.res[ExternalResource_textures].refcount = 1;
|
||||
|
|
|
@ -10,21 +10,17 @@
|
|||
#include "alolcator.h"
|
||||
#include "profiler.h"
|
||||
|
||||
|
||||
#include "xash3d_mathlib.h" // bound
|
||||
|
||||
#define PCG_IMPLEMENT
|
||||
#include "pcg.h"
|
||||
|
||||
#include "ktx2.h"
|
||||
|
||||
#include <math.h> // sqrt
|
||||
|
||||
vk_textures_global_t tglob = {0};
|
||||
|
||||
#define LOG_MODULE LogModule_Textures
|
||||
#define MODULE_NAME "textures"
|
||||
|
||||
#define MAX_SAMPLERS 8 // TF_NEAREST x 2 * TF_BORDER x 2 * TF_CLAMP x 2
|
||||
|
||||
static struct {
|
||||
struct {
|
||||
int count;
|
||||
|
@ -38,11 +34,15 @@ static struct {
|
|||
|
||||
VkSampler default_sampler;
|
||||
|
||||
vk_texture_t cubemap_placeholder;
|
||||
|
||||
//vk_texture_t textures[MAX_TEXTURES];
|
||||
//alo_int_pool_t textures_free;
|
||||
} g_textures;
|
||||
|
||||
// All textures descriptors in their native formats used for RT
|
||||
VkDescriptorImageInfo dii_all_textures[MAX_TEXTURES];
|
||||
|
||||
vk_texture_t skybox_cube;
|
||||
vk_texture_t cubemap_placeholder;
|
||||
} g_vktextures;
|
||||
|
||||
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
|
||||
|
||||
|
@ -55,34 +55,28 @@ 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 void VK_CreateInternalTextures(void);
|
||||
static VkSampler pickSamplerForFlags( texFlags_t flags );
|
||||
static void textureDestroyVkImage( vk_texture_t *tex );
|
||||
|
||||
// FIXME should be static
|
||||
void unloadSkybox( void );
|
||||
qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint);
|
||||
/* FIXME static */ int loadTextureInternal( const char *name, const byte *buf, size_t size, int flags, colorspace_hint_e colorspace_hint, qboolean force_update );
|
||||
/* FIXME static */ rgbdata_t *Common_FakeImage( int width, int height, int depth, int flags );
|
||||
/* FIXME static */ qboolean Common_CheckTexName( const char *name );
|
||||
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_textures.stats.count, "count", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_textures.stats.size_total, "size_total", kSpeedsMetricBytes);
|
||||
R_SPEEDS_METRIC(g_vktextures.stats.count, "count", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_vktextures.stats.size_total, "size_total", kSpeedsMetricBytes);
|
||||
|
||||
// TODO really check device caps for this
|
||||
gEngine.Image_AddCmdFlags( IL_DDS_HARDWARE | IL_KTX2_RAW );
|
||||
|
||||
g_textures.default_sampler = pickSamplerForFlags(0);
|
||||
ASSERT(g_textures.default_sampler != VK_NULL_HANDLE);
|
||||
g_vktextures.default_sampler = pickSamplerForFlags(0);
|
||||
ASSERT(g_vktextures.default_sampler != VK_NULL_HANDLE);
|
||||
|
||||
/* FIXME
|
||||
// validate cvars
|
||||
R_SetTextureParameters();
|
||||
*/
|
||||
|
||||
VK_CreateInternalTextures();
|
||||
|
||||
/* FIXME
|
||||
gEngine.Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" );
|
||||
*/
|
||||
|
@ -96,10 +90,10 @@ qboolean R_VkTexturesInit( void ) {
|
|||
if (tex->vk.image.view)
|
||||
continue;
|
||||
|
||||
tglob.dii_all_textures[i] = (VkDescriptorImageInfo){
|
||||
g_vktextures.dii_all_textures[i] = (VkDescriptorImageInfo){
|
||||
.imageView = default_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.sampler = g_textures.default_sampler,
|
||||
.sampler = g_vktextures.default_sampler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -107,192 +101,27 @@ qboolean R_VkTexturesInit( void ) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void textureDestroy( int index );
|
||||
static void textureDestroy( unsigned int index );
|
||||
|
||||
void R_VkTexturesShutdown( void ) {
|
||||
/* for( unsigned int i = 0; i < COUNTOF(g_textures.textures); i++ ) */
|
||||
/* for( unsigned int i = 0; i < COUNTOF(g_vktextures.textures); i++ ) */
|
||||
/* textureDestroy( i ); */
|
||||
|
||||
unloadSkybox();
|
||||
|
||||
R_VkImageDestroy(&g_textures.cubemap_placeholder.vk.image);
|
||||
g_textures.stats.size_total -= g_textures.cubemap_placeholder.total_size;
|
||||
g_textures.stats.count--;
|
||||
memset(&g_textures.cubemap_placeholder, 0, sizeof(g_textures.cubemap_placeholder));
|
||||
textureDestroyVkImage(&g_vktextures.cubemap_placeholder);
|
||||
|
||||
for (int i = 0; i < COUNTOF(g_textures.samplers); ++i) {
|
||||
if (g_textures.samplers[i].sampler != VK_NULL_HANDLE)
|
||||
vkDestroySampler(vk_core.device, g_textures.samplers[i].sampler, NULL);
|
||||
// FIXME g_vktextures.stats.size_total -= g_vktextures.cubemap_placeholder.total_size;
|
||||
|
||||
g_vktextures.stats.count--;
|
||||
|
||||
|
||||
for (int i = 0; i < COUNTOF(g_vktextures.samplers); ++i) {
|
||||
if (g_vktextures.samplers[i].sampler != VK_NULL_HANDLE)
|
||||
vkDestroySampler(vk_core.device, g_vktextures.samplers[i].sampler, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
vk_texture_t *R_TextureGetByIndex(int index)
|
||||
{
|
||||
ASSERT(index >= 0);
|
||||
ASSERT(index < MAX_TEXTURES);
|
||||
//return g_textures.textures + index;
|
||||
return vk_textures + index;
|
||||
}
|
||||
|
||||
static int textureLoadFromFileF(int flags, colorspace_hint_e colorspace, const char *fmt, ...) {
|
||||
int tex_id = 0;
|
||||
char buffer[1024];
|
||||
va_list argptr;
|
||||
va_start( argptr, fmt );
|
||||
vsnprintf( buffer, sizeof buffer, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
const qboolean force_update = false;
|
||||
return loadTextureInternal(buffer, NULL, 0, flags, colorspace, force_update);
|
||||
}
|
||||
|
||||
#define BLUE_NOISE_NAME_F "bluenoise/LDR_RGBA_%d.png"
|
||||
|
||||
static qboolean generateFallbackNoiseTextures(void) {
|
||||
pcg32_random_t pcg_state = {
|
||||
BLUE_NOISE_SIZE * BLUE_NOISE_SIZE - 1,
|
||||
17,
|
||||
};
|
||||
uint32_t scratch[BLUE_NOISE_SIZE * BLUE_NOISE_SIZE];
|
||||
rgbdata_t pic = {
|
||||
.width = BLUE_NOISE_SIZE,
|
||||
.height = BLUE_NOISE_SIZE,
|
||||
.depth = 1,
|
||||
.flags = 0,
|
||||
.type = PF_RGBA_32,
|
||||
.size = BLUE_NOISE_SIZE * BLUE_NOISE_SIZE * 4,
|
||||
.buffer = (byte*)&scratch,
|
||||
.palette = NULL,
|
||||
.numMips = 1,
|
||||
.encode = 0,
|
||||
};
|
||||
|
||||
int blueNoiseTexturesBegin = -1;
|
||||
for (int i = 0; i < BLUE_NOISE_SIZE; ++i) {
|
||||
for (int j = 0; j < COUNTOF(scratch); ++j) {
|
||||
scratch[j] = pcg32_random_r(&pcg_state);
|
||||
}
|
||||
|
||||
char name[256];
|
||||
snprintf(name, sizeof(name), BLUE_NOISE_NAME_F, i);
|
||||
const int texid = R_TextureUploadFromBufferNew(name, &pic, TF_NOMIPMAP);
|
||||
ASSERT(texid > 0);
|
||||
|
||||
if (blueNoiseTexturesBegin == -1) {
|
||||
ASSERT(texid == BLUE_NOISE_TEXTURE_ID);
|
||||
blueNoiseTexturesBegin = texid;
|
||||
} else {
|
||||
ASSERT(blueNoiseTexturesBegin + i == texid);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean loadBlueNoiseTextures(void) {
|
||||
int blueNoiseTexturesBegin = -1;
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
const int texid = textureLoadFromFileF(TF_NOMIPMAP, kColorspaceLinear, BLUE_NOISE_NAME_F, i);
|
||||
|
||||
if (blueNoiseTexturesBegin == -1) {
|
||||
if (texid <= 0) {
|
||||
ERR("Couldn't find precomputed blue noise textures. Generating bad quality regular noise textures as a fallback");
|
||||
return generateFallbackNoiseTextures();
|
||||
}
|
||||
|
||||
blueNoiseTexturesBegin = texid;
|
||||
} else {
|
||||
ASSERT(texid > 0);
|
||||
ASSERT(blueNoiseTexturesBegin + i == texid);
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Base blue noise texture is %d", blueNoiseTexturesBegin);
|
||||
ASSERT(blueNoiseTexturesBegin == BLUE_NOISE_TEXTURE_ID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void VK_CreateInternalTextures( void )
|
||||
{
|
||||
int dx2, dy, d;
|
||||
int x, y;
|
||||
rgbdata_t *pic;
|
||||
|
||||
// emo-texture from quake1
|
||||
pic = Common_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR );
|
||||
|
||||
for( y = 0; y < 16; y++ )
|
||||
{
|
||||
for( x = 0; x < 16; x++ )
|
||||
{
|
||||
if(( y < 8 ) ^ ( x < 8 ))
|
||||
((uint *)pic->buffer)[y*16+x] = 0xFFFF00FF;
|
||||
else ((uint *)pic->buffer)[y*16+x] = 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
||||
tglob.defaultTexture = R_TextureUploadFromBufferNew( REF_DEFAULT_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// particle texture from quake1
|
||||
pic = Common_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA );
|
||||
|
||||
for( x = 0; x < 16; x++ )
|
||||
{
|
||||
dx2 = x - 8;
|
||||
dx2 = dx2 * dx2;
|
||||
|
||||
for( y = 0; y < 16; y++ )
|
||||
{
|
||||
dy = y - 8;
|
||||
d = 255 - 35 * sqrt( dx2 + dy * dy );
|
||||
pic->buffer[( y * 16 + x ) * 4 + 3] = bound( 0, d, 255 );
|
||||
}
|
||||
}
|
||||
|
||||
tglob.particleTexture = R_TextureUploadFromBufferNew( REF_PARTICLE_TEXTURE, pic, TF_CLAMP );
|
||||
|
||||
// white texture
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFFFFFFFF;
|
||||
tglob.whiteTexture = R_TextureUploadFromBufferNew( REF_WHITE_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// gray texture
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFF7F7F7F;
|
||||
tglob.grayTexture = R_TextureUploadFromBufferNew( REF_GRAY_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// black texture
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFF000000;
|
||||
tglob.blackTexture = R_TextureUploadFromBufferNew( REF_BLACK_TEXTURE, pic, TF_COLORMAP );
|
||||
|
||||
// cinematic dummy
|
||||
pic = Common_FakeImage( 640, 100, 1, IMAGE_HAS_COLOR );
|
||||
tglob.cinTexture = R_TextureUploadFromBufferNew( "*cintexture", pic, TF_NOMIPMAP|TF_CLAMP );
|
||||
|
||||
{
|
||||
rgbdata_t *sides[6];
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFFFFFFFF;
|
||||
|
||||
sides[0] = pic;
|
||||
sides[1] = pic;
|
||||
sides[2] = pic;
|
||||
sides[3] = pic;
|
||||
sides[4] = pic;
|
||||
sides[5] = pic;
|
||||
|
||||
uploadTexture( &g_textures.cubemap_placeholder, sides, 6, true, kColorspaceGamma );
|
||||
}
|
||||
|
||||
loadBlueNoiseTextures();
|
||||
}
|
||||
|
||||
static VkFormat VK_GetFormat(pixformat_t format, colorspace_hint_e colorspace_hint ) {
|
||||
switch(format)
|
||||
{
|
||||
|
@ -377,18 +206,18 @@ static VkSampler createSamplerForFlags( texFlags_t flags ) {
|
|||
static VkSampler pickSamplerForFlags( texFlags_t flags ) {
|
||||
flags &= (TF_BORDER | TF_CLAMP | TF_NEAREST);
|
||||
|
||||
for (int i = 0; i < COUNTOF(g_textures.samplers); ++i) {
|
||||
if (g_textures.samplers[i].sampler == VK_NULL_HANDLE) {
|
||||
g_textures.samplers[i].flags = flags;
|
||||
return g_textures.samplers[i].sampler = createSamplerForFlags(flags);
|
||||
for (int i = 0; i < COUNTOF(g_vktextures.samplers); ++i) {
|
||||
if (g_vktextures.samplers[i].sampler == VK_NULL_HANDLE) {
|
||||
g_vktextures.samplers[i].flags = flags;
|
||||
return g_vktextures.samplers[i].sampler = createSamplerForFlags(flags);
|
||||
}
|
||||
|
||||
if (g_textures.samplers[i].flags == flags)
|
||||
return g_textures.samplers[i].sampler;
|
||||
if (g_vktextures.samplers[i].flags == flags)
|
||||
return g_vktextures.samplers[i].sampler;
|
||||
}
|
||||
|
||||
ERR("Couldn't find/allocate sampler for flags %x", flags);
|
||||
return g_textures.default_sampler;
|
||||
return g_vktextures.default_sampler;
|
||||
}
|
||||
|
||||
static void setDescriptorSet(vk_texture_t* const tex, colorspace_hint_e colorspace_hint) {
|
||||
|
@ -412,7 +241,7 @@ static void setDescriptorSet(vk_texture_t* const tex, colorspace_hint_e colorspa
|
|||
};
|
||||
|
||||
// Set descriptor for bindless/ray tracing
|
||||
tglob.dii_all_textures[index] = dii;
|
||||
g_vktextures.dii_all_textures[index] = dii;
|
||||
|
||||
// Continue with setting unorm descriptor for traditional renderer
|
||||
|
||||
|
@ -532,11 +361,11 @@ static qboolean uploadRawKtx2( vk_texture_t *tex, const rgbdata_t* pic ) {
|
|||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.sampler = pickSamplerForFlags( tex->flags ),
|
||||
};
|
||||
tglob.dii_all_textures[index] = dii;
|
||||
g_vktextures.dii_all_textures[index] = dii;
|
||||
}
|
||||
|
||||
g_textures.stats.size_total += tex->total_size;
|
||||
g_textures.stats.count++;
|
||||
g_vktextures.stats.size_total += tex->total_size;
|
||||
g_vktextures.stats.count++;
|
||||
|
||||
tex->width = header->pixelWidth;
|
||||
tex->height = header->pixelHeight;
|
||||
|
@ -544,7 +373,7 @@ static qboolean uploadRawKtx2( vk_texture_t *tex, const rgbdata_t* pic ) {
|
|||
return true;
|
||||
}
|
||||
|
||||
qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint) {
|
||||
qboolean R_VkTextureUpload(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) {
|
||||
|
@ -624,19 +453,11 @@ qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int nu
|
|||
|
||||
setDescriptorSet(tex, colorspace_hint);
|
||||
|
||||
g_textures.stats.size_total += tex->total_size;
|
||||
g_textures.stats.count++;
|
||||
g_vktextures.stats.size_total += tex->total_size;
|
||||
g_vktextures.stats.count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
int R_TextureUploadFromFileEx( const char *filename, colorspace_hint_e colorspace, qboolean force_reload) {
|
||||
vk_texture_t *tex;
|
||||
if( !Common_CheckTexName( filename ))
|
||||
return 0;
|
||||
|
||||
return loadTextureInternal( filename, NULL, 0, 0, colorspace, force_reload );
|
||||
}
|
||||
|
||||
static void textureDestroyVkImage( 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
|
||||
|
@ -645,8 +466,8 @@ static void textureDestroyVkImage( vk_texture_t *tex ) {
|
|||
XVK_CHECK(vkDeviceWaitIdle(vk_core.device));
|
||||
|
||||
R_VkImageDestroy(&tex->vk.image);
|
||||
g_textures.stats.size_total -= tex->total_size;
|
||||
g_textures.stats.count--;
|
||||
g_vktextures.stats.size_total -= tex->total_size;
|
||||
g_vktextures.stats.count--;
|
||||
|
||||
tex->total_size = 0;
|
||||
}
|
||||
|
@ -717,11 +538,9 @@ end:
|
|||
}
|
||||
|
||||
void unloadSkybox( void ) {
|
||||
if (tglob.skybox_cube.vk.image.image) {
|
||||
R_VkImageDestroy(&tglob.skybox_cube.vk.image);
|
||||
g_textures.stats.size_total -= tglob.skybox_cube.total_size;
|
||||
g_textures.stats.count--;
|
||||
memset(&tglob.skybox_cube, 0, sizeof(tglob.skybox_cube));
|
||||
if (g_vktextures.skybox_cube.vk.image.image) {
|
||||
textureDestroyVkImage( &g_vktextures.skybox_cube );
|
||||
memset(&g_vktextures.skybox_cube, 0, sizeof(g_vktextures.skybox_cube));
|
||||
}
|
||||
|
||||
tglob.fCustomSkybox = false;
|
||||
|
@ -737,10 +556,25 @@ void R_TextureAcquire( unsigned int texnum ) {
|
|||
|
||||
VkDescriptorImageInfo R_VkTextureGetSkyboxDescriptorImageInfo( void ) {
|
||||
return (VkDescriptorImageInfo){
|
||||
.sampler = g_textures.default_sampler,
|
||||
.imageView = tglob.skybox_cube.vk.image.view
|
||||
? tglob.skybox_cube.vk.image.view
|
||||
: g_textures.cubemap_placeholder.vk.image.view,
|
||||
.sampler = g_vktextures.default_sampler,
|
||||
.imageView = g_vktextures.skybox_cube.vk.image.view
|
||||
? g_vktextures.skybox_cube.vk.image.view
|
||||
: g_vktextures.cubemap_placeholder.vk.image.view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
VkDescriptorSet R_VkTextureGetDescriptorUnorm( uint index ) {
|
||||
ASSERT( index < MAX_TEXTURES );
|
||||
return vk_textures[index].vk.descriptor_unorm;
|
||||
}
|
||||
|
||||
const VkDescriptorImageInfo* R_VkTexturesGetAllDescriptorsArray( void ) {
|
||||
return g_vktextures.dii_all_textures;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "r_textures.h"
|
||||
|
||||
#include "vk_core.h"
|
||||
#include "vk_image.h"
|
||||
#include "vk_const.h"
|
||||
|
@ -27,52 +30,18 @@ typedef struct vk_texture_s
|
|||
// int used_maps_ago;
|
||||
} vk_texture_t;
|
||||
|
||||
#define MAX_LIGHTMAPS 256
|
||||
#define MAX_SAMPLERS 8 // TF_NEAREST x 2 * TF_BORDER x 2 * TF_CLAMP x 2
|
||||
|
||||
typedef struct vk_textures_global_s
|
||||
{
|
||||
poolhandle_t mempool;
|
||||
|
||||
// TODO Fix these at compile time statically, akin to BLUE_NOISE_TEXTURE_ID
|
||||
int defaultTexture; // use for bad textures
|
||||
int particleTexture;
|
||||
int whiteTexture;
|
||||
int grayTexture;
|
||||
int blackTexture;
|
||||
int solidskyTexture; // quake1 solid-sky layer
|
||||
int alphaskyTexture; // quake1 alpha-sky layer
|
||||
int lightmapTextures[MAX_LIGHTMAPS];
|
||||
int dlightTexture; // custom dlight texture
|
||||
int cinTexture; // cinematic texture
|
||||
|
||||
// Hardcoded expected blue noise texture slot
|
||||
// TODO consider moving it into a separate resource bindable by request
|
||||
// TODO make it a 3D texture. Currently it's just a sequence of BLUE_NOISE_SIZE textures, loaded into consecutive slots.
|
||||
#define BLUE_NOISE_TEXTURE_ID 7
|
||||
|
||||
// Hardcode blue noise texture size to 64x64x64
|
||||
#define BLUE_NOISE_SIZE 64
|
||||
|
||||
// TODO wire it up for ref_interface_t return
|
||||
qboolean fCustomSkybox;
|
||||
|
||||
// TODO move to vk_textures/g_textures
|
||||
vk_texture_t skybox_cube;
|
||||
|
||||
// All textures descriptors in their native formats used for RT
|
||||
VkDescriptorImageInfo dii_all_textures[MAX_TEXTURES];
|
||||
} vk_textures_global_t;
|
||||
|
||||
// TODO rename this consistently
|
||||
extern vk_textures_global_t tglob;
|
||||
typedef enum {
|
||||
kColorspaceNative,
|
||||
kColorspaceLinear,
|
||||
kColorspaceGamma,
|
||||
} colorspace_hint_e;
|
||||
|
||||
qboolean R_VkTexturesInit( void );
|
||||
void R_VkTexturesShutdown( void );
|
||||
|
||||
// Functions only used in this renderer
|
||||
vk_texture_t *R_TextureGetByIndex( int index );
|
||||
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);
|
||||
|
||||
// FIXME s/R_/R_Vk/
|
||||
void R_TextureAcquire( unsigned int texnum );
|
||||
|
@ -80,21 +49,10 @@ void R_TextureRelease( unsigned int texnum );
|
|||
|
||||
#define R_TextureUploadFromBufferNew(name, pic, flags) R_TextureUploadFromBuffer(name, pic, flags, false)
|
||||
|
||||
typedef enum {
|
||||
kColorspaceNative,
|
||||
kColorspaceLinear,
|
||||
kColorspaceGamma,
|
||||
} colorspace_hint_e;
|
||||
|
||||
int R_TextureUploadFromFileEx( const char *filename, colorspace_hint_e colorspace, qboolean force_reload );
|
||||
int R_TextureFindByNameF( const char *fmt, ...);
|
||||
|
||||
// Tries to find a texture by its short name
|
||||
// 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 );
|
||||
|
||||
// Used by materials to piggy-back onto texture name-to-index hash table
|
||||
int R_TextureCreateDummy_FIXME( const char *name );
|
||||
|
||||
VkDescriptorImageInfo R_VkTextureGetSkyboxDescriptorImageInfo( void );
|
||||
const VkDescriptorImageInfo* R_VkTexturesGetAllDescriptorsArray( void );
|
||||
VkDescriptorSet R_VkTextureGetDescriptorUnorm( uint index );
|
||||
|
|
Loading…
Reference in New Issue