[vulkan] Add a function to load texture arrays

I needed to create an array texture and didn't feel like doing all that
boilerplate again :P.
This commit is contained in:
Bill Currie 2022-05-26 18:43:15 +09:00
parent e86e93551d
commit 4dc1988af1
2 changed files with 43 additions and 15 deletions

View file

@ -19,6 +19,8 @@ void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette,
int alpha, int count);
qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip,
const char *name);
qfv_tex_t *Vulkan_LoadTexArray (struct vulkan_ctx_s *ctx, tex_t *tex,
int layers, int mip, const char *name);
qfv_tex_t *Vulkan_LoadEnvMap (struct vulkan_ctx_s *ctx, tex_t *tex,
const char *name);
qfv_tex_t *Vulkan_LoadEnvSides (struct vulkan_ctx_s *ctx, tex_t **tex,

View file

@ -145,7 +145,8 @@ stage_tex_data (qfv_packet_t *packet, tex_t *tex, int bpp)
}
qfv_tex_t *
Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
Vulkan_LoadTexArray (vulkan_ctx_t *ctx, tex_t *tex, int layers, int mip,
const char *name)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
@ -156,8 +157,15 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
return 0;
}
for (int i = 1; i < layers; i++) {
if (tex[i].width != tex[0].width || tex[i].height != tex[0].height
|| tex[i].format != tex[0].format) {
return 0;
}
}
if (mip) {
mip = QFV_MipLevels (tex->width, tex->height);
mip = QFV_MipLevels (tex[0].width, tex[0].height);
} else {
mip = 1;
}
@ -166,9 +174,15 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
//FIXME this whole thing is ineffiecient, especially for small textures
qfv_tex_t *qtex = malloc (sizeof (qfv_tex_t));
VkExtent3D extent = { tex->width, tex->height, 1 };
qtex->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, format, extent,
mip, 1, VK_SAMPLE_COUNT_1_BIT,
VkExtent3D extent = { tex[0].width, tex[0].height, 1 };
VkImageType itype = layers > 0 ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_2D;
VkImageType vtype = layers > 0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY
: VK_IMAGE_VIEW_TYPE_2D;
if (layers < 1) {
layers = 1;
}
qtex->image = QFV_CreateImage (device, 0, itype, format, extent,
mip, layers, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_SAMPLED_BIT);
@ -180,31 +194,37 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, qtex->memory,
va (ctx->va_ctx, "memory:%s", name));
QFV_BindImageMemory (device, qtex->image, qtex->memory, 0);
qtex->view = QFV_CreateImageView (device, qtex->image,
VK_IMAGE_VIEW_TYPE_2D,
qtex->view = QFV_CreateImageView (device, qtex->image, vtype,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_ASPECT_COLOR_BIT);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view,
va (ctx->va_ctx, "iview:%s", name));
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
stage_tex_data (packet, tex, bpp);
VkBufferImageCopy copy[layers];
copy[0] = (VkBufferImageCopy) {
0, 0, 0,
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
{0, 0, 0}, {tex[0].width, tex[0].height, 1},
};
for (int i = 0; i < layers; i++) {
copy[i] = copy[0];
copy[i].bufferOffset = stage_tex_data (packet, &tex[i], bpp);
copy[i].imageSubresource.baseArrayLayer = i;
}
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
ib.barrier.image = qtex->image;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
0, 0, 0, 0, 0,
1, &ib.barrier);
VkBufferImageCopy copy = {
packet->offset, 0, 0,
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
{0, 0, 0}, {tex->width, tex->height, 1},
};
dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer,
qtex->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &copy);
layers, copy);
if (mip == 1) {
ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
ib.barrier.image = qtex->image;
@ -213,12 +233,18 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
1, &ib.barrier);
} else {
QFV_GenerateMipMaps (device, packet->cmd, qtex->image,
mip, tex->width, tex->height, 1);
mip, tex->width, tex->height, layers);
}
QFV_PacketSubmit (packet);
return qtex;
}
qfv_tex_t *
Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
{
return Vulkan_LoadTexArray (ctx, tex, 0, mip, name);
}
static qfv_tex_t *
create_cubetex (vulkan_ctx_t *ctx, int size, VkFormat format,
const char *name)