[vulkan] Support clipping rectangles via scissor

Seems to work well. The other renderers have stubs because I don't feel
like implementing clipping for them. The gl and glsl wouldn't be too
difficult (need to handle the draw queues), but sw needs a fair bit of
work and I'm not sure it's worth the effort.
This commit is contained in:
Bill Currie 2023-12-22 18:17:09 +09:00
parent f3eebae9bc
commit 650ea052ea
13 changed files with 139 additions and 17 deletions

View file

@ -61,6 +61,8 @@ void gl_Draw_SubPic(int x, int y, struct qpic_s *pic,
int srcx, int srcy, int width, int height);
int gl_Draw_AddFont (struct font_s *font);
void gl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c);
void gl_Draw_SetClip (int x, int y, int w, int h);
void gl_Draw_ResetClip (void);
void GL_Set2D (void);
void GL_Set2DScaled (void);

View file

@ -62,6 +62,8 @@ void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic,
int srcx, int srcy, int width, int height);
int glsl_Draw_AddFont (struct font_s *font);
void glsl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c);
void glsl_Draw_SetClip (int x, int y, int w, int h);
void glsl_Draw_ResetClip (void);
void GLSL_Set2D (void);
void GLSL_Set2DScaled (void);

View file

@ -82,6 +82,8 @@ void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic,
int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx);
void Vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_SetClip (int x, int y, int w, int h, struct vulkan_ctx_s *ctx);
void Vulkan_Draw_ResetClip (struct vulkan_ctx_s *ctx);
void Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height,
struct vulkan_ctx_s *ctx);

View file

@ -279,6 +279,8 @@ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int h
struct font_s;
int Draw_AddFont (struct font_s *font);
void Draw_Glyph (int x, int y, int fontid, int glyphid, int c);
void Draw_SetClip (int x, int y, int w, int h);
void Draw_ResetClip (void);
///@}

View file

@ -116,6 +116,8 @@ typedef struct vid_render_funcs_s {
void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
int (*Draw_AddFont) (struct font_s *font);
void (*Draw_Glyph) (int x, int y, int fontid, int glyphid, int c);
void (*Draw_SetClip) (int x, int y, int w, int h);
void (*Draw_ResetClip) (void);
struct psystem_s *(*ParticleSystem) (void);
struct psystem_s *(*TrailSystem) (void);

View file

@ -1131,3 +1131,13 @@ gl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
qfglEnd ();
qfglColor4ubv (color_white);
}
void
gl_Draw_SetClip (int x, int y, int w, int h)
{
}
void
gl_Draw_ResetClip (void)
{
}

View file

@ -1111,3 +1111,13 @@ glsl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
QuatCopy (color, verts[4].color);
QuatCopy (color, verts[5].color);
}
void
glsl_Draw_SetClip (int x, int y, int w, int h)
{
}
void
glsl_Draw_ResetClip (void)
{
}

View file

@ -1096,3 +1096,13 @@ Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
dst += d_rowbytes;
}
}
void
Draw_SetClip (int x, int y, int w, int h)
{
}
void
Draw_ResetClip (void)
{
}

View file

