[vulkan] Use 4 layer arrays for alias skins

Doesn't seem to make much difference performance-wise, but speed does
seem to be fill-rate limited due to the 8x msaa. Still, it does mean
fewer bindings to worry about.
This commit is contained in:
Bill Currie 2021-02-02 00:11:47 +09:00
parent 0d4ca46923
commit 8e63ab9f94
5 changed files with 112 additions and 78 deletions

View file

@ -37,13 +37,6 @@
#include "QF/modelgen.h" #include "QF/modelgen.h"
#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_vid.h"
typedef struct aliasskin_s {
struct qfv_tex_s *tex;
struct qfv_tex_s *glow;
struct qfv_tex_s *colora;
struct qfv_tex_s *colorb;
} aliasskin_t;
typedef struct aliasvrt_s { typedef struct aliasvrt_s {
float vertex[4]; float vertex[4];
float normal[4]; float normal[4];
@ -77,7 +70,7 @@ typedef struct qfv_light_buffer_s {
} qfv_light_buffer_t; } qfv_light_buffer_t;
#define ALIAS_BUFFER_INFOS 2 #define ALIAS_BUFFER_INFOS 2
#define ALIAS_IMAGE_INFOS 4 #define ALIAS_IMAGE_INFOS 1
typedef struct aliasframe_s { typedef struct aliasframe_s {
VkCommandBuffer cmd; VkCommandBuffer cmd;

View file

@ -46,9 +46,11 @@
#include "QF/vid.h" #include "QF/vid.h"
#include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_texture.h"
#include "QF/Vulkan/barrier.h"
#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/device.h" #include "QF/Vulkan/device.h"
#include "QF/Vulkan/debug.h" #include "QF/Vulkan/debug.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/instance.h" #include "QF/Vulkan/instance.h"
#include "QF/Vulkan/staging.h" #include "QF/Vulkan/staging.h"
@ -63,17 +65,13 @@ static vec3_t vertex_normals[NUMVERTEXNORMALS] = {
static void static void
skin_clear (int skin_offset, aliashdr_t *hdr, vulkan_ctx_t *ctx) skin_clear (int skin_offset, aliashdr_t *hdr, vulkan_ctx_t *ctx)
{ {
aliasskin_t *skin = (aliasskin_t *) ((byte *) hdr + skin_offset); qfv_device_t *device = ctx->device;
Vulkan_UnloadTex (ctx, skin->tex); qfv_devfuncs_t *dfunc = device->funcs;
if (skin->glow) { qfv_tex_t *skin = (qfv_tex_t *) ((byte *) hdr + skin_offset);
Vulkan_UnloadTex (ctx, skin->glow);
} dfunc->vkDestroyImageView (device->dev, skin->view, 0);
if (skin->colora) { dfunc->vkDestroyImage (device->dev, skin->image, 0);
Vulkan_UnloadTex (ctx, skin->colora); dfunc->vkFreeMemory (device->dev, skin->memory, 0);
}
if (skin->colorb) {
Vulkan_UnloadTex (ctx, skin->colorb);
}
} }
static void static void
@ -114,12 +112,14 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
int snum, int gnum, qboolean group, int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) maliasskindesc_t *skindesc, vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliashdr_t *header = alias_ctx->header; aliashdr_t *header = alias_ctx->header;
aliasskin_t *skin; qfv_tex_t *skin;
byte *tskin; byte *tskin;
int w, h; int w, h;
skin = Hunk_Alloc (sizeof (aliasskin_t)); skin = Hunk_Alloc (sizeof (qfv_tex_t));
skindesc->skin = (byte *) skin - (byte *) header; skindesc->skin = (byte *) skin - (byte *) header;
//FIXME move all skins into arrays(?) //FIXME move all skins into arrays(?)
w = header->mdl.skinwidth; w = header->mdl.skinwidth;
@ -128,30 +128,97 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
memcpy (tskin, skinpix, skinsize); memcpy (tskin, skinpix, skinsize);
Mod_FloodFillSkin (tskin, w, h); Mod_FloodFillSkin (tskin, w, h);
tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin + skinsize}; int mipLevels = QFV_MipLevels (w, h);
if (Mod_CalcFullbright (tskin, tskin + skinsize, skinsize)) { VkExtent3D extent = { w, h, 1 };
skin->glow = Vulkan_LoadTex (ctx, &skin_tex, 1, skin->offset = 0;
va (ctx->va_ctx, "%s:%d:%d:glow", skin->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D,
alias_ctx->mod->name, snum, gnum)); VK_FORMAT_R8G8B8A8_UNORM, extent,
Mod_ClearFullbright (tskin, tskin, skinsize); mipLevels, 4, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_USAGE_SAMPLED_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, skin->image,
va (ctx->va_ctx, "image:%s:%d:%d",
alias_ctx->mod->name, snum, gnum));
skin->memory = QFV_AllocImageMemory (device, skin->image,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
0, 0);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, skin->memory,
va (ctx->va_ctx, "memory:%s:%d:%d",
alias_ctx->mod->name, snum, gnum));
QFV_BindImageMemory (device, skin->image, skin->memory, 0);
skin->view = QFV_CreateImageView (device, skin->image,
VK_IMAGE_VIEW_TYPE_2D_ARRAY,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_ASPECT_COLOR_BIT);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, skin->view,
va (ctx->va_ctx, "iview:%s:%d:%d",
alias_ctx->mod->name, snum, gnum));
qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, "alias stage",
4 * skinsize * 4,
ctx->cmdpool);
qfv_packet_t *packet = QFV_PacketAcquire (stage);
byte *base_data = QFV_PacketExtend (packet, skinsize * 4);
byte *cola_data = QFV_PacketExtend (packet, skinsize * 4);
byte *colb_data = QFV_PacketExtend (packet, skinsize * 4);
byte *glow_data = QFV_PacketExtend (packet, skinsize * 4);
Mod_CalcFullbright (tskin, tskin + skinsize, skinsize);
Vulkan_ExpandPalette (glow_data, tskin + skinsize, vid.palette, 1,
skinsize);
Mod_ClearFullbright (tskin, tskin, skinsize);
Skin_CalcTopColors (tskin, tskin + skinsize, skinsize);
Vulkan_ExpandPalette (cola_data, tskin + skinsize, vid.palette, 1,
skinsize);
Skin_ClearTopColors (tskin, tskin, skinsize);
Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize);
Vulkan_ExpandPalette (colb_data, tskin + skinsize, vid.palette, 1,
skinsize);
Skin_ClearBottomColors (tskin, tskin, skinsize);
Vulkan_ExpandPalette (base_data, tskin, vid.palette, 1, skinsize);
VkImageMemoryBarrier barrier;
qfv_pipelinestagepair_t stages;
stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst];
barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst];
barrier.image = skin->image;
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst,
0, 0, 0, 0, 0,
1, &barrier);
VkBufferImageCopy copy = {
packet->offset, 0, 0,
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 4},
{0, 0, 0}, {w, h, 1},
};
dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer,
skin->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &copy);
if (mipLevels == 1) {
stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly];
barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
barrier.image = skin->image;
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst,
0, 0, 0, 0, 0,
1, &barrier);
} else {
QFV_GenerateMipMaps (device, packet->cmd, skin->image,
mipLevels, w, h, 4);
} }
if (Skin_CalcTopColors (tskin, tskin + skinsize, skinsize)) { QFV_PacketSubmit (packet);
skin->colora = Vulkan_LoadTex (ctx, &skin_tex, 1, QFV_DestroyStagingBuffer (stage);
va (ctx->va_ctx, "%s:%d:%d:colora",
alias_ctx->mod->name, snum, gnum));
Skin_ClearTopColors (tskin, tskin, skinsize);
}
if (Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize)) {
skin->colorb = Vulkan_LoadTex (ctx, &skin_tex, 1,
va (ctx->va_ctx, "%s:%d:%d:colorb",
alias_ctx->mod->name, snum, gnum));
Skin_ClearBottomColors (tskin, tskin, skinsize);
}
skin_tex.data = tskin;
skin->tex = Vulkan_LoadTex (ctx, &skin_tex, 1,
va (ctx->va_ctx, "%s:%d:%d:tex",
alias_ctx->mod->name,
snum, gnum));
free (tskin); free (tskin);

