From 668f7f2cd2909d5f9601124c880fd8e2fad5a88b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Nov 2022 11:47:28 +0900 Subject: [PATCH] [vulkan] Use palette lookups for top/bottom colors As the RGB curves for many of the color rows are not linearly related, my idea of scaling the brightest color in the row just didn't work. Using a masked palette lookup works much better as it allows any curves. Also, because the palette is uploaded as a grid and the coordinates are calculated on the CPU, the system is extendable beyond 8-bit palettes. This isn't quite complete as the top and bottom colors are still in separate layers but their indices and masks can fit in just one, but this requires reworking the texture setup (for another commit). --- include/QF/Vulkan/qf_alias.h | 3 +-- include/QF/Vulkan/qf_palette.h | 2 ++ libs/models/alias/vulkan_model_alias.c | 25 ++++++++++++++++--- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- .../renderer/vulkan/shader/alias_gbuf.frag | 15 +++++++---- libs/video/renderer/vulkan/vulkan_alias.c | 21 +++++++--------- libs/video/renderer/vulkan/vulkan_palette.c | 10 ++++++++ 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index b5fad64e0..5c64d00b8 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -58,8 +58,7 @@ typedef struct qfv_alias_skin_s { VkDeviceMemory memory; VkImage image; VkImageView view; - byte colora[4]; - byte colorb[4]; + byte colors[4]; VkDescriptorSet descriptor; } qfv_alias_skin_t; diff --git a/include/QF/Vulkan/qf_palette.h b/include/QF/Vulkan/qf_palette.h index a6cd01387..c1c1a4b33 100644 --- a/include/QF/Vulkan/qf_palette.h +++ b/include/QF/Vulkan/qf_palette.h @@ -38,6 +38,7 @@ typedef struct palettectx_s { struct qfv_tex_s *palette; VkSampler sampler; + VkDescriptorSet descriptor; } palettectx_t; struct vulkan_ctx_s; @@ -45,5 +46,6 @@ struct vulkan_ctx_s; void Vulkan_Palette_Update (struct vulkan_ctx_s *ctx, const byte *palette); void Vulkan_Palette_Init (struct vulkan_ctx_s *ctx, const byte *palette); void Vulkan_Palette_Shutdown (struct vulkan_ctx_s *ctx); +VkDescriptorSet Vulkan_Palette_Descriptor (struct vulkan_ctx_s *ctx) __attribute__((pure)); #endif//__QF_Vulkan_qf_palette_h diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 89cadd84f..44e4e43cf 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -125,8 +125,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, int w, h; skin = Hunk_Alloc (0, sizeof (qfv_alias_skin_t)); - QuatCopy (vid.palette32 + (TOP_RANGE + 15) * 4, skin->colora); - QuatCopy (vid.palette32 + (BOTTOM_RANGE + 15) * 4, skin->colorb); + QuatSet (TOP_RANGE + 7, BOTTOM_RANGE + 7, 0, 0, skin->colors); skindesc->skin = (byte *) skin - (byte *) header; //FIXME move all skins into arrays(?) w = header->mdl.skinwidth; @@ -175,13 +174,31 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, skinsize); Mod_ClearFullbright (tskin, tskin, skinsize); + static byte map_palette[] = { + 0x08, 0x00, 0x00, + 0x18, 0xff, 0x00, + 0x28, 0xff, 0x00, + 0x38, 0xff, 0x00, + 0x48, 0xff, 0x00, + 0x58, 0xff, 0x00, + 0x68, 0xff, 0x00, + 0x78, 0xff, 0x00, + 0x88, 0xff, 0x00, + 0x98, 0xff, 0x00, + 0xa8, 0xff, 0x00, + 0xb8, 0xff, 0x00, + 0xc8, 0xff, 0x00, + 0xd8, 0xff, 0x00, + 0xe8, 0xff, 0x00, + 0xf8, 0xff, 0x00, + }; Skin_CalcTopColors (tskin + skinsize, tskin, skinsize); - Vulkan_ExpandPalette (cola_data, tskin + skinsize, vid.palette, 1, + Vulkan_ExpandPalette (cola_data, tskin + skinsize, map_palette, 1, skinsize); Skin_ClearTopColors (tskin, tskin, skinsize); Skin_CalcBottomColors (tskin + skinsize, tskin, skinsize); - Vulkan_ExpandPalette (colb_data, tskin + skinsize, vid.palette, 1, + Vulkan_ExpandPalette (colb_data, tskin + skinsize, map_palette, 1, skinsize); Skin_ClearBottomColors (tskin, tskin, skinsize); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index aaa8f3f8b..43e3bf646 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -426,7 +426,7 @@ ); }; alias_layout = { - setLayouts = (matrix_set, texture_set); + setLayouts = (matrix_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index de554181d..c56f483e2 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -1,11 +1,11 @@ #version 450 -layout (set = 1, binding = 0) uniform sampler2DArray Skin; +layout (set = 1, binding = 0) uniform sampler2D Palette; +layout (set = 2, binding = 0) uniform sampler2DArray Skin; layout (push_constant) uniform PushConstants { layout (offset = 68) - uint colorA; - uint colorB; + uint colors; vec4 base_color; vec4 fog; }; @@ -26,9 +26,14 @@ main (void) vec4 e; int i; vec3 light = vec3 (0); + vec4 rows = unpackUnorm4x8(colors); + vec2 cols = vec2 (texture (Skin, vec3 (st, 1)).r, + texture (Skin, vec3 (st, 2)).r); + vec2 mask = vec2 (texture (Skin, vec3 (st, 1)).g, + texture (Skin, vec3 (st, 2)).g); c = texture (Skin, vec3 (st, 0)) * base_color; - c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA) * 2; - c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB) * 2; + c += texture (Palette, vec2 (cols.x, rows.x)) * mask.x; + c += texture (Palette, vec2 (cols.y, rows.y)) * mask.y; e = texture (Skin, vec3 (st, 3)); frag_color = c; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 0a5a7ce44..8d3630be7 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -42,6 +42,7 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" @@ -54,8 +55,7 @@ typedef struct { mat4f_t mat; float blend; - byte colorA[4]; - byte colorB[4]; + byte colors[4]; vec4f_t base_color; vec4f_t fog; } alias_push_constants_t; @@ -108,7 +108,7 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, skin->descriptor, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 1, 1, sets, 0, 0); + actx->layout, 2, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); @@ -144,11 +144,8 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) field_offset (alias_push_constants_t, blend), sizeof (float), &constants.blend }, { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (alias_push_constants_t, colorA), - sizeof (constants.colorA), constants.colorA }, - { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (alias_push_constants_t, colorB), - sizeof (constants.colorB), constants.colorB }, + field_offset (alias_push_constants_t, colors), + sizeof (constants.colors), constants.colors }, { VK_SHADER_STAGE_FRAGMENT_BIT, field_offset (alias_push_constants_t, base_color), sizeof (constants.base_color), &constants.base_color }, @@ -165,8 +162,7 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } QuatCopy (renderer->colormod, constants.base_color); - QuatCopy (skin->colora, constants.colorA); - QuatCopy (skin->colorb, constants.colorB); + QuatCopy (skin->colors, constants.colors); QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_aliasDepth], @@ -174,7 +170,7 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) 0, 2, push_constants, hdr, rFrame, ent); emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], animation->pose1, animation->pose2, - skin, 6, push_constants, hdr, rFrame, ent); + skin, 5, push_constants, hdr, rFrame, ent); } static void @@ -210,9 +206,10 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + Vulkan_Palette_Descriptor (ctx), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 0, 1, sets, 0, 0); + actx->layout, 0, 2, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); diff --git a/libs/video/renderer/vulkan/vulkan_palette.c b/libs/video/renderer/vulkan/vulkan_palette.c index ac1c17b59..0b7ce791a 100644 --- a/libs/video/renderer/vulkan/vulkan_palette.c +++ b/libs/video/renderer/vulkan/vulkan_palette.c @@ -78,6 +78,9 @@ Vulkan_Palette_Init (vulkan_ctx_t *ctx, const byte *palette) .data = (byte *) palette, }; pctx->palette = Vulkan_LoadTex (ctx, &tex, 0, "palette"); + pctx->descriptor = Vulkan_CreateCombinedImageSampler (ctx, + pctx->palette->view, + pctx->sampler); qfvPopDebug (ctx); } @@ -94,3 +97,10 @@ Vulkan_Palette_Shutdown (vulkan_ctx_t *ctx) qfvPopDebug (ctx); } + +VkDescriptorSet +Vulkan_Palette_Descriptor (struct vulkan_ctx_s *ctx) +{ + __auto_type pctx = ctx->palette_context; + return pctx->descriptor; +}