@ -529,6 +529,8 @@ vid_render_funcs_t gl_vid_render_funcs = {
.Draw_SubPic = gl_Draw_SubPic,
.Draw_AddFont = gl_Draw_AddFont,
.Draw_Glyph = gl_Draw_Glyph,
.Draw_SetClip = gl_Draw_SetClip,
.Draw_ResetClip = gl_Draw_ResetClip,
.ParticleSystem = gl_ParticleSystem,
.R_Init = gl_R_Init,

View file

@ -475,6 +475,8 @@ vid_render_funcs_t glsl_vid_render_funcs = {
.Draw_SubPic = glsl_Draw_SubPic,
.Draw_AddFont = glsl_Draw_AddFont,
.Draw_Glyph = glsl_Draw_Glyph,
.Draw_SetClip = glsl_Draw_SetClip,
.Draw_ResetClip = glsl_Draw_ResetClip,
.ParticleSystem = glsl_ParticleSystem,
.TrailSystem = glsl_TrailSystem,

View file

@ -485,6 +485,8 @@ vid_render_funcs_t sw_vid_render_funcs = {
.Draw_SubPic = Draw_SubPic,
.Draw_AddFont = Draw_AddFont,
.Draw_Glyph = Draw_Glyph,
.Draw_SetClip = Draw_SetClip,
.Draw_ResetClip = Draw_ResetClip,
.ParticleSystem = sw_ParticleSystem,
.R_Init = sw_R_Init,

View file

@ -327,6 +327,18 @@ vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
Vulkan_Draw_Glyph (x, y, fontid, glyphid, c, vulkan_ctx);
}
static void
vulkan_Draw_SetClip (int x, int y, int w, int h)
{
Vulkan_Draw_SetClip (x, y, w, h, vulkan_ctx);
}
static void
vulkan_Draw_ResetClip (void)
{
Vulkan_Draw_ResetClip (vulkan_ctx);
}
static void
vulkan_set_2d (int scaled)
{
@ -612,6 +624,8 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
.Draw_SubPic = vulkan_Draw_SubPic,
.Draw_AddFont = vulkan_Draw_AddFont,
.Draw_Glyph = vulkan_Draw_Glyph,
.Draw_SetClip = vulkan_Draw_SetClip,
.Draw_ResetClip = vulkan_Draw_ResetClip,
.ParticleSystem = vulkan_ParticleSystem,
.R_Init = vulkan_R_Init,

View file

@ -87,6 +87,15 @@ typedef struct descbatch_s {
typedef struct descbatchset_s
DARRAY_TYPE (descbatch_t) descbatchset_t;
typedef struct drawclip_s {
uint32_t start;
uint32_t count; // number of batches in quad_batch
VkRect2D clip;
} drawclip_t;
typedef struct drawclipset_s
DARRAY_TYPE (drawclip_t) drawclipset_t;
typedef struct {
float xy[2];
byte color[4];
@ -167,6 +176,7 @@ typedef struct drawframe_s {
uint32_t dvertex_index;
uint32_t dvertex_max;
descbatchset_t quad_batch;
drawclipset_t clip_range;
quadqueue_t quad_insts;
linequeue_t line_verts;
descpool_t dyn_descs;
@ -428,6 +438,7 @@ create_buffers (vulkan_ctx_t *ctx)
};
DARRAY_INIT (&frame->quad_batch, 16);
DARRAY_INIT (&frame->clip_range, 16);
frame->quad_insts = (quadqueue_t) {
.quads = (quadinst_t *) ((byte *)data + frame->instance_offset),
.max_count = MAX_INSTANCES,
@ -908,22 +919,32 @@ draw_quads (qfv_taskctx_t *taskctx)
dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32);
uint32_t inst_start = 0;
for (size_t i = 0; i < dframe->quad_batch.size; i++) {
int fontid = dframe->quad_batch.a[i].descid;
uint32_t inst_count = dframe->quad_batch.a[i].count;
uint32_t ind_count = inst_count >> 24;
inst_count &= 0xffffff;
VkDescriptorSet set[2] = {
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
fontid < 0 ? dframe->dyn_descs.sets[~fontid]
: dctx->fonts.a[fontid].set,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, 2, set, 0, 0);
for (size_t i = 0; i < dframe->clip_range.size; i++) {
auto cr = &dframe->clip_range.a[i];
dfunc->vkCmdSetScissor (cmd, 0, 1, &cr->clip);
for (uint32_t j = 0; j < cr->count; j++) {
int fontid = dframe->quad_batch.a[cr->start + j].descid;
uint32_t inst_count = dframe->quad_batch.a[cr->start + j].count;
uint32_t ind_count = inst_count >> 24;
inst_count &= 0xffffff;
VkDescriptorSet set[2] = {
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
fontid < 0 ? dframe->dyn_descs.sets[~fontid]
: dctx->fonts.a[fontid].set,
};
dfunc->vkCmdBindDescriptorSets (cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, 2, set, 0, 0);
dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0, inst_start);
inst_start += inst_count;
dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0,
inst_start);
inst_start += inst_count;
}
}
VkRect2D scissor = {
.extent = { .width = vid.width, .height = vid.height },
};
dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor);
DARRAY_RESIZE (&dframe->quad_batch, 0);
}
@ -973,6 +994,9 @@ slice_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
return;
}
auto cr = &dframe->clip_range.a[dframe->clip_range.size - 1];
cr->count = dframe->quad_batch.size - cr->start;
qftVkScopedZone (taskctx->frame->qftVkCtx, taskctx->cmd, "slice_draw");
VkDeviceMemory memory = dctx->draw_resource[1].memory;
size_t atom = device->physDev->p.properties.limits.nonCoherentAtomSize;
@ -1035,6 +1059,13 @@ draw_scr_funcs (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
auto taskctx = (qfv_taskctx_t *) ectx;
auto ctx = taskctx->ctx;
auto dctx = ctx->draw_context;
auto dframe = &dctx->frames.a[ctx->curFrame];
DARRAY_RESIZE (&dframe->clip_range, 0);
DARRAY_APPEND (&dframe->clip_range, ((drawclip_t) {
.clip.offset = { .x = 0, .y = 0 },
.clip.extent = { .width = vid.width, .height = vid.height },
}));
auto scr_funcs = dctx->scr_funcs;
if (!scr_funcs) {
@ -1047,9 +1078,8 @@ draw_scr_funcs (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
dctx->scr_funcs = 0;
flush_vertqueue (&dctx->slice_vert_queue, ctx);
auto frame = &dctx->frames.a[ctx->curFrame];
flush_vertqueue (&frame->dyn_vert_queue, ctx);
frame->dyn_vert_queue.base = 0;
flush_vertqueue (&dframe->dyn_vert_queue, ctx);
dframe->dyn_vert_queue.base = 0;
}
static exprfunc_t flush_draw_func[] = {
@ -1759,6 +1789,38 @@ Vulkan_Draw_Glyph (int x, int y, int fontid, int glyph, int c,
draw_quad (x, y, fontid, glyph * 4, color, frame);
}
void
Vulkan_Draw_SetClip (int x, int y, int w, int h, vulkan_ctx_t *ctx)
{
auto dctx = ctx->draw_context;
auto dframe = &dctx->frames.a[ctx->curFrame];
if (x < 0) {
w += x;
x = 0;
}
if (y < 0) {
h += y;
y = 0;
}
auto cr = &dframe->clip_range.a[dframe->clip_range.size - 1];
if (x != cr->clip.offset.x || y != cr->clip.offset.y
|| (uint32_t) w != cr->clip.extent.width
|| (uint32_t) h != cr->clip.extent.height) {
cr->count = dframe->quad_batch.size - cr->start;
DARRAY_APPEND (&dframe->clip_range, ((drawclip_t) {
.start = dframe->quad_batch.size,
.clip.offset = { .x = x, .y = y },
.clip.extent = { .width = w, .height = h },
}));
}
}
void
Vulkan_Draw_ResetClip (vulkan_ctx_t *ctx)
{
}
void
Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height,
vulkan_ctx_t *ctx)