View file

@ -1,8 +1,5 @@
#version 450 #version 450
layout (set = 0, binding = 2) uniform sampler2D Texture; layout (set = 0, binding = 2) uniform sampler2DArray Skin;
layout (set = 0, binding = 3) uniform sampler2D GlowMap;
layout (set = 0, binding = 4) uniform sampler2D ColorA;
layout (set = 0, binding = 5) uniform sampler2D ColorB;
/* /*
layout (set = 2, binding = 0) uniform sampler2D Texture; layout (set = 2, binding = 0) uniform sampler2D Texture;
layout (set = 2, binding = 1) uniform sampler2D GlowMap; layout (set = 2, binding = 1) uniform sampler2D GlowMap;
@ -59,9 +56,9 @@ main (void)
vec4 c; vec4 c;
int i; int i;
vec3 light = vec3 (0); vec3 light = vec3 (0);
c = texture (Texture, st); c = texture (Skin, vec3 (st, 0));
c += texture (ColorA, st); c += texture (Skin, vec3 (st, 1));
c += texture (ColorB, st); c += texture (Skin, vec3 (st, 2));
if (MaxLights > 0) { if (MaxLights > 0) {
for (i = 0; i < light_count; i++) { for (i = 0; i < light_count; i++) {
@ -70,7 +67,7 @@ main (void)
} }
c *= vec4 (light, 1); c *= vec4 (light, 1);
c += texture (GlowMap, st); c += texture (Skin, vec3 (st, 3));
//frag_color = vec4((normal + 1)/2, 1); //frag_color = vec4((normal + 1)/2, 1);
frag_color = c;//fogBlend (c); frag_color = c;//fogBlend (c);
} }

View file

@ -172,24 +172,6 @@
descriptorCount = 1; descriptorCount = 1;
stageFlags = fragment; stageFlags = fragment;
}, },
{
binding = 3;
descriptorType = combined_image_sampler;
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 4;
descriptorType = combined_image_sampler;
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 5;
descriptorType = combined_image_sampler;
descriptorCount = 1;
stageFlags = fragment;
},
); );
}; };
alias.matrices = { alias.matrices = {

View file

@ -88,7 +88,7 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx)
aliashdr_t *hdr; aliashdr_t *hdr;
qfv_alias_mesh_t *mesh; qfv_alias_mesh_t *mesh;
float blend; float blend;
aliasskin_t *skin; qfv_tex_t *skin;
if (!(hdr = model->aliashdr)) { if (!(hdr = model->aliashdr)) {
hdr = Cache_Get (&model->cache); hdr = Cache_Get (&model->cache);
@ -102,7 +102,7 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx)
} else { } else {
maliasskindesc_t *skindesc; maliasskindesc_t *skindesc;
skindesc = R_AliasGetSkindesc (ent->skinnum, hdr); skindesc = R_AliasGetSkindesc (ent->skinnum, hdr);
skin = (aliasskin_t *) ((byte *) hdr + skindesc->skin); skin = (qfv_tex_t *) ((byte *) hdr + skindesc->skin);
} }
VkDeviceSize offsets[] = { VkDeviceSize offsets[] = {
@ -124,12 +124,7 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx)
dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, dfunc->vkCmdPushConstants (aframe->cmd, actx->layout,
VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_VERTEX_BIT,
64, sizeof (float), &blend); 64, sizeof (float), &blend);
aframe->imageInfo[0].imageView = get_view (skin->tex, ctx->default_white); aframe->imageInfo[0].imageView = get_view (skin, 0);
aframe->imageInfo[1].imageView = get_view (skin->glow, ctx->default_black);
aframe->imageInfo[2].imageView = get_view (skin->colora,
ctx->default_black);
aframe->imageInfo[3].imageView = get_view (skin->colorb,
ctx->default_black);
dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout, actx->layout,