mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 22:01:33 +00:00
[vullkan] Rework Draw implementation
Line rendering now has its own pipeline (removing the texture issue). Glyph rendering (for fonts) has been reworked to use instanced quad rendering, with the geometry (position and texture coords) in a static buffer (uniform texture buffer), and each instance has a glyph index, color, and 2d base position. Multiple fonts can be loaded, but aren't used yet: still just the one (work needs to be done on the queues to support multiple textures/fonts). Quads haven't changed much, but buffer creation and destruction has been cleaned up to use the resource functions.
This commit is contained in:
parent
c9e7810864
commit
f477f2b96e
9 changed files with 535 additions and 200 deletions
|
@ -275,6 +275,16 @@ vkparse_plist = \
|
|||
|
||||
vkshaderpath = libs/video/renderer/vulkan/shader
|
||||
|
||||
glyph_src = $(vkshaderpath)/glyph.vert
|
||||
glyph_c = $(vkshaderpath)/glyph.vert.spvc
|
||||
glyph_color_src = $(vkshaderpath)/glyph_color.frag
|
||||
glyph_color_c = $(vkshaderpath)/glyph_color.frag.spvc
|
||||
glyph_coverage_src = $(vkshaderpath)/glyph_coverage.frag
|
||||
glyph_coverage_c = $(vkshaderpath)/glyph_coverage.frag.spvc
|
||||
linev_src = $(vkshaderpath)/line.vert
|
||||
linev_c = $(vkshaderpath)/line.vert.spvc
|
||||
linef_src = $(vkshaderpath)/line.frag
|
||||
linef_c = $(vkshaderpath)/line.frag.spvc
|
||||
partphysicsc_src = $(vkshaderpath)/partphysics.comp
|
||||
partphysicsc_c = $(vkshaderpath)/partphysics.comp.spvc
|
||||
partupdatec_src = $(vkshaderpath)/partupdate.comp
|
||||
|
@ -293,8 +303,6 @@ sprite_depthv_src = $(vkshaderpath)/sprite_depth.vert
|
|||
sprite_depthv_c = $(vkshaderpath)/sprite_depth.vert.spvc
|
||||
sprite_depthf_src = $(vkshaderpath)/sprite_depth.frag
|
||||
sprite_depthf_c = $(vkshaderpath)/sprite_depth.frag.spvc
|
||||
twod_impalpha_src = $(vkshaderpath)/twod_impalpha.frag
|
||||
twod_impalpha_c = $(vkshaderpath)/twod_impalpha.frag.spvc
|
||||
twodv_src = $(vkshaderpath)/twod.vert
|
||||
twodv_c = $(vkshaderpath)/twod.vert.spvc
|
||||
twodf_src = $(vkshaderpath)/twod.frag
|
||||
|
@ -343,6 +351,13 @@ fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc
|
|||
pushcolor_src = $(vkshaderpath)/pushcolor.frag
|
||||
pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc
|
||||
|
||||
$(glyph_vert_c): $(glyph_vert_src)
|
||||
$(glyph_color_c): $(glyph_color_src)
|
||||
$(glyph_coverage_c): $(glyph_coverage_src)
|
||||
|
||||
$(linev_c): $(linev_src)
|
||||
$(linef_c): $(linef_src)
|
||||
|
||||
$(partphysicsc_c): $(partphysicsc_src)
|
||||
$(partupdatec_c): $(partupdatec_src)
|
||||
$(particlev_c): $(particlev_src)
|
||||
|
@ -357,8 +372,6 @@ $(sprite_depthv_c): $(sprite_depthv_src)
|
|||
|
||||
$(sprite_depthf_c): $(sprite_depthf_src)
|
||||
|
||||
$(twod_impalpha_c): $(twod_impalpha_src)
|
||||
|
||||
$(twodv_c): $(twodv_src)
|
||||
|
||||
$(twodf_c): $(twodf_src)
|
||||
|
@ -406,6 +419,11 @@ $(fstriangle_c): $(fstriangle_src)
|
|||
$(pushcolor_c): $(pushcolor_src)
|
||||
|
||||
vkshader_c = \
|
||||
$(glyph_c) \
|
||||
$(glyph_color_c) \
|
||||
$(glyph_coverage_c) \
|
||||
$(linev_c) \
|
||||
$(linef_c) \
|
||||
$(partphysicsc_c) \
|
||||
$(partupdatec_c) \
|
||||
$(particlev_c) \
|
||||
|
@ -415,7 +433,6 @@ vkshader_c = \
|
|||
$(sprite_gbuff_c) \
|
||||
$(sprite_depthv_c) \
|
||||
$(sprite_depthf_c) \
|
||||
$(twod_impalpha_c) \
|
||||
$(twodv_c) \
|
||||
$(twodf_c) \
|
||||
$(quakebspv_c) \
|
||||
|
|
|
@ -97,6 +97,21 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
glyph_pool = {
|
||||
maxSets = 16;
|
||||
bindings = (
|
||||
{
|
||||
// glyph geometry data (offset and uv)
|
||||
type = uniform_texel_buffer;
|
||||
descriptorCount = 16;
|
||||
},
|
||||
{
|
||||
// glyph texture data
|
||||
type = combined_image_sampler;
|
||||
descriptorCount = 16;
|
||||
},
|
||||
);
|
||||
};
|
||||
entity_pool = {
|
||||
flags = free_descriptor_set;
|
||||
maxSets = 512;
|
||||
|
@ -216,6 +231,24 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
glyph_data_set = {
|
||||
bindings = (
|
||||
{
|
||||
// glyph geometry data (offset and uv)
|
||||
binding = 0;
|
||||
descriptorType = uniform_texel_buffer;
|
||||
descriptorCount = 1;
|
||||
stageFlags = vertex;
|
||||
},
|
||||
{
|
||||
// glyph texture data
|
||||
binding = 1;
|
||||
descriptorType = combined_image_sampler;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
);
|
||||
};
|
||||
texture_set = {
|
||||
bindings = (
|
||||
{
|
||||
|
@ -359,6 +392,12 @@
|
|||
twod_layout = {
|
||||
setLayouts = (matrix_set, twod_set);
|
||||
};
|
||||
glyph_layout = {
|
||||
setLayouts = (matrix_set, glyph_data_set);
|
||||
};
|
||||
lines_layout = {
|
||||
setLayouts = (matrix_set);
|
||||
};
|
||||
quakebsp_layout = {
|
||||
setLayouts = (matrix_set, entity_set, texture_set, texture_set);
|
||||
pushConstantRanges = (
|
||||
|
@ -526,6 +565,19 @@
|
|||
{ location = 2; binding = 1; format = r32_uint; offset = 0; },
|
||||
);
|
||||
};
|
||||
glyph = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = "4 + 4 + 2 * 4"; inputRate = instance; },
|
||||
);
|
||||
attributes = (
|
||||
// glyph index
|
||||
{ location = 0; binding = 0; format = r32_uint; offset = 0; },
|
||||
// glyph color
|
||||
{ location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; },
|
||||
// glyph position (2d)
|
||||
{ location = 2; binding = 0; format = r32g32_sfloat; offset = 8; },
|
||||
);
|
||||
};
|
||||
iqm = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = 20; inputRate = vertex; },
|
||||
|
@ -1046,24 +1098,44 @@
|
|||
};
|
||||
layout = twod_layout;
|
||||
};
|
||||
twod_impalpha = {
|
||||
@inherit = $properties.pipelines.twod;
|
||||
glyph = {
|
||||
@inherit = $properties.pipelines.trans_base;//FIXME should be sparate
|
||||
vertexInput = $properties.vertexInput.glyph;
|
||||
inputAssembly = {
|
||||
// glyphs are drawn using instanced quads, so primitive restart
|
||||
// is not needed as only four vertices are drawn per instance.
|
||||
topology = triangle_strip;
|
||||
primitiveRestartEnable = false;
|
||||
};
|
||||
rasterization = $properties.rasterization.counter_cw_cull_back;
|
||||
colorBlend = {
|
||||
logicOpEnable = false;
|
||||
attachments = ($properties.attachmentBlendOp.alpha_blend);
|
||||
};
|
||||
layout = glyph_layout;
|
||||
};
|
||||
glyph_color = {
|
||||
@inherit = $properties.pipelines.glyph;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/twod.vert;
|
||||
},
|
||||
{
|
||||
stage = fragment;
|
||||
name = main;
|
||||
module = $builtin/twod_impalpha.frag;
|
||||
},
|
||||
{ stage = vertex; name = main; module = $builtin/glyph.vert; },
|
||||
{ stage = fragment; name = main; module = $builtin/glyph_color.frag; },
|
||||
);
|
||||
};
|
||||
glyph_coverage = {
|
||||
@inherit = $properties.pipelines.glyph;
|
||||
stages = (
|
||||
{ stage = vertex; name = main; module = $builtin/glyph.vert; },
|
||||
{ stage = fragment; name = main; module = $builtin/glyph_coverage.frag; },
|
||||
);
|
||||
};
|
||||
lines = {
|
||||
@inherit = $properties.pipelines.twod;
|
||||
stages = (
|
||||
{ stage = vertex; name = main; module = $builtin/line.vert; },
|
||||
{ stage = fragment; name = main; module = $builtin/line.frag; },
|
||||
);
|
||||
inputAssembly = $properties.inputAssembly.lines;
|
||||
layout = lines_layout;
|
||||
};
|
||||
lighting = {
|
||||
@inherit = $properties.pipelines.comp_base;
|
||||
|
|
|
@ -38,6 +38,16 @@
|
|||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/shader.h"
|
||||
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/glyph.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/glyph_color.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/glyph_coverage.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/line.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/line.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/particle.vert.spvc"
|
||||
static
|
||||
|
@ -57,8 +67,6 @@ static
|
|||
static
|
||||
#include "libs/video/renderer/vulkan/shader/sprite_depth.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/twod_impalpha.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/twod.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/twod.frag.spvc"
|
||||
|
@ -112,6 +120,11 @@ typedef struct shaderdata_s {
|
|||
} shaderdata_t;
|
||||
|
||||
static shaderdata_t builtin_shaders[] = {
|
||||
{ "glyph.vert", glyph_vert, sizeof (glyph_vert) },
|
||||
{ "glyph_color.frag", glyph_color_frag, sizeof (glyph_color_frag) },
|
||||
{ "glyph_coverage.frag", glyph_coverage_frag, sizeof (glyph_coverage_frag) },
|
||||
{ "line.vert", line_vert, sizeof (line_vert) },
|
||||
{ "line.frag", line_frag, sizeof (line_frag) },
|
||||
{ "particle.vert", particle_vert, sizeof (particle_vert) },
|
||||
{ "particle.geom", particle_geom, sizeof (particle_geom) },
|
||||
{ "particle.frag", particle_frag, sizeof (particle_frag) },
|
||||
|
@ -121,7 +134,6 @@ static shaderdata_t builtin_shaders[] = {
|
|||
{ "sprite_gbuf.frag", sprite_gbuf_frag, sizeof (sprite_gbuf_frag) },
|
||||
{ "sprite_depth.vert", sprite_depth_vert, sizeof (sprite_depth_vert) },
|
||||
{ "sprite_depth.frag", sprite_depth_frag, sizeof (sprite_depth_frag) },
|
||||
{ "twod_impalpha.frag", twod_impalpha_frag, sizeof (twod_impalpha_frag) },
|
||||
{ "twod.vert", twod_vert, sizeof (twod_vert) },
|
||||
{ "twod.frag", twod_frag, sizeof (twod_frag) },
|
||||
{ "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) },
|
||||
|
|
32
libs/video/renderer/vulkan/shader/glyph.vert
Normal file
32
libs/video/renderer/vulkan/shader/glyph.vert
Normal file
|
@ -0,0 +1,32 @@
|
|||
#version 450
|
||||
|
||||
layout (set = 0, binding = 0) uniform Matrices {
|
||||
mat4 Projection3d;
|
||||
mat4 View;
|
||||
mat4 Sky;
|
||||
mat4 Projection2d;
|
||||
};
|
||||
layout (set = 1, binding = 0) uniform textureBuffer glyph_data;
|
||||
|
||||
// per instance data
|
||||
layout (location = 0) in uint glyph_index;
|
||||
layout (location = 1) in vec4 glyph_color;
|
||||
layout (location = 2) in vec2 glyph_position;
|
||||
|
||||
// rg -> offset x,y
|
||||
// ba -> texture u,v
|
||||
|
||||
layout (location = 0) out vec2 uv;
|
||||
layout (location = 1) out vec4 color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
vec4 glyph = texelFetch (glyph_data, int(glyph_index) * 4 + gl_VertexIndex);
|
||||
// offset stored in glyph components 0 and 1
|
||||
vec2 position = glyph_position + glyph.xy;
|
||||
gl_Position = Projection2d * vec4 (position.xy, 0.0, 1.0);
|
||||
// texture uv stored in glyph components 2 and 3
|
||||
uv = glyph.pq;
|
||||
color = glyph_color;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#version 450
|
||||
|
||||
layout (set = 1, binding = 0) uniform sampler2D Texture;
|
||||
layout (set = 1, binding = 1) uniform sampler2D Texture;
|
||||
|
||||
layout (location = 0) in vec2 st;
|
||||
layout (location = 0) in vec2 uv;
|
||||
layout (location = 1) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
@ -12,6 +12,6 @@ main (void)
|
|||
{
|
||||
vec4 pix;
|
||||
|
||||
pix = texture(Texture, st).rrrr;
|
||||
pix = texture (Texture, uv);
|
||||
frag_color = pix * color;
|
||||
}
|
17
libs/video/renderer/vulkan/shader/glyph_coverage.frag
Normal file
17
libs/video/renderer/vulkan/shader/glyph_coverage.frag
Normal file
|
@ -0,0 +1,17 @@
|
|||
#version 450
|
||||
|
||||
layout (set = 1, binding = 1) uniform sampler2D Texture;
|
||||
|
||||
layout (location = 0) in vec2 uv;
|
||||
layout (location = 1) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
vec4 pix;
|
||||
|
||||
pix = texture (Texture, uv).rrrr;
|
||||
frag_color = pix * color;
|
||||
}
|
11
libs/video/renderer/vulkan/shader/line.frag
Normal file
11
libs/video/renderer/vulkan/shader/line.frag
Normal file
|
@ -0,0 +1,11 @@
|
|||
#version 450
|
||||
|
||||
layout (location = 0) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
frag_color = color;
|
||||
}
|
20
libs/video/renderer/vulkan/shader/line.vert
Normal file
20
libs/video/renderer/vulkan/shader/line.vert
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 450
|
||||
|
||||
layout (set = 0, binding = 0) uniform Matrices {
|
||||
mat4 Projection3d;
|
||||
mat4 View;
|
||||
mat4 Sky;
|
||||
mat4 Projection2d;
|
||||
};
|
||||
layout (location = 0) in vec2 vertex;
|
||||
layout (location = 1) in vec2 uv;
|
||||
layout (location = 2) in vec4 vcolor;
|
||||
|
||||
layout (location = 0) out vec4 color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
gl_Position = Projection2d * vec4 (vertex.xy, 0.0, 1.0);
|
||||
color = vcolor;
|
||||
}
|
|
@ -63,6 +63,7 @@
|
|||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/resource.h"
|
||||
#include "QF/Vulkan/scrap.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
#include "QF/ui/view.h"
|
||||
|
@ -78,6 +79,17 @@ typedef struct {
|
|||
float color[4];
|
||||
} drawvert_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t index;
|
||||
byte color[4];
|
||||
float position[2];
|
||||
} glyphinst_t;
|
||||
|
||||
typedef struct {
|
||||
float offset[2];
|
||||
float uv[2];
|
||||
} glyphvert_t;
|
||||
|
||||
typedef struct cachepic_s {
|
||||
char *name;
|
||||
qpic_t *pic;
|
||||
|
@ -89,26 +101,48 @@ typedef struct vertqueue_s {
|
|||
int size;
|
||||
} vertqueue_t;
|
||||
|
||||
typedef struct glyphqueue_s {
|
||||
glyphinst_t *glyphs;
|
||||
int count;
|
||||
int size;
|
||||
} glyphqueue_t;
|
||||
|
||||
typedef struct drawframe_s {
|
||||
size_t vert_offset;
|
||||
size_t iavert_offset;
|
||||
size_t quad_offset;
|
||||
size_t glyph_offset;
|
||||
size_t line_offset;
|
||||
VkBuffer quad_buffer;
|
||||
VkBuffer glyph_buffer;
|
||||
VkBuffer line_buffer;
|
||||
vertqueue_t quad_verts;
|
||||
vertqueue_t iaquad_verts;
|
||||
glyphqueue_t glyph_insts;
|
||||
vertqueue_t line_verts;
|
||||
VkCommandBuffer cmd;
|
||||
VkDescriptorSet descriptors;
|
||||
VkDescriptorSet iadescriptors;
|
||||
} drawframe_t;
|
||||
|
||||
typedef struct drawframeset_s
|
||||
DARRAY_TYPE (drawframe_t) drawframeset_t;
|
||||
|
||||
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;
|
||||
rfont_t *font;
|
||||
} drawfont_t;
|
||||
|
||||
typedef struct drawfontset_s
|
||||
DARRAY_TYPE (drawfont_t) drawfontset_t;
|
||||
|
||||
typedef struct drawctx_s {
|
||||
VkSampler sampler;
|
||||
scrap_t *scrap;
|
||||
rfont_t *font;
|
||||
qfv_tex_t *font_tex;
|
||||
qfv_stagebuf_t *stage;
|
||||
qpic_t *crosshair;
|
||||
qpic_t *conchars;
|
||||
|
@ -120,15 +154,18 @@ typedef struct drawctx_s {
|
|||
memsuper_t *pic_memsuper;
|
||||
memsuper_t *string_memsuper;
|
||||
hashtab_t *pic_cache;
|
||||
VkBuffer vert_buffer;
|
||||
VkDeviceMemory vert_memory;
|
||||
VkBuffer ind_buffer;
|
||||
VkDeviceMemory ind_memory;
|
||||
qfv_resource_t *draw_resource;
|
||||
qfv_resobj_t *quad_objects;
|
||||
qfv_resobj_t *glyph_objects;
|
||||
qfv_resobj_t *line_objects;
|
||||
VkPipeline quad_pipeline;
|
||||
VkPipeline iaquad_pipeline;
|
||||
VkPipeline glyph_coverage_pipeline;
|
||||
VkPipeline line_pipeline;
|
||||
VkPipelineLayout layout;
|
||||
VkPipelineLayout glyph_layout;
|
||||
VkDescriptorSet quad_set;
|
||||
drawframeset_t frames;
|
||||
drawfontset_t fonts;
|
||||
} drawctx_t;
|
||||
|
||||
// enough for a full screen of 8x8 chars at 1920x1080 plus some extras (368)
|
||||
|
@ -136,6 +173,8 @@ typedef struct drawctx_s {
|
|||
#define VERTS_PER_QUAD (4)
|
||||
#define INDS_PER_QUAD (5) // one per vert plus primitive reset
|
||||
|
||||
#define MAX_GLYPHS (32768)
|
||||
|
||||
#define MAX_LINES (32768)
|
||||
#define VERTS_PER_LINE (2)
|
||||
|
||||
|
@ -150,66 +189,108 @@ create_quad_buffers (vulkan_ctx_t *ctx)
|
|||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
|
||||
size_t vert_size;
|
||||
size_t ind_size;
|
||||
size_t frames = ctx->frames.size;
|
||||
VkBuffer vbuf, ibuf;
|
||||
VkDeviceMemory vmem, imem;
|
||||
|
||||
vert_size = frames * VERTS_PER_FRAME * sizeof (drawvert_t);
|
||||
ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t);
|
||||
dctx->draw_resource = malloc (2 * sizeof (qfv_resource_t)
|
||||
// quads: index + frames vertex buffers
|
||||
+ (1 + frames) * sizeof (qfv_resobj_t)
|
||||
// glyphs: frames instance vertex buffers
|
||||
+ (frames) * sizeof (qfv_resobj_t)
|
||||
// lines: frames vertex buffers
|
||||
+ (frames) * sizeof (qfv_resobj_t));
|
||||
dctx->quad_objects = (qfv_resobj_t *) &dctx->draw_resource[2];
|
||||
dctx->glyph_objects = &dctx->quad_objects[1 + frames];
|
||||
dctx->line_objects = &dctx->glyph_objects[frames];
|
||||
|
||||
vbuf = QFV_CreateBuffer (device, vert_size,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
ibuf = QFV_CreateBuffer (device, ind_size,
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
vmem = QFV_AllocBufferMemory (device, vbuf,
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
vert_size, 0);
|
||||
imem = QFV_AllocBufferMemory (device, ibuf,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
ind_size, 0);
|
||||
QFV_BindBufferMemory (device, vbuf, vmem, 0);
|
||||
QFV_BindBufferMemory (device, ibuf, imem, 0);
|
||||
dctx->draw_resource[0] = (qfv_resource_t) {
|
||||
.name = "draw",
|
||||
.va_ctx = ctx->va_ctx,
|
||||
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
.num_objects = 1, // has only the quad index buffer
|
||||
.objects = dctx->quad_objects,
|
||||
};
|
||||
dctx->draw_resource[1] = (qfv_resource_t) {
|
||||
.name = "draw",
|
||||
.va_ctx = ctx->va_ctx,
|
||||
.memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
.num_objects = (frames) + (frames) + (frames),
|
||||
.objects = dctx->quad_objects + 1,
|
||||
};
|
||||
|
||||
dctx->vert_buffer = vbuf;
|
||||
dctx->vert_memory = vmem;
|
||||
dctx->ind_buffer = ibuf;
|
||||
dctx->ind_memory = imem;
|
||||
dctx->quad_objects[0] = (qfv_resobj_t) {
|
||||
.name = "quads.index",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
__auto_type ind_buffer = &dctx->quad_objects[0];
|
||||
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
dctx->quad_objects[i + 1] = (qfv_resobj_t) {
|
||||
.name = "quads.geom",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
dctx->glyph_objects[i] = (qfv_resobj_t) {
|
||||
.name = "glyphs.inst",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = MAX_GLYPHS * sizeof (glyphinst_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
dctx->line_objects[i] = (qfv_resobj_t) {
|
||||
.name = "lines.geom",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = MAX_LINES * VERTS_PER_LINE * sizeof (drawvert_t),
|
||||
.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]);
|
||||
|
||||
void *data;
|
||||
dfunc->vkMapMemory (device->dev, vmem, 0, vert_size, 0, &data);
|
||||
drawvert_t *vert_data = data;
|
||||
VkDeviceMemory memory = dctx->draw_resource[1].memory;
|
||||
dfunc->vkMapMemory (device->dev, memory, 0, VK_WHOLE_SIZE, 0, &data);
|
||||
|
||||
for (size_t f = 0; f < frames; f++) {
|
||||
drawframe_t *frame = &dctx->frames.a[f];
|
||||
size_t ind = f * VERTS_PER_FRAME;
|
||||
size_t iaind = ind + IAQUADS_OFFSET;
|
||||
size_t lind = ind + LINES_OFFSET;
|
||||
frame->vert_offset = ind * sizeof (drawvert_t);
|
||||
frame->iavert_offset = iaind;
|
||||
frame->line_offset = lind;
|
||||
frame->quad_buffer = dctx->quad_objects[1 + f].buffer.buffer;
|
||||
frame->quad_offset = dctx->quad_objects[1 + f].buffer.offset;
|
||||
frame->glyph_buffer = dctx->glyph_objects[f].buffer.buffer;
|
||||
frame->glyph_offset = dctx->glyph_objects[f].buffer.offset;
|
||||
frame->line_buffer = dctx->line_objects[f].buffer.buffer;
|
||||
frame->line_offset = dctx->line_objects[f].buffer.offset;
|
||||
|
||||
frame->quad_verts = (vertqueue_t) {
|
||||
.verts = vert_data + ind,
|
||||
.verts = (drawvert_t *) ((byte *)data + frame->quad_offset),
|
||||
.size = MAX_QUADS,
|
||||
};
|
||||
frame->iaquad_verts = (vertqueue_t) {
|
||||
.verts = frame->quad_verts.verts + IAQUADS_OFFSET,
|
||||
frame->glyph_insts = (glyphqueue_t) {
|
||||
.glyphs = (glyphinst_t *) ((byte *)data + frame->glyph_offset),
|
||||
.size = MAX_QUADS,
|
||||
};
|
||||
frame->line_verts = (vertqueue_t) {
|
||||
.verts = frame->quad_verts.verts + LINES_OFFSET,
|
||||
.size = MAX_LINES,
|
||||
.verts = (drawvert_t *) ((byte *)data + frame->line_offset),
|
||||
.size = MAX_QUADS,
|
||||
};
|
||||
}
|
||||
|
||||
// The indices will never change so pre-generate and stash them
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
||||
uint32_t *ind = QFV_PacketExtend (packet, ind_size);
|
||||
uint32_t *ind = QFV_PacketExtend (packet, ind_buffer->buffer.size);
|
||||
for (int i = 0; i < MAX_QUADS; i++) {
|
||||
for (int j = 0; j < VERTS_PER_QUAD; j++) {
|
||||
*ind++ = i * VERTS_PER_QUAD + j;
|
||||
|
@ -217,37 +298,11 @@ create_quad_buffers (vulkan_ctx_t *ctx)
|
|||
// mark end of primitive
|
||||
*ind++ = -1;
|
||||
}
|
||||
|
||||
qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite];
|
||||
bb.barrier.buffer = ibuf;
|
||||
bb.barrier.size = ind_size;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages,
|
||||
0, 0, 0, 1, &bb.barrier, 0, 0);
|
||||
VkBufferCopy copy_region = { packet->offset, 0, ind_size };
|
||||
dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, ibuf,
|
||||
1, ©_region);
|
||||
bb = bufferBarriers[qfv_BB_TransferWrite_to_IndexRead];
|
||||
bb.barrier.buffer = ibuf;
|
||||
bb.barrier.size = ind_size;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages,
|
||||
0, 0, 0, 1, &bb.barrier, 0, 0);
|
||||
QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer,
|
||||
&bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]);
|
||||
QFV_PacketSubmit (packet);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_quad_buffers (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
|
||||
dfunc->vkUnmapMemory (device->dev, dctx->vert_memory);
|
||||
dfunc->vkFreeMemory (device->dev, dctx->vert_memory, 0);
|
||||
dfunc->vkFreeMemory (device->dev, dctx->ind_memory, 0);
|
||||
dfunc->vkDestroyBuffer (device->dev, dctx->vert_buffer, 0);
|
||||
dfunc->vkDestroyBuffer (device->dev, dctx->ind_buffer, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
flush_draw_scrap (vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -387,19 +442,21 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx)
|
|||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
|
||||
destroy_quad_buffers (ctx);
|
||||
QFV_DestroyResource (device, &dctx->draw_resource[0]);
|
||||
QFV_DestroyResource (device, &dctx->draw_resource[1]);
|
||||
for (size_t i = 0; i < dctx->fonts.size; i++) {
|
||||
QFV_DestroyResource (device, &dctx->fonts.a[i].resource->resource);
|
||||
free (dctx->fonts.a[i].resource);
|
||||
}
|
||||
|
||||
dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, dctx->iaquad_pipeline, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, dctx->glyph_coverage_pipeline, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0);
|
||||
Hash_DelTable (dctx->pic_cache);
|
||||
delete_memsuper (dctx->pic_memsuper);
|
||||
delete_memsuper (dctx->string_memsuper);
|
||||
QFV_DestroyScrap (dctx->scrap);
|
||||
QFV_DestroyStagingBuffer (dctx->stage);
|
||||
if (dctx->font_tex) {
|
||||
Vulkan_UnloadTex (ctx, dctx->font_tex);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -417,6 +474,10 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
|
|||
DARRAY_INIT (&dctx->frames, frames);
|
||||
DARRAY_RESIZE (&dctx->frames, frames);
|
||||
dctx->frames.grow = 0;
|
||||
DARRAY_INIT (&dctx->fonts, 16);
|
||||
DARRAY_RESIZE (&dctx->fonts, 16);
|
||||
dctx->fonts.grow = 0;
|
||||
dctx->fonts.size = 0;
|
||||
|
||||
dctx->pic_memsuper = new_memsuper ();
|
||||
dctx->string_memsuper = new_memsuper ();
|
||||
|
@ -457,16 +518,15 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
|
|||
flush_draw_scrap (ctx);
|
||||
|
||||
dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod");
|
||||
dctx->iaquad_pipeline = Vulkan_CreateGraphicsPipeline (ctx,
|
||||
"twod_impalpha");
|
||||
dctx->glyph_coverage_pipeline
|
||||
= Vulkan_CreateGraphicsPipeline (ctx, "glyph_coverage");
|
||||
dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines");
|
||||
|
||||
dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout");
|
||||
dctx->glyph_layout = Vulkan_CreatePipelineLayout (ctx, "glyph_layout");
|
||||
|
||||
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
|
||||
for (size_t i = 0; i < layouts->size; i++) {
|
||||
layouts->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "twod_set");
|
||||
}
|
||||
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca);
|
||||
layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "twod_set");
|
||||
__auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool");
|
||||
|
||||
VkDescriptorImageInfo imageInfo = {
|
||||
|
@ -474,38 +534,27 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
|
|||
QFV_ScrapImageView (dctx->scrap),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
VkDescriptorImageInfo iaimageInfo = {
|
||||
dctx->sampler,
|
||||
Vulkan_TexImageView (ctx->default_magenta),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
__auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca);
|
||||
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers);
|
||||
|
||||
__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts);
|
||||
__auto_type iasets = QFV_AllocateDescriptorSet (device, pool, layouts);
|
||||
dctx->quad_set = sets->a[0];
|
||||
VkWriteDescriptorSet write[] = {
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
dctx->quad_set, 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
&imageInfo, 0, 0 },
|
||||
};
|
||||
free (sets);
|
||||
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
__auto_type dframe = &dctx->frames.a[i];
|
||||
dframe->descriptors = sets->a[i];
|
||||
dframe->iadescriptors = iasets->a[i];
|
||||
|
||||
VkWriteDescriptorSet write[] = {
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
dframe->descriptors, 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
&imageInfo, 0, 0 },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
dframe->iadescriptors, 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
&iaimageInfo, 0, 0 },
|
||||
};
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
|
||||
dframe->cmd = cmdBuffers->a[i];
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
||||
dframe->cmd,
|
||||
va (ctx->va_ctx, "cmd:draw:%zd", i));
|
||||
}
|
||||
free (sets);
|
||||
qfvPopDebug (ctx);
|
||||
}
|
||||
|
||||
|
@ -948,7 +997,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame)
|
|||
drawctx_t *dctx = ctx->draw_context;
|
||||
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
if (!dframe->quad_verts.count && !dframe->iaquad_verts.count
|
||||
if (!dframe->quad_verts.count && !dframe->glyph_insts.count
|
||||
&& !dframe->line_verts.count) {
|
||||
return;
|
||||
}
|
||||
|
@ -957,18 +1006,19 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame)
|
|||
//FIXME which pass?
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd);
|
||||
|
||||
VkDeviceMemory memory = dctx->draw_resource[1].memory;
|
||||
VkMappedMemoryRange ranges[] = {
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
dctx->vert_memory, dframe->vert_offset,
|
||||
memory, dframe->quad_offset,
|
||||
dframe->quad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t) },
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
dctx->vert_memory, dframe->iavert_offset,
|
||||
dframe->iaquad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t) },
|
||||
memory, dframe->glyph_offset,
|
||||
dframe->glyph_insts.count * VERTS_PER_QUAD * sizeof (drawvert_t) },
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
dctx->vert_memory, dframe->line_offset,
|
||||
memory, dframe->line_offset,
|
||||
dframe->line_verts.count * VERTS_PER_LINE * sizeof (drawvert_t) },
|
||||
};
|
||||
dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges);
|
||||
dfunc->vkFlushMappedMemoryRanges (device->dev, 3, ranges);
|
||||
|
||||
dfunc->vkResetCommandBuffer (cmd, 0);
|
||||
VkCommandBufferInheritanceInfo inherit = {
|
||||
|
@ -986,14 +1036,15 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame)
|
|||
|
||||
QFV_duCmdBeginLabel (device, cmd, "twod", { 0.6, 0.2, 0, 1});
|
||||
|
||||
VkDeviceSize offsets[] = {dframe->vert_offset};
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets);
|
||||
dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0,
|
||||
VK_INDEX_TYPE_UINT32);
|
||||
if (dframe->quad_verts.count) {
|
||||
VkBuffer quad_buffer = dframe->quad_buffer;
|
||||
VkBuffer ind_buffer = dctx->quad_objects[0].buffer.buffer;
|
||||
VkDeviceSize offsets[] = {0};
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_buffer, offsets);
|
||||
dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
VkDescriptorSet set[2] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
dframe->descriptors,
|
||||
dctx->quad_set,
|
||||
};
|
||||
VkPipelineLayout layout = dctx->layout;
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
|
@ -1004,58 +1055,50 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame)
|
|||
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
|
||||
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
|
||||
dfunc->vkCmdDrawIndexed (cmd, dframe->quad_verts.count * INDS_PER_QUAD,
|
||||
1, 0, QUADS_OFFSET, 0);
|
||||
1, 0, 0, 0);
|
||||
}
|
||||
if (dframe->iaquad_verts.count) {
|
||||
VkDescriptorImageInfo iaimageInfo = {
|
||||
dctx->sampler,
|
||||
Vulkan_TexImageView (dctx->font_tex),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
VkWriteDescriptorSet write[] = {
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
dframe->iadescriptors, 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
&iaimageInfo, 0, 0 },
|
||||
};
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
|
||||
|
||||
if (dframe->glyph_insts.count) {
|
||||
VkBuffer glyph_buffer = dframe->glyph_buffer;
|
||||
VkDeviceSize offsets[] = {0};
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &glyph_buffer, offsets);
|
||||
VkDescriptorSet set[2] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
dframe->iadescriptors,
|
||||
dctx->fonts.a[0].set,
|
||||
};
|
||||
VkPipelineLayout layout = dctx->layout;
|
||||
VkPipelineLayout layout = dctx->glyph_layout;
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 2, set, 0, 0);
|
||||
|
||||
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
dctx->iaquad_pipeline);
|
||||
dctx->glyph_coverage_pipeline);
|
||||
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
|
||||
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
|
||||
dfunc->vkCmdDrawIndexed (cmd, dframe->iaquad_verts.count*INDS_PER_QUAD,
|
||||
1, 0, IAQUADS_OFFSET, 0);
|
||||
dfunc->vkCmdDraw (cmd, 4, dframe->glyph_insts.count, 0, 0);
|
||||
}
|
||||
|
||||
if (dframe->line_verts.count) {
|
||||
VkDescriptorSet set[2] = {
|
||||
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),
|
||||
dframe->descriptors,
|
||||
};
|
||||
VkPipelineLayout layout = dctx->layout;
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 2, set, 0, 0);
|
||||
layout, 0, 1, set, 0, 0);
|
||||
|
||||
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
dctx->line_pipeline);
|
||||
dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE,
|
||||
1, LINES_OFFSET, 0);
|
||||
1, 0, 0);
|
||||
}
|
||||
|
||||
QFV_duCmdEndLabel (device, cmd);
|
||||
dfunc->vkEndCommandBuffer (cmd);
|
||||
|
||||
dframe->quad_verts.count = 0;
|
||||
dframe->iaquad_verts.count = 0;
|
||||
dframe->glyph_insts.count = 0;
|
||||
dframe->line_verts.count = 0;
|
||||
}
|
||||
|
||||
|
@ -1075,45 +1118,161 @@ Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx)
|
|||
}
|
||||
|
||||
int
|
||||
Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx)
|
||||
Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
int fontid = dctx->fonts.size;
|
||||
DARRAY_OPEN_AT (&dctx->fonts, fontid, 1);
|
||||
drawfont_t *font = &dctx->fonts.a[fontid];
|
||||
|
||||
if (dctx->font_tex) {
|
||||
Vulkan_UnloadTex (ctx, dctx->font_tex);
|
||||
dctx->font_tex = 0;
|
||||
}
|
||||
dctx->font = font;
|
||||
if (dctx->font) {
|
||||
tex_t tex = {
|
||||
.width = font->scrap.width,
|
||||
.height = font->scrap.height,
|
||||
.format = tex_l,
|
||||
.loaded = 1,
|
||||
.data = font->scrap_bitmap,
|
||||
font->font = rfont;
|
||||
|
||||
font->resource = malloc (sizeof (drawfontres_t));
|
||||
font->resource->resource = (qfv_resource_t) {
|
||||
.name = "glyph_data", //FIXME include font info
|
||||
.va_ctx = ctx->va_ctx,
|
||||
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
.num_objects = 4,
|
||||
.objects = &font->resource->glyph_data,
|
||||
};
|
||||
|
||||
font->resource->glyph_data = (qfv_resobj_t) {
|
||||
.name = "geom",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = rfont->num_glyphs * 4 * sizeof (glyphvert_t),
|
||||
.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,
|
||||
.format = tex_l,
|
||||
.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,
|
||||
},
|
||||
};
|
||||
__auto_type glyph_iview = &font->resource->glyph_iview;
|
||||
|
||||
QFV_CreateResource (ctx->device, &font->resource->resource);
|
||||
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
||||
glyphvert_t *verts = QFV_PacketExtend (packet, glyph_data->buffer.size);
|
||||
for (FT_Long i = 0; i < rfont->num_glyphs; i++) {
|
||||
rglyph_t *glyph = &rfont->glyphs[i];
|
||||
float x = 0;//glyph->bearing[0];
|
||||
float y = 0;//-glyph->bearing[1]; // glyph +Y goes up
|
||||
float w = glyph->rect->width;
|
||||
float h = glyph->rect->height;
|
||||
float u = glyph->rect->x;
|
||||
float v = glyph->rect->y;
|
||||
// assumes the glyph image is square
|
||||
float s = 1.0 / rfont->scrap.width;
|
||||
verts[i * 4 + 0] = (glyphvert_t) {
|
||||
.offset = { x + 0, y + 0 },
|
||||
.uv = {(u + 0.25) * s, (v + 0.25) * s },
|
||||
};
|
||||
verts[i * 4 + 1] = (glyphvert_t) {
|
||||
.offset = { x + 0, y + h },
|
||||
.uv = {(u + 0.25) * s, (v + h - 0.25) * s },
|
||||
};
|
||||
verts[i * 4 + 2] = (glyphvert_t) {
|
||||
.offset = { x + w, y + 0 },
|
||||
.uv = {(u + w - 0.25) * s, (v + 0.25) * s },
|
||||
};
|
||||
verts[i * 4 + 3] = (glyphvert_t) {
|
||||
.offset = { x + w, y + h },
|
||||
.uv = {(u + w - 0.25) * s, (v + h - 0.25) * s },
|
||||
};
|
||||
dctx->font_tex = Vulkan_LoadTex (ctx, &tex, 0, "draw.font");
|
||||
}
|
||||
QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer,
|
||||
&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);
|
||||
layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "glyph_data_set");
|
||||
__auto_type pool = Vulkan_CreateDescriptorPool (ctx, "glyph_pool");
|
||||
__auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts);
|
||||
font->set = glyph_sets->a[0];
|
||||
VkDescriptorImageInfo imageInfo = {
|
||||
dctx->sampler,
|
||||
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_UNIFORM_TEXEL_BUFFER,
|
||||
0, 0, &glyph_bview->buffer_view.view },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
font->set, 1, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
&imageInfo, 0, 0 },
|
||||
};
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
|
||||
free (glyph_sets);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
drawframe_t *dframe;
|
||||
subpic_t *subpic;
|
||||
quat_t color;
|
||||
drawframe_t *dframe;
|
||||
drawfont_t *font;
|
||||
byte color[4];
|
||||
} rgctx_t;
|
||||
|
||||
static void
|
||||
vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx)
|
||||
{
|
||||
rgctx_t *rgctx = _rgctx;
|
||||
glyphqueue_t *queue = &rgctx->dframe->glyph_insts;;
|
||||
|
||||
*((vrect_t **) &rgctx->subpic->rect) = glyph->rect;
|
||||
int gw = glyph->rect->width;
|
||||
int gh = glyph->rect->height;
|
||||
draw_pic (x, y, gw, gh, rgctx->subpic, 0, 0, gw, gh, rgctx->color,
|
||||
&rgctx->dframe->iaquad_verts);
|
||||
if (queue->count >= queue->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
glyphinst_t *inst = &queue->glyphs[queue->count++];
|
||||
inst->index = glyph->charcode;
|
||||
QuatCopy (rgctx->color, inst->color);
|
||||
inst->position[0] = x;
|
||||
inst->position[1] = y;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1121,21 +1280,16 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str,
|
|||
vulkan_ctx_t *ctx)
|
||||
{
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
if (!dctx->font) {
|
||||
if (fontid < 0 || (unsigned) fontid > dctx->fonts.size) {
|
||||
return;
|
||||
}
|
||||
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
//FIXME ewwwwwww
|
||||
subpic_t glyph_subpic = {
|
||||
.width = dctx->font->scrap.width,
|
||||
.height = dctx->font->scrap.height,
|
||||
.size = 1.0 / dctx->font->scrap.width,
|
||||
};
|
||||
rgctx_t rgctx = {
|
||||
.dframe = dframe,
|
||||
.subpic = &glyph_subpic,
|
||||
.color = { 0.5, 1, 0.6, 1 },
|
||||
.font = &dctx->fonts.a[fontid],
|
||||
.color = { 127, 255, 153, 255 },
|
||||
};
|
||||
rtext_t text = {
|
||||
.text = str,
|
||||
|
@ -1144,7 +1298,7 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str,
|
|||
.direction = HB_DIRECTION_LTR,
|
||||
};
|
||||
|
||||
rshaper_t *shaper = RText_NewShaper (dctx->font);
|
||||
rshaper_t *shaper = RText_NewShaper (rgctx.font->font);
|
||||
RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx);
|
||||
RText_DeleteShaper (shaper);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue