[vulkan] Implement fitted pic rendering

This makes use of slice rendering to achieve the effective scaling, but
the slice data is created only when needed so pics that never use slices
don't waste 16 vertices.
This commit is contained in:
Bill Currie 2023-01-19 17:18:51 +09:00
parent 7785eebe4c
commit e332164329

View file

@ -82,6 +82,7 @@ static QFV_Subpass subpass_map[] = {
typedef struct pic_data_s { typedef struct pic_data_s {
uint32_t vert_index; uint32_t vert_index;
uint32_t slice_index;
uint32_t descid; uint32_t descid;
subpic_t *subpic; subpic_t *subpic;
} picdata_t; } picdata_t;
@ -189,7 +190,6 @@ typedef struct drawctx_s {
qpic_t *conchars; qpic_t *conchars;
qpic_t *conback; qpic_t *conback;
qpic_t *white_pic; qpic_t *white_pic;
int white_pic_ind;
qpic_t *backtile_pic; qpic_t *backtile_pic;
// use two separate cmem blocks for pics and strings (cachepic names) // use two separate cmem blocks for pics and strings (cachepic names)
// to ensure the names are never in the same cacheline as a pic since the // to ensure the names are never in the same cacheline as a pic since the
@ -245,7 +245,7 @@ get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view,
} }
} }
if (pool->in_use >= MAX_DESCIPTORS) { if (pool->in_use >= MAX_DESCIPTORS) {
Sys_Error ("get_dyn_descriptor: out of dynamic desciptors"); Sys_Error ("get_dyn_descriptor: out of dynamic descriptors");
} }
int descid = pool->in_use++; int descid = pool->in_use++;
pool->users[descid] = id; pool->users[descid] = id;
@ -472,8 +472,8 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic,
{ {
__auto_type pd = (picdata_t *) pic->data; __auto_type pd = (picdata_t *) pic->data;
int x = rect[0] + pd->subpic->rect->x; int x = rect[0];
int y = rect[1] + pd->subpic->rect->y; int y = rect[1];
int w = rect[2]; int w = rect[2];
int h = rect[3]; int h = rect[3];
int l = border[0]; int l = border[0];
@ -481,6 +481,14 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic,
int r = w - border[2]; int r = w - border[2];
int b = h - border[3]; int b = h - border[3];
float sx = 1.0 / pic->width;
float sy = 1.0 / pic->height;
if (pd->subpic) {
x += pd->subpic->rect->x;
y += pd->subpic->rect->y;
sx = sy = pd->subpic->size;
}
vec4f_t p[16] = { vec4f_t p[16] = {
{ 0, 0, 0, 0 }, { 0, t, 0, t }, { l, 0, l, 0 }, { l, t, l, t }, { 0, 0, 0, 0 }, { 0, t, 0, t }, { l, 0, l, 0 }, { l, t, l, t },
{ r, 0, r, 0 }, { r, t, r, t }, { w, 0, w, 0 }, { w, t, w, t }, { r, 0, r, 0 }, { r, t, r, t }, { w, 0, w, 0 }, { w, t, w, t },
@ -488,8 +496,7 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic,
{ r, b, r, b }, { r, h, r, h }, { w, b, w, b }, { w, h, w, h }, { r, b, r, b }, { r, h, r, h }, { w, b, w, b }, { w, h, w, h },
}; };
float s = pd->subpic->size; vec4f_t size = { 1, 1, sx, sy };
vec4f_t size = { 1, 1, s, s };
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_SLICE); quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_SLICE);
for (int i = 0; i < VERTS_PER_SLICE; i++) { for (int i = 0; i < VERTS_PER_SLICE; i++) {
@ -506,6 +513,15 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic,
return ind; return ind;
} }
static uint32_t
make_static_slice (vec4i_t rect, vec4i_t border, qpic_t *pic, vulkan_ctx_t *ctx)
{
drawctx_t *dctx = ctx->draw_context;
VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer;
return create_slice (rect, border, pic, &dctx->svertex_index, buffer, ctx);
}
static uint32_t static uint32_t
create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index, create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index,
VkBuffer buffer, vulkan_ctx_t *ctx) VkBuffer buffer, vulkan_ctx_t *ctx)
@ -540,7 +556,7 @@ create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index,
return ind; return ind;
} }
static int static uint32_t
make_static_quad (int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) make_static_quad (int w, int h, qpic_t *pic, vulkan_ctx_t *ctx)
{ {
drawctx_t *dctx = ctx->draw_context; drawctx_t *dctx = ctx->draw_context;
@ -573,6 +589,7 @@ pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx)
__auto_type pd = (picdata_t *) pic->data; __auto_type pd = (picdata_t *) pic->data;
pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h); pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h);
pd->vert_index = make_static_quad (w, h, pic, ctx); pd->vert_index = make_static_quad (w, h, pic, ctx);
pd->slice_index = ~0;
pd->descid = CORE_DESC; pd->descid = CORE_DESC;
picdata = QFV_SubpicBatch (pd->subpic, dctx->stage); picdata = QFV_SubpicBatch (pd->subpic, dctx->stage);
@ -718,6 +735,7 @@ load_lmp (const char *path, vulkan_ctx_t *ctx)
__auto_type pd = (picdata_t *) pic->data; __auto_type pd = (picdata_t *) pic->data;
pd->subpic = 0; pd->subpic = 0;
pd->vert_index = make_static_quad (p->width, p->height, pic, ctx); pd->vert_index = make_static_quad (p->width, p->height, pic, ctx);
pd->slice_index = ~0;
pd->descid = fontid; pd->descid = fontid;
free (p); free (p);
@ -831,13 +849,12 @@ load_white_pic (vulkan_ctx_t *ctx)
{ {
drawctx_t *dctx = ctx->draw_context; drawctx_t *dctx = ctx->draw_context;
byte white_block = 0xfe; byte white_block = 0xfe;
VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer;
dctx->white_pic = pic_data ("white", 1, 1, &white_block, ctx); dctx->white_pic = pic_data ("white", 1, 1, &white_block, ctx);
dctx->white_pic_ind = create_slice ((vec4i_t) {0, 0, 1, 1}, __auto_type pd = (picdata_t *) dctx->white_pic->data;
pd->slice_index = make_static_slice ((vec4i_t) {0, 0, 1, 1},
(vec4i_t) {0, 0, 0, 0}, (vec4i_t) {0, 0, 0, 0},
dctx->white_pic, dctx->white_pic, ctx);
&dctx->svertex_index, buffer, ctx);
} }
void void
@ -1231,9 +1248,20 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx)
} }
void void
Vulkan_Draw_FitPic (int x, int y, int widht, int height, qpic_t *pic, Vulkan_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic,
vulkan_ctx_t *ctx) vulkan_ctx_t *ctx)
{ {
drawctx_t *dctx = ctx->draw_context;
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
__auto_type pd = (picdata_t *) pic->data;
if (pd->slice_index == ~0u) {
vec4i_t rect = (vec4i_t) {0, 0, pic->width, pic->height};
vec4i_t border = (vec4i_t) {0, 0, 0, 0};
pd->slice_index = make_static_slice (rect, border, pic, ctx);
}
static byte color[4] = { 255, 255, 255, 255};
draw_slice (x, y, width - pic->width, height - pic->height,
pd->descid, pd->slice_index, color, frame);
} }
void void
@ -1329,8 +1357,8 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx)
drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
byte color[4] = {VectorExpand (vid.palette + c * 3), 255 }; byte color[4] = {VectorExpand (vid.palette + c * 3), 255 };
draw_slice (x, y, w - 1, h - 1, __auto_type pd = (picdata_t *) dctx->white_pic->data;
CORE_DESC, dctx->white_pic_ind, color, frame); draw_slice (x, y, w - 1, h - 1, pd->descid, pd->slice_index, color, frame);
} }
void void
@ -1377,8 +1405,9 @@ draw_blendscreen (const byte *color, vulkan_ctx_t *ctx)
drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
float s = 1.0 / ctx->twod_scale; float s = 1.0 / ctx->twod_scale;
__auto_type pd = (picdata_t *) dctx->white_pic->data;
draw_slice (0, 0, vid.width * s - 1, vid.height * s - 1, draw_slice (0, 0, vid.width * s - 1, vid.height * s - 1,
CORE_DESC, dctx->white_pic_ind, color, frame); pd->descid, pd->slice_index, color, frame);
} }
void void