mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[vulkan] Implement the sprite render passes
It turned out the bindless approach wouldn't work too well for my design of the sprite objects, but I don't think that's a big issue at this stage (and it seems bindless is causing problems for brush/alias rendering via renderdoc and on my versa pro). However, I have figured out how to make effective use of descriptor sets (finally :P). The actual normal still needs checking, but the sprites are currently unlit so not an issue at this stage.
This commit is contained in:
parent
dafe591446
commit
c366b1b7bb
12 changed files with 412 additions and 30 deletions
|
@ -47,6 +47,7 @@ typedef struct qfv_sprite_s {
|
|||
VkBuffer verts;
|
||||
VkImage image;
|
||||
VkImageView view;
|
||||
VkDescriptorSet descriptors;
|
||||
} qfv_sprite_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -64,20 +65,15 @@ typedef struct spriteframe_s {
|
|||
typedef struct spriteframeset_s
|
||||
DARRAY_TYPE (spriteframe_t) spriteframeset_t;
|
||||
|
||||
typedef struct spriteindset_s
|
||||
DARRAY_TYPE (unsigned) spriteindset_t;
|
||||
|
||||
typedef struct spritectx_s {
|
||||
spriteframeset_t frames;
|
||||
VkPipeline depth;
|
||||
VkPipeline gbuf;
|
||||
VkDescriptorSet descriptors;
|
||||
VkDescriptorPool pool;
|
||||
VkDescriptorSetLayout setLayout;
|
||||
VkPipelineLayout layout;
|
||||
unsigned maxImages;
|
||||
VkSampler sampler;
|
||||
spriteindset_t texindices;
|
||||
} spritectx_t;
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
|
@ -85,6 +81,8 @@ struct qfv_renderframe_s;
|
|||
struct entity_s;
|
||||
struct mod_sprite_ctx_s;
|
||||
|
||||
void Vulkan_Sprite_DescriptorSet (struct vulkan_ctx_s *ctx,
|
||||
qfv_sprite_t *sprite);
|
||||
void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef struct vulkan_ctx_s {
|
|||
struct matrixctx_s *matrix_context;
|
||||
struct aliasctx_s *alias_context;
|
||||
struct bspctx_s *bsp_context;
|
||||
struct spritectx_s *sprite_context;
|
||||
struct drawctx_s *draw_context;
|
||||
struct lightingctx_s *lighting_context;
|
||||
struct composectx_s *compose_context;
|
||||
|
|
|
@ -102,7 +102,7 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx)
|
|||
int numverts = 4 * sprite_ctx->numframes;
|
||||
sprite->verts = QFV_CreateBuffer (device, numverts * sizeof (spritevrt_t),
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
| VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, sprite->verts,
|
||||
va (ctx->va_ctx, "buffer:sprite:vertex:%s",
|
||||
mod->name));
|
||||
|
@ -149,10 +149,11 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx)
|
|||
Mod_LoadSpriteFrame (&f, dframe);
|
||||
verts[i * 4 + 0] = (spritevrt_t) { f.left, f.up, 0, 0 };
|
||||
verts[i * 4 + 1] = (spritevrt_t) { f.right, f.up, 1, 0 };
|
||||
verts[i * 4 + 2] = (spritevrt_t) { f.right, f.down, 1, 1 };
|
||||
verts[i * 4 + 3] = (spritevrt_t) { f.left, f.down, 0, 1 };
|
||||
verts[i * 4 + 2] = (spritevrt_t) { f.left, f.down, 0, 1 };
|
||||
verts[i * 4 + 3] = (spritevrt_t) { f.right, f.down, 1, 1 };
|
||||
Vulkan_ExpandPalette (pixels + i * texsize, (const byte *)(dframe + 1),
|
||||
vid.palette32, 2, texsize / 4);
|
||||
*sprite_ctx->frames[i] = (mspriteframe_t *) (ptrdiff_t) i;
|
||||
}
|
||||
|
||||
qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite];
|
||||
|
@ -195,6 +196,8 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx)
|
|||
QFV_PacketSubmit (packet);
|
||||
QFV_DestroyStagingBuffer (stage);
|
||||
|
||||
Vulkan_Sprite_DescriptorSet (ctx, sprite);
|
||||
|
||||
sprite_ctx->sprite->data = (byte *) sprite - (byte *) sprite_ctx->sprite;
|
||||
|
||||
qfvPopDebug (ctx);
|
||||
|
|
|
@ -267,6 +267,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
|
|||
libs/video/renderer/vulkan/vulkan_main.c \
|
||||
libs/video/renderer/vulkan/vulkan_matrices.c \
|
||||
libs/video/renderer/vulkan/vulkan_particles.c \
|
||||
libs/video/renderer/vulkan/vulkan_sprite.c \
|
||||
libs/video/renderer/vulkan/vulkan_texture.c \
|
||||
libs/video/renderer/vulkan/vulkan_vid_common.c
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ vulkan_R_Init (void)
|
|||
Vulkan_Matrix_Init (vulkan_ctx);
|
||||
Vulkan_Alias_Init (vulkan_ctx);
|
||||
Vulkan_Bsp_Init (vulkan_ctx);
|
||||
Vulkan_Sprite_Init (vulkan_ctx);
|
||||
Vulkan_Draw_Init (vulkan_ctx);
|
||||
Vulkan_Particles_Init (vulkan_ctx);
|
||||
Vulkan_Lighting_Init (vulkan_ctx);
|
||||
|
@ -629,6 +630,7 @@ vulkan_vid_render_shutdown (void)
|
|||
Vulkan_Compose_Shutdown (vulkan_ctx);
|
||||
Vulkan_Lighting_Shutdown (vulkan_ctx);
|
||||
Vulkan_Draw_Shutdown (vulkan_ctx);
|
||||
Vulkan_Sprite_Shutdown (vulkan_ctx);
|
||||
Vulkan_Bsp_Shutdown (vulkan_ctx);
|
||||
Vulkan_Alias_Shutdown (vulkan_ctx);
|
||||
Vulkan_Matrix_Shutdown (vulkan_ctx);
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
borderColor = float_transparent_black;
|
||||
unnormalizedCoordinates = false;
|
||||
};
|
||||
sprite_sampler = $properties.samplers.alias_sampler;
|
||||
shadow_sampler = {
|
||||
magFilter = linear;
|
||||
minFilter = linear;
|
||||
|
@ -111,6 +112,20 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
sprite_pool = {
|
||||
flags = free_descriptor_set;
|
||||
maxSets = 64; //FIXME cvar?
|
||||
bindings = (
|
||||
{
|
||||
type = uniform_buffer;
|
||||
descriptorCount = $properties.descriptorPools.sprite_pool.maxSets;
|
||||
},
|
||||
{
|
||||
type = combined_image_sampler;
|
||||
descriptorCount = $properties.descriptorPools.sprite_pool.maxSets;
|
||||
},
|
||||
);
|
||||
};
|
||||
//FIXME probably should just share a larger pool
|
||||
alias_pool = $properties.descriptorPools.texture_pool;
|
||||
quakebsp_pool = $properties.descriptorPools.texture_pool;
|
||||
|
@ -194,6 +209,22 @@
|
|||
};
|
||||
quakebsp_set = $properties.setLayouts.texture_set;
|
||||
alias_set = $properties.setLayouts.texture_set;
|
||||
sprite_set = {
|
||||
bindings = (
|
||||
{
|
||||
binding = 0;
|
||||
descriptorType = uniform_buffer;
|
||||
descriptorCount = 1;
|
||||
stageFlags = vertex;
|
||||
},
|
||||
{
|
||||
binding = 1;
|
||||
descriptorType = combined_image_sampler;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
);
|
||||
};
|
||||
lighting_attach = {
|
||||
bindings = (
|
||||
{
|
||||
|
@ -300,21 +331,16 @@
|
|||
);
|
||||
};
|
||||
sprite_layout = {
|
||||
setLayouts = (matrix_set, spritevrt_set, texture_set);
|
||||
setLayouts = (matrix_set, sprite_set);
|
||||
pushConstantRanges = (
|
||||
{
|
||||
stageFlags = vertex;
|
||||
offset = 0;
|
||||
size = "16 * 4";
|
||||
},
|
||||
{
|
||||
stageFlags = vertex|fragment;
|
||||
offset = 64;
|
||||
size = "4";
|
||||
size = "16 * 4 + 4";
|
||||
},
|
||||
{
|
||||
stageFlags = fragment;
|
||||
offset = 68;
|
||||
offset = 64;
|
||||
size = "2 * 4 + 2 * 4 + 4 * 4";
|
||||
},
|
||||
);
|
||||
|
@ -371,6 +397,10 @@
|
|||
};
|
||||
|
||||
vertexInput = {
|
||||
index_only = {
|
||||
bindings = ();
|
||||
attributes = ();
|
||||
};
|
||||
alias = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; },
|
||||
|
@ -840,6 +870,7 @@
|
|||
module = $builtin/sprite_gbuf.frag;
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.vertexInput.index_only;
|
||||
inputAssembly = $properties.inputAssembly.sprite;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
|
@ -866,6 +897,7 @@
|
|||
module = $builtin/sprite_depth.frag;
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.vertexInput.index_only;
|
||||
inputAssembly = $properties.inputAssembly.alias;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
|
@ -875,7 +907,7 @@
|
|||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
layout = alias_layout;
|
||||
layout = sprite_layout;
|
||||
renderPass = renderpass;
|
||||
};
|
||||
twod = {
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
layout (constant_id = 0) const int MaxTextures = 256;
|
||||
|
||||
layout (set = 2, binding = 0) uniform sampler samp;
|
||||
layout (set = 2, binding = 1) uniform texture2DArray sprites[MaxTextures];
|
||||
layout (set = 1, binding = 1) uniform sampler2DArray Texture;
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
layout (offset = 64)
|
||||
|
@ -20,7 +19,7 @@ main (void)
|
|||
{
|
||||
vec4 pix;
|
||||
|
||||
pix = texture (sampler2DArray(sprites[spriteind], samp), vec3 (st, frame));
|
||||
pix = texture (Texture, vec3 (st, frame));
|
||||
if (pix.a < 0.5) {
|
||||
discard;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ layout (set = 0, binding = 0) uniform Matrices {
|
|||
mat4 Projection2d;
|
||||
};
|
||||
|
||||
layout (set = 1, binding = 0) buffer Vertices {
|
||||
vec4 xyuv[];
|
||||
layout (set = 1, binding = 0) uniform Vertices {
|
||||
vec4 xyuv[4];
|
||||
};
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
|
@ -23,7 +23,7 @@ main (void)
|
|||
{
|
||||
vec4 v = xyuv[frame * 4 + gl_VertexIndex];
|
||||
|
||||
vec4 pos = vec4 (0, 0, 0, 1);
|
||||
vec4 pos = Model[3];
|
||||
pos += v.x * Model[1] + v.y * Model[2];
|
||||
|
||||
gl_Position = Projection3d * (View * pos);
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
layout (constant_id = 0) const int MaxTextures = 256;
|
||||
|
||||
layout (set = 2, binding = 0) uniform sampler samp;
|
||||
layout (set = 2, binding = 1) uniform texture2DArray sprites[MaxTextures];
|
||||
layout (set = 1, binding = 1) uniform sampler2DArray Texture;
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
layout (offset = 64)
|
||||
|
@ -27,7 +26,7 @@ main (void)
|
|||
{
|
||||
vec4 pix;
|
||||
|
||||
pix = texture (sampler2DArray(sprites[spriteind], samp), vec3 (st, frame));
|
||||
pix = texture (Texture, vec3 (st, frame));
|
||||
if (pix.a < 0.5) {
|
||||
discard;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ layout (set = 0, binding = 0) uniform Matrices {
|
|||
mat4 Projection2d;
|
||||
};
|
||||
|
||||
layout (set = 1, binding = 0) buffer Vertices {
|
||||
vec4 xyuv[];
|
||||
layout (set = 1, binding = 0) uniform Vertices {
|
||||
vec4 xyuv[4];
|
||||
};
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
|
@ -25,7 +25,7 @@ main (void)
|
|||
{
|
||||
vec4 v = xyuv[frame * 4 + gl_VertexIndex];
|
||||
|
||||
vec4 pos = vec4 (0, 0, 0, 1);
|
||||
vec4 pos = Model[3];
|
||||
pos += v.x * Model[1] + v.y * Model[2];
|
||||
|
||||
gl_Position = Projection3d * (View * pos);
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "QF/Vulkan/qf_lightmap.h"
|
||||
#include "QF/Vulkan/qf_main.h"
|
||||
#include "QF/Vulkan/qf_particles.h"
|
||||
#include "QF/Vulkan/qf_sprite.h"
|
||||
//#include "QF/Vulkan/qf_textures.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
|
||||
|
@ -110,7 +111,7 @@ Vulkan_RenderEntities (qfv_renderframe_t *rFrame)
|
|||
|
||||
RE_LOOP (alias, Alias);
|
||||
//RE_LOOP (iqm, IQM);
|
||||
//RE_LOOP (sprite, Sprite);
|
||||
RE_LOOP (sprite, Sprite);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
346
libs/video/renderer/vulkan/vulkan_sprite.c
Normal file
346
libs/video/renderer/vulkan/vulkan_sprite.c
Normal file
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
vulkan_sprite.c
|
||||
|
||||
Vulkan sprite model pipeline
|
||||
|
||||
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2012/1/7
|
||||
Date: 2021/12/14
|
||||
|
||||
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
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "qfalloca.h"
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/darray.h"
|
||||
#include "QF/image.h"
|
||||
#include "QF/render.h"
|
||||
#include "QF/skin.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_sprite.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/buffer.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/descriptor.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
typedef struct {
|
||||
VkShaderStageFlags stageFlags;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
const void *data;
|
||||
} qfv_push_constants_t;
|
||||
|
||||
static const char * __attribute__((used)) sprite_pass_names[] = {
|
||||
"depth",
|
||||
"g-buffer",
|
||||
"translucent",
|
||||
};
|
||||
|
||||
static QFV_Subpass subpass_map[] = {
|
||||
QFV_passDepth, // QFV_spriteDepth
|
||||
QFV_passGBuffer, // QFV_spriteGBuffer
|
||||
QFV_passTranslucent, // QFV_spriteTranslucent
|
||||
};
|
||||
|
||||
static void
|
||||
emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite,
|
||||
int numPC, qfv_push_constants_t *constants,
|
||||
qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
spritectx_t *sctx = ctx->sprite_context;
|
||||
|
||||
for (int i = 0; i < numPC; i++) {
|
||||
dfunc->vkCmdPushConstants (cmd, sctx->layout, constants[i].stageFlags,
|
||||
constants[i].offset, constants[i].size,
|
||||
constants[i].data);
|
||||
}
|
||||
VkDescriptorSet sets[] = {
|
||||
sprite->descriptors,
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
sctx->layout, 1, 1, sets, 0, 0);
|
||||
dfunc->vkCmdDraw (cmd, 4, 1, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
spritectx_t *sctx = ctx->sprite_context;
|
||||
spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame];
|
||||
model_t *model = ent->renderer.model;
|
||||
msprite_t *sprite = model->cache.data;
|
||||
animation_t *animation = &ent->animation;
|
||||
|
||||
mat4f_t mat;
|
||||
uint32_t frame;
|
||||
qfv_push_constants_t push_constants[] = {
|
||||
{ VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat), mat },
|
||||
{ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
64, sizeof (frame), &frame },
|
||||
};
|
||||
|
||||
frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation);
|
||||
|
||||
mat[3] = Transform_GetWorldPosition (ent->transform);
|
||||
vec4f_t cameravec = {r_origin[0], r_origin[1], r_origin[2], 0 };
|
||||
vec4f_t svpn = {}, svright = {}, svup = {};
|
||||
cameravec -= mat[3];
|
||||
R_BillboardFrame (ent, sprite->type, &cameravec[0],
|
||||
&svup[0], &svright[0], &svpn[0]);
|
||||
mat[2] = svup;
|
||||
mat[1] = svright;
|
||||
mat[0] = -svpn;
|
||||
|
||||
emit_commands (aframe->cmdSet.a[QFV_spriteDepth],
|
||||
(qfv_sprite_t *) ((byte *) sprite + sprite->data),
|
||||
2, push_constants, rFrame);
|
||||
emit_commands (aframe->cmdSet.a[QFV_spriteGBuffer],
|
||||
(qfv_sprite_t *) ((byte *) sprite + sprite->data),
|
||||
2, push_constants, rFrame);
|
||||
}
|
||||
|
||||
static void
|
||||
sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline,
|
||||
qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
spritectx_t *sctx = ctx->sprite_context;
|
||||
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
|
||||
spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame];
|
||||
VkCommandBuffer cmd = aframe->cmdSet.a[subpass];
|
||||
|
||||
dfunc->vkResetCommandBuffer (cmd, 0);
|
||||
VkCommandBufferInheritanceInfo inherit = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
|
||||
rFrame->renderpass->renderpass, subpass_map[subpass],
|
||||
cframe->framebuffer,
|
||||
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, "sprite:%s",
|
||||
sprite_pass_names[subpass]),
|
||||
{ 0.6, 0.5, 0, 1});
|
||||
|
||||
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
VkDescriptorSet sets[] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
sctx->layout, 0, 1, sets, 0, 0);
|
||||
dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport);
|
||||
dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor);
|
||||
|
||||
//XXX glsl_Fog_GetColor (fog);
|
||||
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
|
||||
}
|
||||
|
||||
static void
|
||||
sprite_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);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_SpriteBegin (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
spritectx_t *sctx = ctx->sprite_context;
|
||||
spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame];
|
||||
|
||||
//XXX quat_t fog;
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth],
|
||||
aframe->cmdSet.a[QFV_spriteDepth]);
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer],
|
||||
aframe->cmdSet.a[QFV_spriteGBuffer]);
|
||||
|
||||
sprite_begin_subpass (QFV_spriteDepth, sctx->depth, rFrame);
|
||||
sprite_begin_subpass (QFV_spriteGBuffer, sctx->gbuf, rFrame);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_SpriteEnd (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
spritectx_t *sctx = ctx->sprite_context;
|
||||
spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame];
|
||||
|
||||
sprite_end_subpass (aframe->cmdSet.a[QFV_spriteDepth], ctx);
|
||||
sprite_end_subpass (aframe->cmdSet.a[QFV_spriteGBuffer], ctx);
|
||||
}
|
||||
|
||||
static VkDescriptorBufferInfo base_buffer_info = {
|
||||
.range = VK_WHOLE_SIZE,
|
||||
};
|
||||
static VkDescriptorImageInfo base_image_info = {
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
static VkWriteDescriptorSet base_buffer_write = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstBinding = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
};
|
||||
static VkWriteDescriptorSet base_image_write = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstBinding = 1,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
};
|
||||
|
||||
void
|
||||
Vulkan_Sprite_DescriptorSet (vulkan_ctx_t *ctx, qfv_sprite_t *sprite)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
spritectx_t *sctx = ctx->sprite_context;
|
||||
|
||||
//FIXME kinda dumb
|
||||
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca);
|
||||
for (size_t i = 0; i < layouts->size; i++) {
|
||||
layouts->a[i] = sctx->setLayout;
|
||||
}
|
||||
__auto_type sets = QFV_AllocateDescriptorSet (device, sctx->pool, layouts);
|
||||
sprite->descriptors = sets->a[0];
|
||||
free (sets);
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo[1];
|
||||
bufferInfo[0] = base_buffer_info;
|
||||
bufferInfo[0].buffer = sprite->verts;
|
||||
|
||||
VkDescriptorImageInfo imageInfo[1];
|
||||
imageInfo[0] = base_image_info;
|
||||
imageInfo[0].sampler = sctx->sampler;
|
||||
imageInfo[0].imageView = sprite->view;
|
||||
|
||||
VkWriteDescriptorSet write[2];
|
||||
write[0] = base_buffer_write;
|
||||
write[0].dstSet = sprite->descriptors;
|
||||
write[0].pBufferInfo = bufferInfo;
|
||||
write[1] = base_image_write;
|
||||
write[1].dstSet = sprite->descriptors;
|
||||
write[1].pImageInfo = imageInfo;
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Sprite_Init (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
||||
qfvPushDebug (ctx, "sprite init");
|
||||
|
||||
spritectx_t *sctx = calloc (1, sizeof (spritectx_t));
|
||||
ctx->sprite_context = sctx;
|
||||
|
||||
size_t frames = ctx->frames.size;
|
||||
DARRAY_INIT (&sctx->frames, frames);
|
||||
DARRAY_RESIZE (&sctx->frames, frames);
|
||||
sctx->frames.grow = 0;
|
||||
|
||||
sctx->depth = Vulkan_CreatePipeline (ctx, "sprite_depth");
|
||||
sctx->gbuf = Vulkan_CreatePipeline (ctx, "sprite_gbuf");
|
||||
sctx->layout = Vulkan_CreatePipelineLayout (ctx, "sprite_layout");
|
||||
sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler");
|
||||
|
||||
//FIXME too many places
|
||||
__auto_type limits = device->physDev->properties.limits;
|
||||
sctx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8);
|
||||
sctx->pool = Vulkan_CreateDescriptorPool (ctx, "sprite_pool");
|
||||
sctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "sprite_set");
|
||||
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
__auto_type aframe = &sctx->frames.a[i];
|
||||
|
||||
DARRAY_INIT (&aframe->cmdSet, QFV_spriteNumPasses);
|
||||
DARRAY_RESIZE (&aframe->cmdSet, QFV_spriteNumPasses);
|
||||
aframe->cmdSet.grow = 0;
|
||||
|
||||
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet);
|
||||
|
||||
for (int j = 0; j < QFV_spriteNumPasses; j++) {
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
||||
aframe->cmdSet.a[j],
|
||||
va (ctx->va_ctx, "cmd:sprite:%zd:%s", i,
|
||||
sprite_pass_names[j]));
|
||||
}
|
||||
}
|
||||
qfvPopDebug (ctx);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Sprite_Shutdown (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
spritectx_t *sctx = ctx->sprite_context;
|
||||
|
||||
for (size_t i = 0; i < sctx->frames.size; i++) {
|
||||
__auto_type aframe = &sctx->frames.a[i];
|
||||
free (aframe->cmdSet.a);
|
||||
}
|
||||
|
||||
dfunc->vkDestroyPipeline (device->dev, sctx->depth, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, sctx->gbuf, 0);
|
||||
free (sctx->frames.a);
|
||||
free (sctx);
|
||||
}
|
Loading…
Reference in a new issue