2019-07-06 05:42:53 +00:00
|
|
|
/*
|
|
|
|
vulkan_draw.c
|
|
|
|
|
|
|
|
2D drawing support for Vulkan
|
|
|
|
|
2021-01-10 06:52:27 +00:00
|
|
|
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
2019-07-06 05:42:53 +00:00
|
|
|
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
2021-01-10 06:52:27 +00:00
|
|
|
Date: 2021/1/10
|
2019-07-06 05:42:53 +00:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
|
|
|
|
2021-02-05 07:25:08 +00:00
|
|
|
#include "QF/cmem.h"
|
2019-07-06 05:42:53 +00:00
|
|
|
#include "QF/cvar.h"
|
|
|
|
#include "QF/draw.h"
|
|
|
|
#include "QF/dstring.h"
|
|
|
|
#include "QF/hash.h"
|
|
|
|
#include "QF/quakefs.h"
|
2021-01-13 01:43:23 +00:00
|
|
|
#include "QF/render.h"
|
2019-07-06 05:42:53 +00:00
|
|
|
#include "QF/sys.h"
|
2021-04-18 11:40:43 +00:00
|
|
|
#include "QF/va.h"
|
2019-07-06 05:42:53 +00:00
|
|
|
#include "QF/vid.h"
|
|
|
|
|
2021-01-10 06:52:27 +00:00
|
|
|
#include "compat.h"
|
2019-07-06 05:42:53 +00:00
|
|
|
#include "QF/Vulkan/qf_draw.h"
|
2021-12-08 06:28:21 +00:00
|
|
|
#include "QF/Vulkan/qf_matrices.h"
|
2022-05-30 03:10:00 +00:00
|
|
|
#include "QF/Vulkan/qf_renderpass.h"
|
2022-08-31 10:23:30 +00:00
|
|
|
#include "QF/Vulkan/qf_texture.h"
|
2019-07-06 05:42:53 +00:00
|
|
|
#include "QF/Vulkan/qf_vid.h"
|
2021-01-10 16:27:40 +00:00
|
|
|
#include "QF/Vulkan/barrier.h"
|
2021-01-12 02:27:41 +00:00
|
|
|
#include "QF/Vulkan/buffer.h"
|
|
|
|
#include "QF/Vulkan/command.h"
|
2021-04-18 11:40:43 +00:00
|
|
|
#include "QF/Vulkan/debug.h"
|
2021-01-10 06:52:27 +00:00
|
|
|
#include "QF/Vulkan/descriptor.h"
|
|
|
|
#include "QF/Vulkan/device.h"
|
|
|
|
#include "QF/Vulkan/image.h"
|
2021-12-02 13:48:50 +00:00
|
|
|
#include "QF/Vulkan/instance.h"
|
2022-10-03 01:29:49 +00:00
|
|
|
#include "QF/Vulkan/resource.h"
|
2021-01-21 07:39:11 +00:00
|
|
|
#include "QF/Vulkan/scrap.h"
|
2021-01-10 16:27:40 +00:00
|
|
|
#include "QF/Vulkan/staging.h"
|
2022-12-07 06:11:08 +00:00
|
|
|
#include "QF/ui/font.h"
|
2021-07-10 09:04:34 +00:00
|
|
|
#include "QF/ui/view.h"
|
2019-07-06 05:42:53 +00:00
|
|
|
|
|
|
|
#include "r_internal.h"
|
2021-01-10 06:52:27 +00:00
|
|
|
#include "vid_vulkan.h"
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
static const char *draw_pass_names[] = {
|
2022-11-20 17:29:03 +00:00
|
|
|
"2d",
|
|
|
|
};
|
|
|
|
|
|
|
|
static QFV_Subpass subpass_map[] = {
|
2022-11-27 00:51:01 +00:00
|
|
|
[QFV_draw2d] = 0,
|
2022-11-20 17:29:03 +00:00
|
|
|
};
|
|
|
|
|
2023-01-11 04:34:27 +00:00
|
|
|
typedef struct pic_data_s {
|
|
|
|
uint32_t vert_index;
|
|
|
|
subpic_t *subpic;
|
|
|
|
} picdata_t;
|
|
|
|
|
2022-10-07 07:53:13 +00:00
|
|
|
typedef struct descbatch_s {
|
|
|
|
int32_t descid; // texture or font descriptor id
|
|
|
|
uint32_t count; // number of objects in batch
|
|
|
|
} descbatch_t;
|
|
|
|
|
|
|
|
typedef struct descbatchset_s
|
|
|
|
DARRAY_TYPE (descbatch_t) descbatchset_t;
|
|
|
|
|
2021-01-12 02:27:41 +00:00
|
|
|
typedef struct {
|
|
|
|
float xy[2];
|
2021-01-12 04:51:41 +00:00
|
|
|
float st[2];
|
2023-01-11 02:34:32 +00:00
|
|
|
byte color[4];
|
|
|
|
} linevert_t;
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2022-11-18 00:44:01 +00:00
|
|
|
typedef struct {
|
|
|
|
uint32_t index;
|
|
|
|
byte color[4];
|
|
|
|
float position[2];
|
|
|
|
float offset[2];
|
2023-01-11 02:34:32 +00:00
|
|
|
} quadinst_t;
|
2022-11-18 00:44:01 +00:00
|
|
|
|
2022-10-03 01:29:49 +00:00
|
|
|
typedef struct {
|
|
|
|
float offset[2];
|
|
|
|
float uv[2];
|
2023-01-11 02:34:32 +00:00
|
|
|
} quadvert_t;
|
2021-01-13 15:44:34 +00:00
|
|
|
|
2022-09-09 08:06:33 +00:00
|
|
|
typedef struct vertqueue_s {
|
2023-01-11 02:34:32 +00:00
|
|
|
linevert_t *verts;
|
2022-09-09 08:06:33 +00:00
|
|
|
int count;
|
|
|
|
int size;
|
|
|
|
} vertqueue_t;
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
typedef struct quadqueue_s {
|
|
|
|
quadinst_t *quads;
|
2022-11-18 00:44:01 +00:00
|
|
|
int count;
|
|
|
|
int size;
|
2023-01-11 02:34:32 +00:00
|
|
|
} quadqueue_t;
|
2022-11-18 00:44:01 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
typedef struct cachepic_s {
|
|
|
|
char *name;
|
|
|
|
qpic_t *pic;
|
|
|
|
} cachepic_t;
|
2022-10-03 01:29:49 +00:00
|
|
|
|
2021-01-16 05:42:25 +00:00
|
|
|
typedef struct drawframe_s {
|
2023-01-11 02:34:32 +00:00
|
|
|
size_t instance_offset;
|
2022-05-28 09:14:26 +00:00
|
|
|
size_t line_offset;
|
2023-01-11 02:34:32 +00:00
|
|
|
VkBuffer instance_buffer;
|
2023-01-11 08:16:49 +00:00
|
|
|
VkBuffer dvert_buffer;
|
2023-01-11 02:34:32 +00:00
|
|
|
VkBufferView dvert_view;
|
2023-01-11 03:47:22 +00:00
|
|
|
VkDescriptorSet dyn_quad_set;
|
2023-01-11 02:34:32 +00:00
|
|
|
|
2023-01-11 08:16:49 +00:00
|
|
|
uint32_t dvertex_index;
|
|
|
|
uint32_t dvertex_max;
|
2022-10-07 07:53:13 +00:00
|
|
|
descbatchset_t quad_batch;
|
2023-01-11 02:34:32 +00:00
|
|
|
quadqueue_t quad_insts;
|
2022-09-09 08:06:33 +00:00
|
|
|
vertqueue_t line_verts;
|
2022-11-20 17:29:03 +00:00
|
|
|
qfv_cmdbufferset_t cmdSet;
|
2021-01-16 05:42:25 +00:00
|
|
|
} drawframe_t;
|
|
|
|
|
|
|
|
typedef struct drawframeset_s
|
|
|
|
DARRAY_TYPE (drawframe_t) drawframeset_t;
|
|
|
|
|
2022-10-03 01:29:49 +00:00
|
|
|
typedef struct drawfontres_s {
|
|
|
|
qfv_resource_t resource;
|
|
|
|
qfv_resobj_t glyph_data;
|
|
|
|
qfv_resobj_t glyph_bview;
|
|
|
|
qfv_resobj_t glyph_image;
|
|
|
|
qfv_resobj_t glyph_iview;
|
|
|
|
} drawfontres_t;
|
|
|
|
|
|
|
|
typedef struct drawfont_s {
|
|
|
|
VkDescriptorSet set;
|
|
|
|
drawfontres_t *resource;
|
|
|
|
} drawfont_t;
|
|
|
|
|
|
|
|
typedef struct drawfontset_s
|
|
|
|
DARRAY_TYPE (drawfont_t) drawfontset_t;
|
|
|
|
|
2021-01-16 05:42:25 +00:00
|
|
|
typedef struct drawctx_s {
|
2022-11-19 18:59:01 +00:00
|
|
|
VkSampler pic_sampler;
|
|
|
|
VkSampler glyph_sampler;
|
2021-01-16 05:42:25 +00:00
|
|
|
scrap_t *scrap;
|
|
|
|
qfv_stagebuf_t *stage;
|
2023-01-11 08:16:49 +00:00
|
|
|
int *crosshair_inds;
|
2021-12-18 04:07:56 +00:00
|
|
|
qpic_t *crosshair;
|
2023-01-11 02:34:32 +00:00
|
|
|
int *conchar_inds;
|
2021-01-16 05:42:25 +00:00
|
|
|
qpic_t *conchars;
|
|
|
|
qpic_t *conback;
|
|
|
|
qpic_t *white_pic;
|
2023-01-12 08:10:43 +00:00
|
|
|
int white_pic_ind;
|
2022-11-12 15:49:47 +00:00
|
|
|
qpic_t *backtile_pic;
|
2021-02-05 07:25:08 +00:00
|
|
|
// 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
|
|
|
|
// names are used only for lookup
|
|
|
|
memsuper_t *pic_memsuper;
|
|
|
|
memsuper_t *string_memsuper;
|
2021-01-16 05:42:25 +00:00
|
|
|
hashtab_t *pic_cache;
|
2022-10-03 01:29:49 +00:00
|
|
|
qfv_resource_t *draw_resource;
|
2023-01-11 02:34:32 +00:00
|
|
|
qfv_resobj_t *index_object;
|
2023-01-11 03:47:22 +00:00
|
|
|
qfv_resobj_t *svertex_objects;
|
2023-01-11 02:34:32 +00:00
|
|
|
qfv_resobj_t *instance_objects;
|
|
|
|
qfv_resobj_t *dvertex_objects;
|
|
|
|
uint32_t svertex_index;
|
|
|
|
uint32_t svertex_max;
|
2022-05-28 09:14:26 +00:00
|
|
|
VkPipeline quad_pipeline;
|
|
|
|
VkPipeline line_pipeline;
|
2023-01-11 02:34:32 +00:00
|
|
|
VkPipelineLayout lines_layout;
|
|
|
|
VkPipelineLayout quad_layout;
|
|
|
|
VkDescriptorSetLayout quad_data_set_layout;
|
|
|
|
VkDescriptorPool quad_pool;
|
2023-01-11 03:47:22 +00:00
|
|
|
VkDescriptorSet core_quad_set;
|
2021-01-16 05:42:25 +00:00
|
|
|
drawframeset_t frames;
|
2022-10-03 01:29:49 +00:00
|
|
|
drawfontset_t fonts;
|
2021-01-16 05:42:25 +00:00
|
|
|
} drawctx_t;
|
|
|
|
|
|
|
|
#define MAX_QUADS (32768)
|
2021-01-12 02:27:41 +00:00
|
|
|
#define VERTS_PER_QUAD (4)
|
2023-01-11 02:34:32 +00:00
|
|
|
#define BYTES_PER_QUAD (VERTS_PER_QUAD * sizeof (quadvert_t))
|
|
|
|
#define VERTS_PER_SLICE (16)
|
|
|
|
#define BYTES_PER_SLICE (VERTS_PER_SLICE * sizeof (quadvert_t))
|
|
|
|
#define INDS_PER_QUAD (4)
|
|
|
|
#define INDS_PER_SLICE (26)
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
#define MAX_INSTANCES (1024*1024)
|
2022-10-03 01:29:49 +00:00
|
|
|
|
2022-05-28 09:14:26 +00:00
|
|
|
#define MAX_LINES (32768)
|
|
|
|
#define VERTS_PER_LINE (2)
|
2023-01-11 02:34:32 +00:00
|
|
|
#define BYTES_PER_LINE (VERTS_PER_LINE * sizeof (linevert_t))
|
2022-05-28 09:14:26 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
#define DVERTS_PER_FRAME (LINES_OFFSET + MAX_LINES*VERTS_PER_LINE)
|
2022-11-18 00:44:01 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
generate_slice_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer)
|
|
|
|
{
|
|
|
|
qfv_packet_t *packet = QFV_PacketAcquire (staging);
|
|
|
|
uint32_t *ind = QFV_PacketExtend (packet, ind_buffer->buffer.size);
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
ind[i] = i;
|
|
|
|
ind[i + 9] = i + 1 + (i & 1) * 6;
|
|
|
|
ind[i + 18] = i + 8;
|
|
|
|
}
|
|
|
|
ind[8] = ind[17] = ~0;
|
2023-01-11 02:32:05 +00:00
|
|
|
QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, 0,
|
2022-11-18 00:44:01 +00:00
|
|
|
&bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]);
|
|
|
|
QFV_PacketSubmit (packet);
|
|
|
|
}
|
|
|
|
|
2021-01-12 02:27:41 +00:00
|
|
|
static void
|
2023-01-11 02:34:32 +00:00
|
|
|
create_buffers (vulkan_ctx_t *ctx)
|
2021-01-12 02:27:41 +00:00
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
2021-02-05 01:22:32 +00:00
|
|
|
size_t frames = ctx->frames.size;
|
2022-10-03 01:29:49 +00:00
|
|
|
|
|
|
|
dctx->draw_resource = malloc (2 * sizeof (qfv_resource_t)
|
2023-01-11 02:34:32 +00:00
|
|
|
// index buffer
|
|
|
|
+ sizeof (qfv_resobj_t)
|
|
|
|
// svertex buffer and view
|
2022-11-18 00:44:01 +00:00
|
|
|
+ 2 * sizeof (qfv_resobj_t)
|
2023-01-11 02:34:32 +00:00
|
|
|
// frames dynamic vertex buffers and views
|
|
|
|
+ (frames) * 2 * sizeof (qfv_resobj_t)
|
|
|
|
// frames instance buffers
|
2022-10-03 01:29:49 +00:00
|
|
|
+ (frames) * sizeof (qfv_resobj_t));
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->index_object = (qfv_resobj_t *) &dctx->draw_resource[2];
|
2023-01-11 03:47:22 +00:00
|
|
|
dctx->svertex_objects = &dctx->index_object[1];
|
|
|
|
dctx->dvertex_objects = &dctx->svertex_objects[2];
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->instance_objects = &dctx->dvertex_objects[2 * frames];
|
|
|
|
|
|
|
|
dctx->svertex_index = 0;
|
|
|
|
dctx->svertex_max = MAX_QUADS * VERTS_PER_QUAD;
|
2022-10-03 01:29:49 +00:00
|
|
|
|
|
|
|
dctx->draw_resource[0] = (qfv_resource_t) {
|
|
|
|
.name = "draw",
|
|
|
|
.va_ctx = ctx->va_ctx,
|
|
|
|
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
2023-01-11 03:47:22 +00:00
|
|
|
.num_objects = 1 + 2, // quad and 9-slice indices, and static verts
|
2023-01-11 02:34:32 +00:00
|
|
|
.objects = dctx->index_object,
|
2022-10-03 01:29:49 +00:00
|
|
|
};
|
|
|
|
dctx->draw_resource[1] = (qfv_resource_t) {
|
|
|
|
.name = "draw",
|
|
|
|
.va_ctx = ctx->va_ctx,
|
|
|
|
.memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
2023-01-11 02:34:32 +00:00
|
|
|
.num_objects = (2 * frames) + (frames),
|
|
|
|
.objects = dctx->dvertex_objects,
|
2022-10-03 01:29:49 +00:00
|
|
|
};
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->index_object[0] = (qfv_resobj_t) {
|
2022-10-03 01:29:49 +00:00
|
|
|
.name = "quads.index",
|
|
|
|
.type = qfv_res_buffer,
|
|
|
|
.buffer = {
|
2023-01-11 02:34:32 +00:00
|
|
|
.size = INDS_PER_SLICE * sizeof (uint32_t),
|
2022-10-03 01:29:49 +00:00
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
|
|
|
},
|
|
|
|
};
|
2023-01-11 03:47:22 +00:00
|
|
|
dctx->svertex_objects[0] = (qfv_resobj_t) {
|
2023-01-11 02:34:32 +00:00
|
|
|
.name = "sverts",
|
2022-11-18 00:44:01 +00:00
|
|
|
.type = qfv_res_buffer,
|
|
|
|
.buffer = {
|
2023-01-11 02:34:32 +00:00
|
|
|
.size = MAX_QUADS * BYTES_PER_QUAD,
|
2022-11-18 00:44:01 +00:00
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
2023-01-11 02:34:32 +00:00
|
|
|
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
|
|
|
|
},
|
|
|
|
};
|
2023-01-11 03:47:22 +00:00
|
|
|
dctx->svertex_objects[1] = (qfv_resobj_t) {
|
2023-01-11 02:34:32 +00:00
|
|
|
.name = "sverts",
|
|
|
|
.type = qfv_res_buffer_view,
|
|
|
|
.buffer_view = {
|
|
|
|
.buffer = 1,
|
|
|
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
|
|
|
.offset = 0,
|
2023-01-11 03:47:22 +00:00
|
|
|
.size = dctx->svertex_objects[0].buffer.size,
|
2022-11-18 00:44:01 +00:00
|
|
|
},
|
|
|
|
};
|
2022-10-03 01:29:49 +00:00
|
|
|
|
|
|
|
for (size_t i = 0; i < frames; i++) {
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->dvertex_objects[i * 2 + 0] = (qfv_resobj_t) {
|
|
|
|
.name = "dverts",
|
2022-11-18 00:44:01 +00:00
|
|
|
.type = qfv_res_buffer,
|
|
|
|
.buffer = {
|
2023-01-11 02:34:32 +00:00
|
|
|
.size = MAX_QUADS * BYTES_PER_QUAD,
|
2022-11-18 00:44:01 +00:00
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
2023-01-11 02:34:32 +00:00
|
|
|
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
|
2022-11-18 00:44:01 +00:00
|
|
|
},
|
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->dvertex_objects[i * 2 + 1] = (qfv_resobj_t) {
|
|
|
|
.name = "dverts",
|
|
|
|
.type = qfv_res_buffer_view,
|
|
|
|
.buffer_view = {
|
|
|
|
.buffer = &dctx->dvertex_objects[i * 2 + 0]
|
|
|
|
- dctx->draw_resource[1].objects,
|
|
|
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
|
|
|
.offset = 0,
|
|
|
|
.size = dctx->dvertex_objects[i * 2 + 0].buffer.size,
|
2022-10-03 01:29:49 +00:00
|
|
|
},
|
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->instance_objects[i] = (qfv_resobj_t) {
|
|
|
|
.name = "inst",
|
2022-10-03 01:29:49 +00:00
|
|
|
.type = qfv_res_buffer,
|
|
|
|
.buffer = {
|
2023-01-11 02:34:32 +00:00
|
|
|
.size = MAX_INSTANCES * sizeof (quadinst_t),
|
2022-10-03 01:29:49 +00:00
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
QFV_CreateResource (device, &dctx->draw_resource[0]);
|
|
|
|
QFV_CreateResource (device, &dctx->draw_resource[1]);
|
2021-01-16 05:42:25 +00:00
|
|
|
|
2021-01-12 02:27:41 +00:00
|
|
|
void *data;
|
2022-10-03 01:29:49 +00:00
|
|
|
VkDeviceMemory memory = dctx->draw_resource[1].memory;
|
|
|
|
dfunc->vkMapMemory (device->dev, memory, 0, VK_WHOLE_SIZE, 0, &data);
|
2021-01-16 05:42:25 +00:00
|
|
|
|
|
|
|
for (size_t f = 0; f < frames; f++) {
|
|
|
|
drawframe_t *frame = &dctx->frames.a[f];
|
2023-01-11 02:34:32 +00:00
|
|
|
frame->instance_buffer = dctx->instance_objects[f].buffer.buffer;
|
|
|
|
frame->instance_offset = dctx->instance_objects[f].buffer.offset;
|
2023-01-11 08:16:49 +00:00
|
|
|
frame->dvert_buffer = dctx->dvertex_objects[f * 2 + 0].buffer.buffer;
|
2023-01-11 02:34:32 +00:00
|
|
|
frame->dvert_view = dctx->dvertex_objects[f * 2 + 1].buffer_view.view;
|
|
|
|
frame->line_offset = dctx->dvertex_objects[f * 2].buffer.offset;
|
|
|
|
|
2023-01-11 08:16:49 +00:00
|
|
|
frame->dvertex_index = 0;
|
|
|
|
frame->dvertex_max = MAX_QUADS * VERTS_PER_QUAD;
|
|
|
|
|
2022-10-07 07:53:13 +00:00
|
|
|
DARRAY_INIT (&frame->quad_batch, 16);
|
2023-01-11 02:34:32 +00:00
|
|
|
frame->quad_insts = (quadqueue_t) {
|
|
|
|
.quads = (quadinst_t *) ((byte *)data + frame->instance_offset),
|
|
|
|
.size = MAX_INSTANCES,
|
2022-09-09 08:06:33 +00:00
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
|
2022-09-09 08:06:33 +00:00
|
|
|
frame->line_verts = (vertqueue_t) {
|
2023-01-11 02:34:32 +00:00
|
|
|
.verts = (linevert_t *) ((byte *)data + frame->line_offset),
|
|
|
|
.size = MAX_INSTANCES,
|
2022-09-09 08:06:33 +00:00
|
|
|
};
|
2021-01-16 05:42:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// The indices will never change so pre-generate and stash them
|
2023-01-11 02:34:32 +00:00
|
|
|
generate_slice_indices (ctx->staging, &dctx->index_object[0]);
|
2021-01-12 02:27:41 +00:00
|
|
|
}
|
|
|
|
|
2021-01-13 06:28:56 +00:00
|
|
|
static void
|
|
|
|
flush_draw_scrap (vulkan_ctx_t *ctx)
|
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
QFV_ScrapFlush (ctx->draw_context->scrap);
|
2021-01-13 06:28:56 +00:00
|
|
|
}
|
|
|
|
|
2021-01-13 15:44:34 +00:00
|
|
|
static void
|
2021-02-05 07:25:08 +00:00
|
|
|
pic_free (drawctx_t *dctx, qpic_t *pic)
|
2021-01-13 15:44:34 +00:00
|
|
|
{
|
2023-01-11 04:34:27 +00:00
|
|
|
__auto_type pd = (picdata_t *) pic->data;
|
|
|
|
QFV_SubpicDelete (pd->subpic);
|
2021-02-05 07:25:08 +00:00
|
|
|
cmemfree (dctx->pic_memsuper, pic);
|
2021-01-13 15:44:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static cachepic_t *
|
2021-02-05 07:25:08 +00:00
|
|
|
new_cachepic (drawctx_t *dctx, const char *name, qpic_t *pic)
|
2021-01-13 15:44:34 +00:00
|
|
|
{
|
|
|
|
cachepic_t *cp;
|
2021-02-05 07:25:08 +00:00
|
|
|
size_t size = strlen (name) + 1;
|
2021-01-13 15:44:34 +00:00
|
|
|
|
2021-02-05 07:25:08 +00:00
|
|
|
cp = cmemalloc (dctx->pic_memsuper, sizeof (cachepic_t));
|
|
|
|
cp->name = cmemalloc (dctx->string_memsuper, size);
|
|
|
|
memcpy (cp->name, name, size);
|
2021-01-13 15:44:34 +00:00
|
|
|
cp->pic = pic;
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-05 07:25:08 +00:00
|
|
|
cachepic_free (void *_cp, void *_dctx)
|
2021-01-13 15:44:34 +00:00
|
|
|
{
|
2021-02-05 07:25:08 +00:00
|
|
|
drawctx_t *dctx = _dctx;
|
2021-01-13 15:44:34 +00:00
|
|
|
cachepic_t *cp = (cachepic_t *) _cp;
|
2021-02-05 07:25:08 +00:00
|
|
|
pic_free (dctx, cp->pic);
|
|
|
|
cmemfree (dctx->string_memsuper, cp->name);
|
|
|
|
cmemfree (dctx->pic_memsuper, cp);
|
2021-01-13 15:44:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
cachepic_getkey (const void *_cp, void *unused)
|
|
|
|
{
|
|
|
|
return ((cachepic_t *) _cp)->name;
|
|
|
|
}
|
|
|
|
|
2023-01-12 08:10:43 +00:00
|
|
|
static uint32_t
|
|
|
|
create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic,
|
|
|
|
uint32_t *vertex_index, VkBuffer buffer, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
__auto_type pd = (picdata_t *) pic->data;
|
|
|
|
|
|
|
|
int x = rect[0] + pd->subpic->rect->x;
|
|
|
|
int y = rect[1] + pd->subpic->rect->y;
|
|
|
|
int w = rect[2];
|
|
|
|
int h = rect[3];
|
|
|
|
int l = border[0];
|
|
|
|
int t = border[1];
|
|
|
|
int r = w - border[2];
|
|
|
|
int b = h - border[3];
|
|
|
|
|
|
|
|
vec4f_t p[16] = {
|
|
|
|
{ 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 },
|
|
|
|
{ 0, b, 0, b }, { 0, h, 0, h }, { l, b, l, b }, { l, h, l, 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, s, s };
|
|
|
|
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
|
|
|
quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_SLICE);
|
|
|
|
for (int i = 0; i < VERTS_PER_SLICE; i++) {
|
|
|
|
vec4f_t v = ((vec4f_t) {0, 0, x, y} + p[i]) * size;
|
|
|
|
verts[i] = (quadvert_t) { {v[0], v[1]}, {v[2], v[3]} };
|
|
|
|
}
|
|
|
|
|
|
|
|
int ind = *vertex_index;
|
|
|
|
*vertex_index += VERTS_PER_SLICE;
|
|
|
|
QFV_PacketCopyBuffer (packet, buffer, ind * sizeof (quadvert_t),
|
|
|
|
&bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]);
|
|
|
|
QFV_PacketSubmit (packet);
|
|
|
|
|
|
|
|
return ind;
|
|
|
|
}
|
|
|
|
|
2023-01-11 08:16:49 +00:00
|
|
|
static uint32_t
|
|
|
|
create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index,
|
|
|
|
VkBuffer buffer, vulkan_ctx_t *ctx)
|
2023-01-11 04:34:27 +00:00
|
|
|
{
|
|
|
|
__auto_type pd = (picdata_t *) pic->data;
|
|
|
|
|
|
|
|
x += pd->subpic->rect->x;
|
|
|
|
y += pd->subpic->rect->y;
|
|
|
|
float size = pd->subpic->size;
|
|
|
|
float sl = (x + 0) * size;
|
|
|
|
float sr = (x + w) * size;
|
|
|
|
float st = (y + 0) * size;
|
|
|
|
float sb = (y + h) * size;
|
|
|
|
|
|
|
|
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
|
|
|
quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_QUAD);
|
|
|
|
verts[0] = (quadvert_t) { {0, 0}, {sl, st} };
|
|
|
|
verts[1] = (quadvert_t) { {0, h}, {sl, sb} };
|
|
|
|
verts[2] = (quadvert_t) { {w, 0}, {sr, st} };
|
|
|
|
verts[3] = (quadvert_t) { {w, h}, {sr, sb} };
|
|
|
|
|
2023-01-11 08:16:49 +00:00
|
|
|
int ind = *vertex_index;
|
|
|
|
*vertex_index += VERTS_PER_QUAD;
|
|
|
|
QFV_PacketCopyBuffer (packet, buffer, ind * sizeof (quadvert_t),
|
2023-01-11 04:34:27 +00:00
|
|
|
&bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]);
|
|
|
|
QFV_PacketSubmit (packet);
|
|
|
|
|
|
|
|
return ind;
|
|
|
|
}
|
|
|
|
|
2023-01-11 08:16:49 +00:00
|
|
|
static int
|
|
|
|
make_static_quad (int w, int h, qpic_t *pic, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
|
|
|
|
return create_quad (0, 0, w, h, pic, &dctx->svertex_index,
|
|
|
|
dctx->svertex_objects[0].buffer.buffer, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
make_dyn_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
|
|
|
return create_quad (x, y, w, h, pic, &frame->dvertex_index,
|
|
|
|
frame->dvert_buffer, ctx);
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:19:16 +00:00
|
|
|
static qpic_t *
|
2023-01-11 04:34:27 +00:00
|
|
|
pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx)
|
2020-02-11 03:19:16 +00:00
|
|
|
{
|
2023-01-11 04:34:27 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
2020-02-11 03:19:16 +00:00
|
|
|
qpic_t *pic;
|
2021-01-13 06:28:56 +00:00
|
|
|
byte *picdata;
|
2020-02-11 03:19:16 +00:00
|
|
|
|
2021-02-05 07:25:08 +00:00
|
|
|
pic = cmemalloc (dctx->pic_memsuper,
|
2023-01-11 04:34:27 +00:00
|
|
|
field_offset (qpic_t, data[sizeof (picdata_t)]));
|
2020-02-11 03:19:16 +00:00
|
|
|
pic->width = w;
|
|
|
|
pic->height = h;
|
2023-01-11 04:34:27 +00:00
|
|
|
__auto_type pd = (picdata_t *) pic->data;
|
|
|
|
pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h);
|
2023-01-11 08:16:49 +00:00
|
|
|
pd->vert_index = make_static_quad (w, h, pic, ctx);
|
2021-01-13 06:28:56 +00:00
|
|
|
|
2023-01-11 04:34:27 +00:00
|
|
|
picdata = QFV_SubpicBatch (pd->subpic, dctx->stage);
|
2021-01-13 06:28:56 +00:00
|
|
|
size_t size = w * h;
|
|
|
|
for (size_t i = 0; i < size; i++) {
|
|
|
|
byte pix = *data++;
|
|
|
|
byte *col = vid.palette + pix * 3;
|
2022-08-30 05:29:22 +00:00
|
|
|
byte alpha = (pix == 255) - 1;
|
|
|
|
// pre-multiply alpha.
|
|
|
|
*picdata++ = *col++ & alpha;
|
|
|
|
*picdata++ = *col++ & alpha;
|
|
|
|
*picdata++ = *col++ & alpha;
|
|
|
|
*picdata++ = alpha;
|
2021-01-13 06:28:56 +00:00
|
|
|
}
|
2022-04-23 01:46:55 +00:00
|
|
|
//FIXME live updates of the scrap aren't
|
|
|
|
//syncronized properly for some reason and result in stale texels being
|
|
|
|
//rendered (flashing pink around the Q menu cursor the first time it's
|
|
|
|
//displayed). I suspect simple barriers aren't enough and more
|
|
|
|
//sophisticated syncronization (events? semaphores?) is needed.
|
2020-02-11 03:19:16 +00:00
|
|
|
return pic;
|
|
|
|
}
|
|
|
|
|
2019-07-06 05:42:53 +00:00
|
|
|
qpic_t *
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_MakePic (int width, int height, const byte *data,
|
|
|
|
vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2023-01-11 04:34:27 +00:00
|
|
|
return pic_data (0, width, height, data, ctx);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_DestroyPic (qpic_t *pic, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
qpic_t *
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-13 06:28:56 +00:00
|
|
|
qpic_t *wadpic = W_GetLumpName (name);
|
|
|
|
|
|
|
|
if (!wadpic) {
|
|
|
|
return 0;
|
|
|
|
}
|
2023-01-11 04:34:27 +00:00
|
|
|
return pic_data (name, wadpic->width, wadpic->height, wadpic->data, ctx);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
qpic_t *
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-13 15:44:34 +00:00
|
|
|
qpic_t *p;
|
|
|
|
qpic_t *pic;
|
|
|
|
cachepic_t *cpic;
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
2021-01-13 15:44:34 +00:00
|
|
|
|
2021-01-16 05:42:25 +00:00
|
|
|
if ((cpic = Hash_Find (dctx->pic_cache, path))) {
|
2021-01-13 15:44:34 +00:00
|
|
|
return cpic->pic;
|
|
|
|
}
|
|
|
|
if (strlen (path) < 4 || strcmp (path + strlen (path) - 4, ".lmp")
|
|
|
|
|| !(p = (qpic_t *) QFS_LoadFile (QFS_FOpenFile (path), 0))) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-01-11 04:34:27 +00:00
|
|
|
pic = pic_data (path, p->width, p->height, p->data, ctx);
|
2021-01-13 15:44:34 +00:00
|
|
|
free (p);
|
2021-02-05 07:25:08 +00:00
|
|
|
cpic = new_cachepic (dctx, path, pic);
|
2021-01-16 05:42:25 +00:00
|
|
|
Hash_Add (dctx->pic_cache, cpic);
|
2021-01-13 15:44:34 +00:00
|
|
|
return pic;
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_UncachePic (const char *path, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
Hash_Free (dctx->pic_cache, Hash_Del (dctx->pic_cache, path));
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
2021-01-12 02:27:41 +00:00
|
|
|
void
|
|
|
|
Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-10 06:52:27 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
2021-01-10 06:52:27 +00:00
|
|
|
|
2022-10-03 01:29:49 +00:00
|
|
|
QFV_DestroyResource (device, &dctx->draw_resource[0]);
|
|
|
|
QFV_DestroyResource (device, &dctx->draw_resource[1]);
|
2023-01-11 03:47:22 +00:00
|
|
|
// the first two "fonts" are reserved for the dynamic and core quad data
|
|
|
|
// sets and thus does not have its own resources (they are created
|
|
|
|
// separately)
|
|
|
|
for (size_t i = 2; i < dctx->fonts.size; i++) {
|
2022-10-03 01:29:49 +00:00
|
|
|
QFV_DestroyResource (device, &dctx->fonts.a[i].resource->resource);
|
|
|
|
free (dctx->fonts.a[i].resource);
|
|
|
|
}
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2022-05-28 09:14:26 +00:00
|
|
|
dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0);
|
|
|
|
dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0);
|
2021-02-05 07:25:08 +00:00
|
|
|
Hash_DelTable (dctx->pic_cache);
|
|
|
|
delete_memsuper (dctx->pic_memsuper);
|
|
|
|
delete_memsuper (dctx->string_memsuper);
|
2021-01-16 05:42:25 +00:00
|
|
|
QFV_DestroyScrap (dctx->scrap);
|
|
|
|
QFV_DestroyStagingBuffer (dctx->stage);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
static void
|
|
|
|
load_conchars (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
|
|
|
|
draw_chars = W_GetLumpName ("conchars");
|
|
|
|
if (draw_chars) {
|
|
|
|
for (int i = 0; i < 256 * 64; i++) {
|
|
|
|
if (draw_chars[i] == 0) {
|
|
|
|
draw_chars[i] = 255; // proper transparent color
|
|
|
|
}
|
|
|
|
}
|
2023-01-11 04:34:27 +00:00
|
|
|
dctx->conchars = pic_data ("conchars", 128, 128, draw_chars, ctx);
|
2023-01-11 02:34:32 +00:00
|
|
|
} else {
|
|
|
|
qpic_t *charspic = Draw_Font8x8Pic ();
|
|
|
|
dctx->conchars = pic_data ("conchars", charspic->width,
|
2023-01-11 04:34:27 +00:00
|
|
|
charspic->height, charspic->data, ctx);
|
2023-01-11 02:34:32 +00:00
|
|
|
free (charspic);
|
|
|
|
}
|
|
|
|
dctx->conchar_inds = malloc (256 * sizeof (int));
|
2023-01-11 08:16:49 +00:00
|
|
|
VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer;
|
2023-01-11 02:34:32 +00:00
|
|
|
for (int i = 0; i < 256; i++) {
|
|
|
|
int cx = i % 16;
|
|
|
|
int cy = i / 16;
|
|
|
|
dctx->conchar_inds[i] = create_quad (cx * 8, cy * 8, 8, 8,
|
2023-01-11 08:16:49 +00:00
|
|
|
dctx->conchars,
|
|
|
|
&dctx->svertex_index, buffer, ctx);
|
2023-01-11 02:34:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-11 08:16:49 +00:00
|
|
|
static void
|
|
|
|
load_crosshairs (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
qpic_t *hairpic = Draw_CrosshairPic ();
|
|
|
|
dctx->crosshair = pic_data ("crosshair", hairpic->width,
|
|
|
|
hairpic->height, hairpic->data, ctx);
|
|
|
|
free (hairpic);
|
|
|
|
|
|
|
|
dctx->crosshair_inds = malloc (4 * sizeof (int));
|
|
|
|
VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer;
|
|
|
|
#define W CROSSHAIR_WIDTH
|
|
|
|
#define H CROSSHAIR_HEIGHT
|
|
|
|
dctx->crosshair_inds[0] = create_quad (0, 0, W, H, dctx->crosshair,
|
|
|
|
&dctx->svertex_index, buffer, ctx);
|
|
|
|
dctx->crosshair_inds[1] = create_quad (W, 0, W, H, dctx->crosshair,
|
|
|
|
&dctx->svertex_index, buffer, ctx);
|
|
|
|
dctx->crosshair_inds[2] = create_quad (0, H, W, H, dctx->crosshair,
|
|
|
|
&dctx->svertex_index, buffer, ctx);
|
|
|
|
dctx->crosshair_inds[3] = create_quad (W, H, W, H, dctx->crosshair,
|
|
|
|
&dctx->svertex_index, buffer, ctx);
|
|
|
|
#undef W
|
|
|
|
#undef H
|
|
|
|
}
|
|
|
|
|
2023-01-12 08:10:43 +00:00
|
|
|
static void
|
|
|
|
load_white_pic (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
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_ind = create_slice ((vec4i_t) {0, 0, 1, 1},
|
|
|
|
(vec4i_t) {0, 0, 0, 0},
|
|
|
|
dctx->white_pic,
|
|
|
|
&dctx->svertex_index, buffer, ctx);
|
|
|
|
}
|
|
|
|
|
2019-07-06 05:42:53 +00:00
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_Init (vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-10 06:52:27 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
2021-01-10 16:27:40 +00:00
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
2021-12-02 13:48:50 +00:00
|
|
|
qfvPushDebug (ctx, "draw init");
|
|
|
|
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = calloc (1, sizeof (drawctx_t));
|
|
|
|
ctx->draw_context = dctx;
|
|
|
|
|
2021-02-05 01:22:32 +00:00
|
|
|
size_t frames = ctx->frames.size;
|
2021-01-16 05:42:25 +00:00
|
|
|
DARRAY_INIT (&dctx->frames, frames);
|
|
|
|
DARRAY_RESIZE (&dctx->frames, frames);
|
|
|
|
dctx->frames.grow = 0;
|
2022-10-03 01:29:49 +00:00
|
|
|
DARRAY_INIT (&dctx->fonts, 16);
|
|
|
|
DARRAY_RESIZE (&dctx->fonts, 16);
|
|
|
|
dctx->fonts.grow = 0;
|
|
|
|
dctx->fonts.size = 0;
|
2021-01-16 05:42:25 +00:00
|
|
|
|
2021-02-05 07:25:08 +00:00
|
|
|
dctx->pic_memsuper = new_memsuper ();
|
|
|
|
dctx->string_memsuper = new_memsuper ();
|
2021-01-16 05:42:25 +00:00
|
|
|
dctx->pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free,
|
2021-02-05 07:25:08 +00:00
|
|
|
dctx, 0);
|
2021-01-13 15:44:34 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
create_buffers (ctx);
|
2021-01-31 10:58:55 +00:00
|
|
|
dctx->stage = QFV_CreateStagingBuffer (device, "draw", 4 * 1024 * 1024,
|
2021-01-19 16:23:24 +00:00
|
|
|
ctx->cmdpool);
|
2021-01-31 10:58:55 +00:00
|
|
|
dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba,
|
|
|
|
dctx->stage);
|
2022-11-19 18:59:01 +00:00
|
|
|
dctx->pic_sampler = Vulkan_CreateSampler (ctx, "quakepic");
|
|
|
|
dctx->glyph_sampler = Vulkan_CreateSampler (ctx, "glyph");
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
load_conchars (ctx);
|
2023-01-11 08:16:49 +00:00
|
|
|
load_crosshairs (ctx);
|
2023-01-12 08:10:43 +00:00
|
|
|
load_white_pic (ctx);
|
2021-01-10 16:27:40 +00:00
|
|
|
|
2022-11-12 15:49:47 +00:00
|
|
|
dctx->backtile_pic = Vulkan_Draw_PicFromWad ("backtile", ctx);
|
|
|
|
if (!dctx->backtile_pic) {
|
|
|
|
dctx->backtile_pic = dctx->white_pic;
|
|
|
|
}
|
|
|
|
|
2021-01-13 06:28:56 +00:00
|
|
|
flush_draw_scrap (ctx);
|
2021-01-10 16:27:40 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice");
|
2022-05-28 09:14:26 +00:00
|
|
|
dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines");
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
dctx->lines_layout = Vulkan_CreatePipelineLayout (ctx, "lines_layout");
|
|
|
|
dctx->quad_layout = Vulkan_CreatePipelineLayout (ctx, "quad_layout");
|
|
|
|
__auto_type sl = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set");
|
|
|
|
dctx->quad_data_set_layout = sl;
|
|
|
|
dctx->quad_pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool");
|
2021-01-10 06:52:27 +00:00
|
|
|
|
2023-01-11 03:47:22 +00:00
|
|
|
// core set + dynamic sets
|
|
|
|
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1 + frames, alloca);
|
2023-01-11 02:34:32 +00:00
|
|
|
for (size_t i = 0; i < layouts->size; i++) {
|
|
|
|
layouts->a[i] = dctx->quad_data_set_layout;
|
|
|
|
}
|
2021-01-12 02:27:41 +00:00
|
|
|
|
|
|
|
VkDescriptorImageInfo imageInfo = {
|
2022-11-19 18:59:01 +00:00
|
|
|
dctx->pic_sampler,
|
2021-01-16 05:42:25 +00:00
|
|
|
QFV_ScrapImageView (dctx->scrap),
|
2021-01-12 02:27:41 +00:00
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
|
|
};
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
__auto_type pool = dctx->quad_pool;
|
2021-01-10 06:52:27 +00:00
|
|
|
__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts);
|
2023-01-11 03:47:22 +00:00
|
|
|
for (size_t i = 1; i < sets->size; i++) {
|
|
|
|
__auto_type frame = &dctx->frames.a[i - 1];
|
|
|
|
frame->dyn_quad_set = sets->a[i];
|
2023-01-11 02:34:32 +00:00
|
|
|
VkWriteDescriptorSet write[] = {
|
|
|
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
2023-01-11 03:47:22 +00:00
|
|
|
frame->dyn_quad_set, 0, 0, 1,
|
2023-01-11 02:34:32 +00:00
|
|
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
&imageInfo, 0, 0 },
|
|
|
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
2023-01-11 03:47:22 +00:00
|
|
|
frame->dyn_quad_set, 1, 0, 1,
|
2023-01-11 02:34:32 +00:00
|
|
|
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
|
|
|
|
0, 0, &frame->dvert_view },
|
|
|
|
};
|
|
|
|
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
|
|
|
|
}
|
2023-01-11 03:47:22 +00:00
|
|
|
dctx->core_quad_set = sets->a[0];
|
2022-10-03 01:29:49 +00:00
|
|
|
free (sets);
|
|
|
|
|
2023-01-11 03:47:22 +00:00
|
|
|
VkWriteDescriptorSet write[] = {
|
|
|
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
|
|
|
dctx->core_quad_set, 0, 0, 1,
|
|
|
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
&imageInfo, 0, 0 },
|
|
|
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
|
|
|
dctx->core_quad_set, 1, 0, 1,
|
|
|
|
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
|
|
|
|
0, 0, &dctx->svertex_objects[1].buffer_view.view },
|
|
|
|
};
|
|
|
|
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
DARRAY_APPEND (&dctx->fonts, (drawfont_t) {});
|
2023-01-11 03:47:22 +00:00
|
|
|
DARRAY_APPEND (&dctx->fonts, (drawfont_t) { .set = dctx->core_quad_set });
|
2023-01-11 02:34:32 +00:00
|
|
|
|
2021-01-15 13:45:49 +00:00
|
|
|
for (size_t i = 0; i < frames; i++) {
|
2021-01-16 05:42:25 +00:00
|
|
|
__auto_type dframe = &dctx->frames.a[i];
|
2022-11-20 17:29:03 +00:00
|
|
|
|
|
|
|
DARRAY_INIT (&dframe->cmdSet, QFV_drawNumPasses);
|
|
|
|
DARRAY_RESIZE (&dframe->cmdSet, QFV_drawNumPasses);
|
|
|
|
dframe->cmdSet.grow = 0;
|
|
|
|
|
|
|
|
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &dframe->cmdSet);
|
|
|
|
|
|
|
|
for (int j = 0; j < QFV_drawNumPasses; j++) {
|
|
|
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
|
|
|
dframe->cmdSet.a[j],
|
|
|
|
va (ctx->va_ctx, "cmd:draw:%zd:%s", i,
|
|
|
|
draw_pass_names[j]));
|
|
|
|
}
|
2021-01-12 02:27:41 +00:00
|
|
|
}
|
2021-12-02 13:48:50 +00:00
|
|
|
qfvPopDebug (ctx);
|
2021-01-12 02:27:41 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
static inline descbatch_t *
|
|
|
|
get_desc_batch (drawframe_t *frame, int descid, uint32_t ind_count)
|
|
|
|
{
|
|
|
|
descbatch_t *batch = &frame->quad_batch.a[frame->quad_batch.size - 1];
|
|
|
|
if (!frame->quad_batch.size || batch->descid != descid
|
|
|
|
|| ((batch->count & (0xff << 24)) != (ind_count << 24))) {
|
|
|
|
DARRAY_APPEND(&frame->quad_batch, ((descbatch_t) { .descid = descid }));
|
|
|
|
batch = &frame->quad_batch.a[frame->quad_batch.size - 1];
|
|
|
|
batch->count = ind_count << 24;
|
|
|
|
}
|
|
|
|
|
|
|
|
return batch;
|
|
|
|
}
|
|
|
|
|
2021-01-12 02:27:41 +00:00
|
|
|
static inline void
|
2023-01-12 08:10:43 +00:00
|
|
|
draw_slice (float x, float y, float ox, float oy, int descid, uint32_t vertid,
|
|
|
|
const byte *color, drawframe_t *frame)
|
|
|
|
{
|
|
|
|
__auto_type queue = &frame->quad_insts;
|
|
|
|
if (queue->count >= queue->size) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
__auto_type batch = get_desc_batch (frame, descid, INDS_PER_SLICE);
|
|
|
|
batch->count++;
|
|
|
|
|
|
|
|
quadinst_t *quad = &queue->quads[queue->count++];
|
|
|
|
*quad = (quadinst_t) {
|
|
|
|
.index = vertid,
|
|
|
|
.color = { QuatExpand (color) },
|
|
|
|
.position = { x, y },
|
|
|
|
.offset = { ox, oy },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
draw_quad (float x, float y, int descid, uint32_t vertid, const byte *color,
|
2023-01-11 02:34:32 +00:00
|
|
|
drawframe_t *frame)
|
2021-01-12 02:27:41 +00:00
|
|
|
{
|
2023-01-11 02:34:32 +00:00
|
|
|
__auto_type queue = &frame->quad_insts;
|
2022-09-09 08:06:33 +00:00
|
|
|
if (queue->count >= queue->size) {
|
2021-01-12 02:27:41 +00:00
|
|
|
return;
|
2021-01-10 06:52:27 +00:00
|
|
|
}
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
__auto_type batch = get_desc_batch (frame, descid, INDS_PER_QUAD);
|
|
|
|
batch->count++;
|
2021-01-13 06:28:56 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
quadinst_t *quad = &queue->quads[queue->count++];
|
|
|
|
*quad = (quadinst_t) {
|
|
|
|
.index = vertid,
|
|
|
|
.color = { QuatExpand (color) },
|
|
|
|
.position = { x, y },
|
|
|
|
.offset = { 0, 0 },
|
|
|
|
};
|
2021-01-12 02:27:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx)
|
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
byte color[4] = {255, 255, 255, 255};
|
2023-01-11 03:47:22 +00:00
|
|
|
draw_quad (x, y, 1, dctx->conchar_inds[chr], color, frame);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
2022-09-15 05:24:33 +00:00
|
|
|
void
|
|
|
|
Vulkan_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer,
|
|
|
|
vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
const byte *line = (byte *) buffer->chars;
|
|
|
|
int width = buffer->width;
|
|
|
|
int height = buffer->height;
|
|
|
|
while (height-- > 0) {
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
Vulkan_Draw_Character (x + i * 8, y, line[i], ctx);
|
|
|
|
}
|
|
|
|
line += width;
|
|
|
|
y += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-06 05:42:53 +00:00
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-12 02:27:41 +00:00
|
|
|
if (chr == ' ') {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-21 08:31:18 +00:00
|
|
|
if (y <= -8 || y >= (int) vid.height) {
|
2021-01-12 02:27:41 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-09-21 08:31:18 +00:00
|
|
|
if (x <= -8 || x >= (int) vid.width) {
|
2021-01-12 02:27:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
queue_character (x, y, chr, ctx);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_String (int x, int y, const char *str, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-12 02:27:41 +00:00
|
|
|
byte chr;
|
|
|
|
|
|
|
|
if (!str || !str[0]) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-21 08:31:18 +00:00
|
|
|
if (y <= -8 || y >= (int) vid.height) {
|
2021-01-12 02:27:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
while (*str) {
|
2022-09-21 08:31:18 +00:00
|
|
|
if ((chr = *str++) != ' ' && x >= -8 && x < (int) vid.width) {
|
2021-01-12 02:27:41 +00:00
|
|
|
queue_character (x, y, chr, ctx);
|
|
|
|
}
|
|
|
|
x += 8;
|
|
|
|
}
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_nString (int x, int y, const char *str, int count,
|
|
|
|
vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-12 02:27:41 +00:00
|
|
|
byte chr;
|
|
|
|
|
|
|
|
if (!str || !str[0]) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-21 08:31:18 +00:00
|
|
|
if (y <= -8 || y >= (int) vid.height) {
|
2021-01-12 02:27:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
while (count-- > 0 && *str) {
|
2022-09-21 08:31:18 +00:00
|
|
|
if ((chr = *str++) != ' ' && x >= -8 && x < (int) vid.width) {
|
2021-01-12 02:27:41 +00:00
|
|
|
queue_character (x, y, chr, ctx);
|
|
|
|
}
|
|
|
|
x += 8;
|
|
|
|
}
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_AltString (int x, int y, const char *str, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-12 02:27:41 +00:00
|
|
|
byte chr;
|
|
|
|
|
|
|
|
if (!str || !str[0]) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-21 08:31:18 +00:00
|
|
|
if (y <= -8 || y >= (int) vid.height) {
|
2021-01-12 02:27:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
while (*str) {
|
|
|
|
if ((chr = *str++ | 0x80) != (' ' | 0x80)
|
2022-09-21 08:31:18 +00:00
|
|
|
&& x >= -8 && x < (int) vid.width) {
|
2021-01-12 02:27:41 +00:00
|
|
|
queue_character (x, y, chr, ctx);
|
|
|
|
}
|
|
|
|
x += 8;
|
|
|
|
}
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
2021-12-18 04:07:56 +00:00
|
|
|
static void
|
|
|
|
draw_crosshair_plus (int ch, int x, int y, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
Vulkan_Draw_Character (x - 4, y - 4, '+', ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
byte *color = &vid.palette32[bound (0, crosshaircolor, 255) * 4];
|
2023-01-11 08:16:49 +00:00
|
|
|
draw_quad (x, y, 1, dctx->crosshair_inds[ch - 1], color, frame);
|
2021-12-18 04:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void (*crosshair_func[]) (int ch, int x, int y, vulkan_ctx_t *ctx) = {
|
|
|
|
draw_crosshair_plus,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
};
|
|
|
|
|
2019-07-06 05:42:53 +00:00
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_CrosshairAt (int ch, int x, int y, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-12-18 04:07:56 +00:00
|
|
|
unsigned c = ch - 1;
|
|
|
|
|
|
|
|
if (c >= sizeof (crosshair_func) / sizeof (crosshair_func[0]))
|
|
|
|
return;
|
|
|
|
|
|
|
|
crosshair_func[c] (c, x, y, ctx);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-12-18 04:07:56 +00:00
|
|
|
int x, y;
|
2022-11-18 02:23:32 +00:00
|
|
|
int s = 2 * ctx->twod_scale;
|
2021-12-18 04:07:56 +00:00
|
|
|
|
2022-11-18 02:23:32 +00:00
|
|
|
x = vid.width / s + cl_crossx;
|
|
|
|
y = vid.height / s + cl_crossy;
|
2021-12-18 04:07:56 +00:00
|
|
|
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
Vulkan_Draw_CrosshairAt (crosshair, x, y, ctx);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
2021-07-11 01:59:27 +00:00
|
|
|
void
|
|
|
|
Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha,
|
|
|
|
vulkan_ctx_t *ctx)
|
|
|
|
{
|
2023-01-11 02:34:32 +00:00
|
|
|
#if 0
|
2021-07-11 01:59:27 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
|
|
|
quat_t color = {1, 1, 1, 1};
|
|
|
|
qpic_t *p;
|
|
|
|
int cx, cy, n;
|
2022-09-09 11:05:31 +00:00
|
|
|
#define draw(px, py, pp) \
|
|
|
|
do { \
|
|
|
|
subpic_t *subpic = *(subpic_t **) (pp)->data; \
|
|
|
|
draw_pic (px, py, pp->width, pp->height, subpic, \
|
|
|
|
0, 0, pp->width, pp->height, color, &frame->quad_verts); \
|
|
|
|
} while (0)
|
2021-07-11 01:59:27 +00:00
|
|
|
|
|
|
|
color[3] = alpha;
|
|
|
|
// draw left side
|
|
|
|
cx = x;
|
|
|
|
cy = y;
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_tl.lmp", true, ctx);
|
|
|
|
draw (cx, cy, p);
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_ml.lmp", true, ctx);
|
|
|
|
for (n = 0; n < lines; n++) {
|
|
|
|
cy += 8;
|
|
|
|
draw (cx, cy, p);
|
|
|
|
}
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_bl.lmp", true, ctx);
|
|
|
|
draw (cx, cy + 8, p);
|
|
|
|
|
|
|
|
// draw middle
|
|
|
|
cx += 8;
|
|
|
|
while (width > 0) {
|
|
|
|
cy = y;
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_tm.lmp", true, ctx);
|
|
|
|
draw (cx, cy, p);
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_mm.lmp", true, ctx);
|
|
|
|
for (n = 0; n < lines; n++) {
|
|
|
|
cy += 8;
|
|
|
|
if (n == 1)
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_mm2.lmp", true, ctx);
|
|
|
|
draw (cx, cy, p);
|
|
|
|
}
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_bm.lmp", true, ctx);
|
|
|
|
draw (cx, cy + 8, p);
|
|
|
|
width -= 2;
|
|
|
|
cx += 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw right side
|
|
|
|
cy = y;
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_tr.lmp", true, ctx);
|
|
|
|
draw (cx, cy, p);
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_mr.lmp", true, ctx);
|
|
|
|
for (n = 0; n < lines; n++) {
|
|
|
|
cy += 8;
|
|
|
|
draw (cx, cy, p);
|
|
|
|
}
|
|
|
|
p = Vulkan_Draw_CachePic ("gfx/box_br.lmp", true, ctx);
|
|
|
|
draw (cx, cy + 8, p);
|
|
|
|
#undef draw
|
2023-01-11 02:34:32 +00:00
|
|
|
#endif
|
2021-07-11 01:59:27 +00:00
|
|
|
}
|
|
|
|
|
2019-07-06 05:42:53 +00:00
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
static byte color[4] = { 255, 255, 255, 255};
|
2023-01-11 04:34:27 +00:00
|
|
|
__auto_type pd = (picdata_t *) pic->data;
|
|
|
|
draw_quad (x, y, 1, pd->vert_index, color, frame);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
static byte color[4] = { 255, 255, 255, 255};
|
2023-01-11 04:34:27 +00:00
|
|
|
__auto_type pd = (picdata_t *) pic->data;
|
|
|
|
draw_quad (x, y, 1, pd->vert_index, color, frame);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_SubPic (int x, int y, qpic_t *pic,
|
|
|
|
int srcx, int srcy, int width, int height,
|
|
|
|
vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-11 08:16:49 +00:00
|
|
|
uint32_t vind = make_dyn_quad (srcx, srcy, width, height, pic, ctx);
|
2023-01-11 02:34:32 +00:00
|
|
|
static byte color[4] = { 255, 255, 255, 255};
|
2023-01-11 08:16:49 +00:00
|
|
|
draw_quad (x, y, 0, vind, color, frame);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2023-01-11 02:34:32 +00:00
|
|
|
#if 0
|
2021-01-17 17:10:10 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2022-08-30 05:29:22 +00:00
|
|
|
float a = bound (0, alpha, 255) / 255.0;
|
|
|
|
// use pre-multiplied alpha
|
|
|
|
quat_t color = { a, a, a, a};
|
2021-01-17 17:10:10 +00:00
|
|
|
qpic_t *cpic;
|
|
|
|
cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx);
|
2022-11-13 13:23:56 +00:00
|
|
|
int s = ctx->twod_scale;
|
|
|
|
float frac = (vid.height - s * lines) / (float) vid.height;
|
2022-09-28 09:29:53 +00:00
|
|
|
int ofs = frac * cpic->height;
|
2022-09-09 11:05:31 +00:00
|
|
|
subpic_t *subpic = *(subpic_t **) cpic->data;
|
2022-11-13 13:23:56 +00:00
|
|
|
draw_pic (0, 0, vid.width / s, lines, subpic,
|
2022-09-28 09:29:53 +00:00
|
|
|
0, ofs, cpic->width, cpic->height - ofs, color,
|
|
|
|
&frame->quad_verts);
|
2023-01-11 02:34:32 +00:00
|
|
|
#endif
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2022-11-12 15:49:47 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-12 08:06:18 +00:00
|
|
|
static byte color[4] = { 255, 255, 255, 255};
|
2022-11-12 15:49:47 +00:00
|
|
|
vrect_t *tile_rect = VRect_New (x, y, w, h);
|
|
|
|
vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later
|
|
|
|
qpic_t *pic = dctx->backtile_pic;
|
|
|
|
int sub_sx, sub_sy, sub_ex, sub_ey;
|
|
|
|
|
|
|
|
sub_sx = x / pic->width;
|
|
|
|
sub_sy = y / pic->height;
|
|
|
|
sub_ex = (x + w + pic->width - 1) / pic->width;
|
|
|
|
sub_ey = (y + h + pic->height - 1) / pic->height;
|
|
|
|
for (int j = sub_sy; j < sub_ey; j++) {
|
|
|
|
for (int i = sub_sx; i < sub_ex; i++) {
|
|
|
|
vrect_t *t = sub;
|
|
|
|
|
|
|
|
sub->x = i * pic->width;
|
|
|
|
sub->y = j * pic->height;
|
|
|
|
sub->width = pic->width;
|
|
|
|
sub->height = pic->height;
|
|
|
|
sub = VRect_Intersect (sub, tile_rect);
|
|
|
|
VRect_Delete (t);
|
2023-01-12 08:06:18 +00:00
|
|
|
int sx = sub->x % pic->width;
|
|
|
|
int sy = sub->y % pic->height;
|
|
|
|
int sw = sub->width;
|
|
|
|
int sh = sub->height;
|
|
|
|
uint32_t vind = make_dyn_quad (sx, sy, sw, sh, pic, ctx);
|
|
|
|
draw_quad (sub->x, sub->y, 0, vind, color, frame);
|
2022-11-12 15:49:47 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-12 08:06:18 +00:00
|
|
|
byte color[4] = {VectorExpand (vid.palette + c * 3), 255 };
|
|
|
|
draw_slice (x, y, w - 1, h - 1, 1, dctx->white_pic_ind, color, frame);
|
2021-01-13 15:44:34 +00:00
|
|
|
}
|
|
|
|
|
2022-05-28 09:14:26 +00:00
|
|
|
void
|
|
|
|
Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
2022-09-09 08:06:33 +00:00
|
|
|
vertqueue_t *queue = &frame->line_verts;
|
2022-05-28 09:14:26 +00:00
|
|
|
|
2022-09-09 08:06:33 +00:00
|
|
|
if (queue->count >= queue->size) {
|
2022-05-28 09:14:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-11 04:34:27 +00:00
|
|
|
__auto_type pd = (picdata_t *) dctx->white_pic->data;
|
|
|
|
int srcx = pd->subpic->rect->x;
|
|
|
|
int srcy = pd->subpic->rect->y;
|
|
|
|
int srcw = pd->subpic->rect->width;
|
|
|
|
int srch = pd->subpic->rect->height;
|
|
|
|
float size = pd->subpic->size;
|
2022-09-28 12:53:22 +00:00
|
|
|
float sl = (srcx + 0.03125) * size;
|
|
|
|
float sr = (srcx + srcw - 0.03125) * size;
|
|
|
|
float st = (srcy + 0.03125) * size;
|
|
|
|
float sb = (srcy + srch - 0.03125) * size;
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
linevert_t *verts = queue->verts + queue->count * VERTS_PER_LINE;
|
|
|
|
verts[0] = (linevert_t) {
|
2022-05-28 09:14:26 +00:00
|
|
|
.xy = { x0, y0 },
|
2022-09-28 12:53:22 +00:00
|
|
|
.st = {sl, st},
|
2023-01-11 02:34:32 +00:00
|
|
|
.color = { VectorExpand (vid.palette + c * 3), 255 },
|
2022-05-28 09:14:26 +00:00
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
verts[1] = (linevert_t) {
|
2022-05-28 09:14:26 +00:00
|
|
|
.xy = { x1, y1 },
|
2022-09-28 12:53:22 +00:00
|
|
|
.st = {sr, sb},
|
2023-01-11 02:34:32 +00:00
|
|
|
.color = { VectorExpand (vid.palette + c * 3), 255 },
|
2022-05-28 09:14:26 +00:00
|
|
|
};
|
|
|
|
|
2022-09-09 08:06:33 +00:00
|
|
|
queue->count++;
|
2022-05-28 09:14:26 +00:00
|
|
|
}
|
|
|
|
|
2021-01-13 15:44:34 +00:00
|
|
|
static inline void
|
2023-01-12 08:10:43 +00:00
|
|
|
draw_blendscreen (const byte *color, vulkan_ctx_t *ctx)
|
2021-01-13 15:44:34 +00:00
|
|
|
{
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
2023-01-12 08:10:43 +00:00
|
|
|
float s = 1.0 / ctx->twod_scale;
|
2021-01-16 05:42:25 +00:00
|
|
|
|
2023-01-12 08:10:43 +00:00
|
|
|
draw_slice (0, 0, vid.width * s - 1, vid.height * s - 1,
|
|
|
|
1, dctx->white_pic_ind, color, frame);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2023-01-12 08:10:43 +00:00
|
|
|
static byte color[4] = { 0, 0, 0, 179 };
|
2021-01-16 05:42:25 +00:00
|
|
|
draw_blendscreen (color, ctx);
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
2022-11-20 17:29:03 +00:00
|
|
|
static void
|
|
|
|
draw_begin_subpass (QFV_DrawSubpass subpass, qfv_renderframe_t *rFrame)
|
|
|
|
{
|
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
|
|
|
VkCommandBuffer cmd = dframe->cmdSet.a[subpass];
|
|
|
|
|
|
|
|
dfunc->vkResetCommandBuffer (cmd, 0);
|
|
|
|
VkCommandBufferInheritanceInfo inherit = {
|
|
|
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
|
|
|
|
rFrame->renderpass->renderpass, subpass_map[subpass],
|
2022-11-21 08:25:55 +00:00
|
|
|
rFrame->framebuffer,
|
2022-11-20 17:29:03 +00:00
|
|
|
0, 0, 0,
|
|
|
|
};
|
|
|
|
VkCommandBufferBeginInfo beginInfo = {
|
|
|
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
|
|
|
|
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
|
|
|
| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit,
|
|
|
|
};
|
|
|
|
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
|
|
|
|
|
|
|
QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "draw:%s",
|
|
|
|
draw_pass_names[subpass]),
|
|
|
|
{0.5, 0.8, 0.1, 1});
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
|
|
|
QFV_duCmdEndLabel (device, cmd);
|
|
|
|
dfunc->vkEndCommandBuffer (cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bind_pipeline (qfv_renderframe_t *rFrame, VkPipeline pipeline,
|
|
|
|
VkCommandBuffer cmd)
|
|
|
|
{
|
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
|
|
|
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
|
|
|
|
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd)
|
|
|
|
{
|
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
VkBuffer instance_buffer = dframe->instance_buffer;
|
2022-11-20 17:29:03 +00:00
|
|
|
VkDeviceSize offsets[] = {0};
|
2023-01-11 02:34:32 +00:00
|
|
|
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &instance_buffer, offsets);
|
2022-11-20 17:29:03 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
VkBuffer ind_buffer = dctx->index_object[0].buffer.buffer;
|
2022-11-20 17:29:03 +00:00
|
|
|
dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
|
|
|
|
|
|
uint32_t inst_start = 0;
|
2023-01-11 02:34:32 +00:00
|
|
|
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;
|
2022-11-20 17:29:03 +00:00
|
|
|
VkDescriptorSet set[2] = {
|
|
|
|
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
|
|
|
dctx->fonts.a[fontid].set,
|
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
VkPipelineLayout layout = dctx->quad_layout;
|
|
|
|
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
2022-11-20 17:29:03 +00:00
|
|
|
layout, 0, 2, set, 0, 0);
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0, inst_start);
|
2022-11-20 17:29:03 +00:00
|
|
|
inst_start += inst_count;
|
|
|
|
}
|
2023-01-11 02:34:32 +00:00
|
|
|
DARRAY_RESIZE (&dframe->quad_batch, 0);
|
2022-11-20 17:29:03 +00:00
|
|
|
}
|
2023-01-11 02:34:32 +00:00
|
|
|
#if 0
|
2022-11-20 17:29:03 +00:00
|
|
|
static void
|
|
|
|
draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd)
|
|
|
|
{
|
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
|
|
|
VkBuffer line_buffer = dframe->line_buffer;
|
|
|
|
VkDeviceSize offsets[] = {0};
|
|
|
|
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets);
|
|
|
|
VkDescriptorSet set[1] = {
|
|
|
|
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
VkPipelineLayout layout = dctx->lines_layout;
|
2022-11-20 17:29:03 +00:00
|
|
|
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
layout, 0, 1, set, 0, 0);
|
2022-11-25 02:12:05 +00:00
|
|
|
dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE,
|
|
|
|
1, 0, 0);
|
2022-11-20 17:29:03 +00:00
|
|
|
}
|
2023-01-11 02:34:32 +00:00
|
|
|
#endif
|
2019-07-06 05:42:53 +00:00
|
|
|
void
|
2021-12-02 12:58:29 +00:00
|
|
|
Vulkan_FlushText (qfv_renderframe_t *rFrame)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-12-02 12:58:29 +00:00
|
|
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
2021-01-15 13:50:04 +00:00
|
|
|
flush_draw_scrap (ctx);
|
|
|
|
|
2021-01-12 02:27:41 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2021-01-16 05:42:25 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
|
|
|
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
if (!dframe->quad_insts.count && !dframe->line_verts.count) {
|
2022-05-28 09:14:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-11 03:47:22 +00:00
|
|
|
dctx->fonts.a[0].set = dframe->dyn_quad_set;
|
2023-01-11 02:34:32 +00:00
|
|
|
|
2022-10-03 01:29:49 +00:00
|
|
|
VkDeviceMemory memory = dctx->draw_resource[1].memory;
|
2022-11-18 00:44:01 +00:00
|
|
|
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
|
|
|
size_t atom_mask = atom - 1;
|
|
|
|
#define a(x) (((x) + atom_mask) & ~atom_mask)
|
2022-05-28 09:14:26 +00:00
|
|
|
VkMappedMemoryRange ranges[] = {
|
|
|
|
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
2023-01-11 02:34:32 +00:00
|
|
|
memory, dframe->instance_offset,
|
|
|
|
a(dframe->quad_insts.count * BYTES_PER_QUAD) },
|
2022-05-28 09:14:26 +00:00
|
|
|
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
2022-10-03 01:29:49 +00:00
|
|
|
memory, dframe->line_offset,
|
2023-01-11 02:34:32 +00:00
|
|
|
a(dframe->line_verts.count * VERTS_PER_LINE * sizeof (linevert_t)) },
|
2021-01-12 02:27:41 +00:00
|
|
|
};
|
2022-11-18 00:44:01 +00:00
|
|
|
#undef a
|
2023-01-11 02:34:32 +00:00
|
|
|
dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges);
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2022-11-20 17:29:03 +00:00
|
|
|
DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_draw2d]],
|
|
|
|
dframe->cmdSet.a[QFV_draw2d]);
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2022-11-20 17:29:03 +00:00
|
|
|
draw_begin_subpass (QFV_draw2d, rFrame);
|
2021-04-18 11:40:43 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
if (dframe->quad_insts.count) {
|
2022-11-20 17:29:03 +00:00
|
|
|
bind_pipeline (rFrame, dctx->quad_pipeline,
|
|
|
|
dframe->cmdSet.a[QFV_draw2d]);
|
|
|
|
draw_quads (rFrame, dframe->cmdSet.a[QFV_draw2d]);
|
2022-09-02 05:23:19 +00:00
|
|
|
}
|
2023-01-11 02:34:32 +00:00
|
|
|
#if 0
|
2022-09-09 08:06:33 +00:00
|
|
|
if (dframe->line_verts.count) {
|
2022-11-20 17:29:03 +00:00
|
|
|
bind_pipeline (rFrame, dctx->line_pipeline,
|
|
|
|
dframe->cmdSet.a[QFV_draw2d]);
|
|
|
|
draw_lines (rFrame, dframe->cmdSet.a[QFV_draw2d]);
|
2022-05-28 09:14:26 +00:00
|
|
|
}
|
2023-01-11 02:34:32 +00:00
|
|
|
#endif
|
2022-11-20 17:29:03 +00:00
|
|
|
draw_end_subpass (dframe->cmdSet.a[QFV_draw2d], ctx);
|
2021-01-12 02:27:41 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
dframe->quad_insts.count = 0;
|
2022-09-09 08:06:33 +00:00
|
|
|
dframe->line_verts.count = 0;
|
2023-01-11 08:16:49 +00:00
|
|
|
dframe->dvertex_index = 0;
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-10 06:52:27 +00:00
|
|
|
Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx)
|
2019-07-06 05:42:53 +00:00
|
|
|
{
|
2021-01-13 15:44:34 +00:00
|
|
|
if (color[3]) {
|
2023-01-12 08:10:43 +00:00
|
|
|
byte c[4];
|
2022-08-30 05:29:22 +00:00
|
|
|
// pre-multiply alpha.
|
|
|
|
// FIXME this is kind of silly because q1source pre-multiplies alpha
|
|
|
|
// for blends, but this was un-done early in QF's history in order
|
|
|
|
// to avoid a pair of state changes
|
2023-01-12 08:10:43 +00:00
|
|
|
VectorScale (color, color[3] * 255, c);
|
|
|
|
c[3] = color[3] * 255;
|
2022-08-30 05:29:22 +00:00
|
|
|
draw_blendscreen (c, ctx);
|
2021-01-13 15:44:34 +00:00
|
|
|
}
|
2019-07-06 05:42:53 +00:00
|
|
|
}
|
2022-08-31 10:23:30 +00:00
|
|
|
|
2022-10-02 23:58:27 +00:00
|
|
|
int
|
2022-12-07 06:11:08 +00:00
|
|
|
Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx)
|
2022-08-31 10:23:30 +00:00
|
|
|
{
|
2022-10-03 01:29:49 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
2022-08-31 10:23:30 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
2022-10-03 01:29:49 +00:00
|
|
|
int fontid = dctx->fonts.size;
|
|
|
|
DARRAY_OPEN_AT (&dctx->fonts, fontid, 1);
|
|
|
|
drawfont_t *font = &dctx->fonts.a[fontid];
|
|
|
|
|
|
|
|
font->resource = malloc (sizeof (drawfontres_t));
|
|
|
|
font->resource->resource = (qfv_resource_t) {
|
2022-10-07 07:53:13 +00:00
|
|
|
.name = va (ctx->va_ctx, "glyph_data:%d", fontid),
|
2022-10-03 01:29:49 +00:00
|
|
|
.va_ctx = ctx->va_ctx,
|
|
|
|
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
.num_objects = 4,
|
|
|
|
.objects = &font->resource->glyph_data,
|
|
|
|
};
|
2022-08-31 10:23:30 +00:00
|
|
|
|
2022-10-03 01:29:49 +00:00
|
|
|
font->resource->glyph_data = (qfv_resobj_t) {
|
|
|
|
.name = "geom",
|
|
|
|
.type = qfv_res_buffer,
|
|
|
|
.buffer = {
|
2023-01-11 02:34:32 +00:00
|
|
|
.size = rfont->num_glyphs * 4 * sizeof (quadvert_t),
|
2022-10-03 01:29:49 +00:00
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
__auto_type glyph_data = &font->resource->glyph_data;
|
|
|
|
|
|
|
|
font->resource->glyph_bview = (qfv_resobj_t) {
|
|
|
|
.name = "geom_view",
|
|
|
|
.type = qfv_res_buffer_view,
|
|
|
|
.buffer_view = {
|
|
|
|
.buffer = 0,
|
|
|
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
|
|
|
.offset = 0,
|
|
|
|
.size = font->resource->glyph_data.buffer.size,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
__auto_type glyph_bview = &font->resource->glyph_bview;
|
|
|
|
|
|
|
|
tex_t tex = {
|
|
|
|
.width = rfont->scrap.width,
|
|
|
|
.height = rfont->scrap.height,
|
2022-12-05 08:13:32 +00:00
|
|
|
.format = tex_a,
|
2022-10-03 01:29:49 +00:00
|
|
|
.loaded = 1,
|
|
|
|
.data = rfont->scrap_bitmap,
|
|
|
|
};
|
|
|
|
QFV_ResourceInitTexImage (&font->resource->glyph_image, "image", 0, &tex);
|
|
|
|
__auto_type glyph_image = &font->resource->glyph_image;
|
|
|
|
|
|
|
|
font->resource->glyph_iview = (qfv_resobj_t) {
|
|
|
|
.name = "image_view",
|
|
|
|
.type = qfv_res_image_view,
|
|
|
|
.image_view = {
|
|
|
|
.image = 2,
|
|
|
|
.type = VK_IMAGE_VIEW_TYPE_2D,
|
|
|
|
.format = font->resource->glyph_image.image.format,
|
|
|
|
.aspect = VK_IMAGE_ASPECT_COLOR_BIT,
|
2022-11-20 06:46:16 +00:00
|
|
|
.components = {
|
|
|
|
.r = VK_COMPONENT_SWIZZLE_R,
|
|
|
|
.g = VK_COMPONENT_SWIZZLE_R,
|
|
|
|
.b = VK_COMPONENT_SWIZZLE_R,
|
|
|
|
.a = VK_COMPONENT_SWIZZLE_R,
|
|
|
|
},
|
2022-10-03 01:29:49 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
__auto_type glyph_iview = &font->resource->glyph_iview;
|
|
|
|
|
|
|
|
QFV_CreateResource (ctx->device, &font->resource->resource);
|
|
|
|
|
|
|
|
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
2023-01-11 02:34:32 +00:00
|
|
|
quadvert_t *verts = QFV_PacketExtend (packet, glyph_data->buffer.size);
|
2022-10-03 01:29:49 +00:00
|
|
|
for (FT_Long i = 0; i < rfont->num_glyphs; i++) {
|
2022-10-20 06:50:53 +00:00
|
|
|
vrect_t *rect = &rfont->glyph_rects[i];
|
|
|
|
float x = 0;
|
|
|
|
float y = 0;
|
|
|
|
float w = rect->width;
|
|
|
|
float h = rect->height;
|
|
|
|
float u = rect->x;
|
|
|
|
float v = rect->y;
|
2022-10-03 01:29:49 +00:00
|
|
|
float s = 1.0 / rfont->scrap.width;
|
2022-10-20 06:50:53 +00:00
|
|
|
float t = 1.0 / rfont->scrap.height;
|
2023-01-11 02:34:32 +00:00
|
|
|
verts[i * 4 + 0] = (quadvert_t) {
|
2022-11-19 18:59:01 +00:00
|
|
|
.offset = { x, y },
|
|
|
|
.uv = { u * s, v * t },
|
2022-10-03 01:29:49 +00:00
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
verts[i * 4 + 1] = (quadvert_t) {
|
2022-11-19 18:59:01 +00:00
|
|
|
.offset = { x, y + h },
|
|
|
|
.uv = { u * s, (v + h) * t },
|
2022-10-03 01:29:49 +00:00
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
verts[i * 4 + 2] = (quadvert_t) {
|
2022-11-19 18:59:01 +00:00
|
|
|
.offset = { x + w, y },
|
|
|
|
.uv = {(u + w) * s, v * t },
|
2022-10-03 01:29:49 +00:00
|
|
|
};
|
2023-01-11 02:34:32 +00:00
|
|
|
verts[i * 4 + 3] = (quadvert_t) {
|
2022-10-03 01:29:49 +00:00
|
|
|
.offset = { x + w, y + h },
|
2022-11-19 18:59:01 +00:00
|
|
|
.uv = {(u + w) * s, (v + h) * t },
|
2022-08-31 10:23:30 +00:00
|
|
|
};
|
|
|
|
}
|
2023-01-11 02:32:05 +00:00
|
|
|
QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer, 0,
|
2022-10-03 01:29:49 +00:00
|
|
|
&bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]);
|
|
|
|
QFV_PacketSubmit (packet);
|
|
|
|
|
|
|
|
packet = QFV_PacketAcquire (ctx->staging);
|
|
|
|
byte *texels = QFV_PacketExtend (packet, tex.width * tex.height);
|
|
|
|
memcpy (texels, tex.data, tex.width * tex.height);
|
|
|
|
QFV_PacketCopyImage (packet, glyph_image->image.image,
|
|
|
|
tex.width, tex.height,
|
|
|
|
&imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]);
|
|
|
|
QFV_PacketSubmit (packet);
|
|
|
|
|
|
|
|
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca);
|
2023-01-11 02:34:32 +00:00
|
|
|
layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set");
|
|
|
|
__auto_type pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool");
|
2022-10-03 01:29:49 +00:00
|
|
|
__auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts);
|
|
|
|
font->set = glyph_sets->a[0];
|
|
|
|
VkDescriptorImageInfo imageInfo = {
|
2022-11-19 18:59:01 +00:00
|
|
|
dctx->glyph_sampler,
|
2022-10-03 01:29:49 +00:00
|
|
|
glyph_iview->image_view.view,
|
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
|
|
};
|
|
|
|
VkWriteDescriptorSet write[] = {
|
|
|
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
|
|
|
font->set, 0, 0, 1,
|
|
|
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
&imageInfo, 0, 0 },
|
2023-01-05 04:25:46 +00:00
|
|
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
|
|
|
font->set, 1, 0, 1,
|
|
|
|
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
|
|
|
|
0, 0, &glyph_bview->buffer_view.view },
|
2022-10-03 01:29:49 +00:00
|
|
|
};
|
|
|
|
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
|
|
|
|
free (glyph_sets);
|
2022-10-02 23:58:27 +00:00
|
|
|
|
2022-10-07 07:53:13 +00:00
|
|
|
return fontid;
|
2022-08-31 10:23:30 +00:00
|
|
|
}
|
2022-09-04 11:56:38 +00:00
|
|
|
|
2022-09-02 02:38:09 +00:00
|
|
|
void
|
2022-12-10 09:55:08 +00:00
|
|
|
Vulkan_Draw_Glyph (int x, int y, int fontid, int glyph, int c,
|
2022-10-02 23:58:27 +00:00
|
|
|
vulkan_ctx_t *ctx)
|
2022-09-02 02:38:09 +00:00
|
|
|
{
|
2022-09-02 05:23:19 +00:00
|
|
|
drawctx_t *dctx = ctx->draw_context;
|
2023-01-11 02:34:32 +00:00
|
|
|
drawframe_t *frame = &dctx->frames.a[ctx->curFrame];
|
2022-09-04 11:56:38 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
quadqueue_t *queue = &frame->quad_insts;
|
2022-12-10 09:55:08 +00:00
|
|
|
if (queue->count >= queue->size) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-04 11:56:38 +00:00
|
|
|
|
2023-01-11 02:34:32 +00:00
|
|
|
byte color[4] = { VectorExpand (vid.palette + c * 3), 255 };
|
|
|
|
draw_quad (x, y, fontid, glyph * 4, color, frame);
|
2022-09-02 02:38:09 +00:00
|
|
|
}
|
2022-11-10 12:19:01 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height,
|
|
|
|
vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
static int colors[] = { 0xd0, 0x4f, 0x6f };
|
|
|
|
|
|
|
|
while (count-- > 0) {
|
|
|
|
int h = *h_vals++;
|
|
|
|
int c = h < 9998 || h > 10000 ? 0xfe : colors[h - 9998];
|
|
|
|
h = min (h, height);
|
|
|
|
Vulkan_Draw_Line (x, y, x, y - h, c, ctx);
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
}
|