[vulkan] Get alias texture loading working

That was a mess, partly premature optimizations, and some silly
mistakes.
This commit is contained in:
Bill Currie 2021-01-27 12:15:45 +09:00
parent 748217b438
commit a64f477796
4 changed files with 115 additions and 74 deletions

View file

@ -123,7 +123,7 @@ Vulkan_Mod_LoadSkin (byte *skinpix, int skinsize, int snum, int gnum,
w = pheader->mdl.skinwidth;
h = pheader->mdl.skinheight;
tskin = malloc (2 * skinsize);
memcpy (tskin, skin, skinsize);
memcpy (tskin, skinpix, skinsize);
Mod_FloodFillSkin (tskin, w, h);
tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin + skinsize};

View file

@ -40,10 +40,12 @@ Mod_CalcFullbright (const byte *in, byte *out, int pixels)
while (pixels-- > 0) {
byte pix = *in++;
byte mask = (pix >= 256 - 32) - 1;
fb |= mask + 1;
// mask is 0 for fullbright, otherwise 0xff
*out++ = pix | mask;
if (pix >= 256 - 32) {
fb = 1;
*out++ = pix;
} else {
*out++ = 0;
}
}
return fb;
}
@ -53,8 +55,10 @@ Mod_ClearFullbright (const byte *in, byte *out, int pixels)
{
while (pixels-- > 0) {
byte pix = *in++;
byte mask = ~((pix >= 256 - 32) - 1);
// mask is 0xff for fullbright, otherwise 0
*out++ = pix | mask;
if (pix >= 256 - 32) {
*out++ = 0;
} else {
*out++ = pix;
}
}
}

View file

@ -254,12 +254,12 @@ Skin_CalcTopColors (const byte *in, byte *out, int pixels)
while (pixels-- > 0) {
byte pix = *in++;
byte a = (pix < TOP_RANGE) - 1;
byte b = (pix > TOP_RANGE + 15) - 1;
byte mask = ~(a & b);
tc |= mask;
// mask is 0 for top color otherwise 0xff
*out++ = (pix - TOP_RANGE) | mask;
if (pix >= TOP_RANGE && pix < TOP_RANGE + 16) {
tc = 1;
*out++ = pix - TOP_RANGE;
} else {
*out++ = 0;
}
}
return tc;
}
@ -271,12 +271,12 @@ Skin_CalcBottomColors (const byte *in, byte *out, int pixels)
while (pixels-- > 0) {
byte pix = *in++;
byte a = (pix < BOTTOM_RANGE) - 1;
byte b = (pix > BOTTOM_RANGE + 15) - 1;
byte mask = ~(a & b);
bc |= mask;
// mask is 0 for bottom color otherwise 0xff
*out++ = (pix - BOTTOM_RANGE) | mask;
if (pix >= BOTTOM_RANGE && pix < BOTTOM_RANGE + 16) {
bc = 1;
*out++ = pix - BOTTOM_RANGE;
} else {
*out++ = 0;
}
}
return bc;
}
@ -286,11 +286,11 @@ Skin_ClearTopColors (const byte *in, byte *out, int pixels)
{
while (pixels-- > 0) {
byte pix = *in++;
byte a = (pix < TOP_RANGE) - 1;
byte b = (pix > TOP_RANGE + 15) - 1;
byte mask = (a & b);
// mask is 0xff for top color otherwise 0
*out++ = (pix - TOP_RANGE) | mask;
if (pix >= TOP_RANGE && pix < TOP_RANGE + 16) {
*out++ = 0;
} else {
*out++ = pix;
}
}
}
@ -299,10 +299,10 @@ Skin_ClearBottomColors (const byte *in, byte *out, int pixels)
{
while (pixels-- > 0) {
byte pix = *in++;
byte a = (pix < BOTTOM_RANGE) - 1;
byte b = (pix > BOTTOM_RANGE + 15) - 1;
byte mask = (a & b);
// mask is 0xff for bottom color otherwise 0
*out++ = (pix - BOTTOM_RANGE) | mask;
if (pix >= BOTTOM_RANGE && pix < BOTTOM_RANGE + 16) {
*out++ = 0;
} else {
*out++ = pix;
}
}
}

View file

@ -119,6 +119,85 @@ Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette,
}
}
static void
blit_mips (int mips, VkImage image, tex_t *tex,
qfv_devfuncs_t *dfunc, VkCommandBuffer cmd)
{
qfv_pipelinestagepair_t pre_stages = {
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
};
qfv_pipelinestagepair_t post_stages = {
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
};
qfv_pipelinestagepair_t final_stages = {
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
};
VkImageMemoryBarrier pre_barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
image,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
};
VkImageMemoryBarrier post_barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
image,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
};
VkImageMemoryBarrier final_barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
image,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
};
VkImageBlit blit = {
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
{{0, 0, 0}, {tex->width, tex->height, 1}},
{VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, 1},
{{0, 0, 0}, {max (tex->width >> 1, 1), max (tex->height >> 1, 1), 1}},
};
while (--mips > 0) {
dfunc->vkCmdPipelineBarrier (cmd, pre_stages.src, pre_stages.dst, 0,
0, 0, 0, 0,
1, &pre_barrier);
dfunc->vkCmdBlitImage (cmd,
image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit, VK_FILTER_LINEAR);
dfunc->vkCmdPipelineBarrier (cmd, post_stages.src, post_stages.dst, 0,
0, 0, 0, 0,
1, &post_barrier);
blit.srcSubresource.mipLevel++;
blit.srcOffsets[1].x = blit.dstOffsets[1].x;
blit.srcOffsets[1].y = blit.dstOffsets[1].y;
blit.dstSubresource.mipLevel++;
blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1);
blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1);
pre_barrier.subresourceRange.baseMipLevel++;
post_barrier.subresourceRange.baseMipLevel++;
final_barrier.subresourceRange.baseMipLevel++;
}
dfunc->vkCmdPipelineBarrier (cmd, final_stages.src, final_stages.dst, 0,
0, 0, 0, 0,
1, &final_barrier);
}
qfv_tex_t *
Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip)
{
@ -216,16 +295,6 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip)
qtex->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &copy);
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
stages.src = VK_PIPELINE_STAGE_TRANSFER_BIT;
stages.dst = VK_PIPELINE_STAGE_TRANSFER_BIT;
VkImageBlit blit = {
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
{{0, 0, 0}, {tex->width, tex->height, 1}},
{VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, 1},
{{0, 0, 0}, {max (tex->width >> 1, 1), max (tex->height >> 1, 1), 1}},
};
if (mip == 1) {
stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly];
barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
@ -233,40 +302,8 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip)
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst,
0, 0, 0, 0, 0,
1, &barrier);
}
while (--mip > 0) {
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
stages.dst = VK_PIPELINE_STAGE_TRANSFER_BIT;
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0,
0, 0, 0, 0,
1, &barrier);
dfunc->vkCmdBlitImage (packet->cmd,
qtex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
qtex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit, VK_FILTER_LINEAR);
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
stages.dst = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0,
0, 0, 0, 0,
1, &barrier);
blit.srcSubresource.mipLevel++;
blit.srcOffsets[1].x = blit.dstOffsets[1].x;
blit.srcOffsets[1].y = blit.dstOffsets[1].y;
blit.dstSubresource.mipLevel++;
blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1);
blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1);
barrier.subresourceRange.baseMipLevel++;
} else {
blit_mips (mip, qtex->image, tex, dfunc, packet->cmd);
}
QFV_PacketSubmit (packet);
return qtex;