vk: consolidate and simplify texture uploading

This commit is contained in:
Ivan Avdeev 2023-10-12 14:05:15 -04:00
parent 8ba7b3649e
commit 0a5f061ba3
1 changed files with 111 additions and 102 deletions

View File

@ -639,20 +639,64 @@ static VkSampler pickSamplerForFlags( texFlags_t flags ) {
return tglob.default_sampler_fixme;
}
static qboolean loadKtx2Raw( vk_texture_t *tex, const rgbdata_t* pic );
static void prepDestriptorSets(vk_texture_t* const tex, colorspace_hint_e colorspace_hint) {
// TODO how should we approach this:
// - per-texture desc sets can be inconvenient if texture is used in different incompatible contexts
// - update descriptor sets in batch?
if (vk_desc.next_free < MAX_TEXTURES-2) {
const int index = tex - vk_textures;
const VkDescriptorSet ds = vk_desc.sets[vk_desc.next_free++];
const VkDescriptorSet ds_unorm =
(colorspace_hint == kColorspaceGamma && tex->vk.image.view_unorm != VK_NULL_HANDLE)
? vk_desc.sets[vk_desc.next_free++] : VK_NULL_HANDLE;
static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap, colorspace_hint_e colorspace_hint) {
const VkDescriptorImageInfo dii = {
.imageView = tex->vk.image.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
.sampler = pickSamplerForFlags( tex->flags ),
};
if (num_layers == 1 && layers[0]->type == PF_KTX2_RAW)
return loadKtx2Raw(tex, layers[0]);
const VkDescriptorImageInfo dii_unorm = {
.imageView = tex->vk.image.view_unorm,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
.sampler = dii.sampler,
};
const VkFormat format = VK_GetFormat(layers[0]->type, colorspace_hint);
int mipCount = 0;
VkWriteDescriptorSet wds[2] = { {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &dii,
.dstSet = ds,
}, {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &dii_unorm,
.dstSet = ds_unorm,
}};
vkUpdateDescriptorSets(vk_core.device, ds_unorm != VK_NULL_HANDLE ? 2 : 1 , wds, 0, NULL);
tex->total_size = 0;
// FIXME detect skybox some other way
if (tex->vk.image.layers == 1) {
tglob.dii_all_textures[index] = dii;
}
// TODO non-rbga textures
tex->vk.descriptor_unorm = ds_unorm != VK_NULL_HANDLE ? ds_unorm : ds;
}
else
{
tex->vk.descriptor_unorm = VK_NULL_HANDLE;
}
}
static qboolean uploadRawKtx2( vk_texture_t *tex, const rgbdata_t* pic );
static qboolean validatePicLayers(const vk_texture_t* const tex, rgbdata_t *const *const layers, int num_layers) {
for (int i = 0; i < num_layers; ++i) {
// FIXME create empty black texture if there's no buffer
if (!layers[i]->buffer) {
@ -682,18 +726,31 @@ static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers,
}
}
return true;
}
static qboolean uploadTexture(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]))
return false;
} else {
const VkFormat format = VK_GetFormat(layers[0]->type, colorspace_hint);
int mipCount = 0;
// TODO non-rbga textures
if (!validatePicLayers(tex, layers, num_layers))
return false;
tex->width = layers[0]->width;
tex->height = layers[0]->height;
mipCount = CalcMipmapCount( tex, true);
DEBUG("Uploading texture[%d] %s, mips=%d, layers=%d", (int)(tex-vk_textures), tex->name, mipCount, num_layers);
// TODO this vvv
// // NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides
// if(( tex->depth == 1 ) && (( layers->width != tex->width ) || ( layers->height != tex->height )))
// data = GL_ResampleTexture( buf, layers->width, layers->height, tex->width, tex->height, normalMap );
// else data = buf;
// TODO (not sure why, but GL does this)
// if( !ImageDXT( layers->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( layers->flags, IMAGE_ONEBIT_ALPHA ))
// data = GL_ApplyFilter( data, tex->width, tex->height );
@ -737,59 +794,9 @@ static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers,
R_VkImageUploadEnd(&tex->vk.image);
}
// TODO how should we approach this:
// - per-texture desc sets can be inconvenient if texture is used in different incompatible contexts
// - update descriptor sets in batch?
if (vk_desc.next_free < MAX_TEXTURES-2) {
const int index = tex - vk_textures;
const VkDescriptorSet ds = vk_desc.sets[vk_desc.next_free++];
const VkDescriptorSet ds_unorm =
(colorspace_hint == kColorspaceGamma && tex->vk.image.view_unorm != VK_NULL_HANDLE)
? vk_desc.sets[vk_desc.next_free++] : VK_NULL_HANDLE;
const VkDescriptorImageInfo dii = {
.imageView = tex->vk.image.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
.sampler = pickSamplerForFlags( tex->flags ),
};
const VkDescriptorImageInfo dii_unorm = {
.imageView = tex->vk.image.view_unorm,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
.sampler = dii.sampler,
};
VkWriteDescriptorSet wds[2] = { {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &dii,
.dstSet = ds,
}, {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &dii_unorm,
.dstSet = ds_unorm,
}};
vkUpdateDescriptorSets(vk_core.device, ds_unorm != VK_NULL_HANDLE ? 2 : 1 , wds, 0, NULL);
// FIXME handle cubemaps properly w/o this garbage. they should be the same as regular textures.
if (num_layers == 1) {
tglob.dii_all_textures[index] = dii;
}
tex->vk.descriptor_unorm = ds_unorm != VK_NULL_HANDLE ? ds_unorm : ds;
}
else
{
tex->vk.descriptor_unorm = VK_NULL_HANDLE;
}
prepDestriptorSets(tex, colorspace_hint);
g_textures.stats.size_total += tex->total_size;
g_textures.stats.count++;
@ -826,7 +833,9 @@ const byte* VK_TextureData( unsigned int texnum )
return NULL;
}
static qboolean loadKtx2Raw( vk_texture_t *tex, const rgbdata_t* pic ) {
static qboolean uploadRawKtx2( vk_texture_t *tex, const rgbdata_t* pic ) {
DEBUG("Uploading raw KTX2 texture[%d] %s", (int)(tex-vk_textures), tex->name);
const byte *const data = pic->buffer;
const int size = pic->size;