[vulkan] Switch bsp renderer to multi-texture

I guess it's not quite bindless as the texture index is a push constant,
but it seems to work well (and I may have fixed some full-bright issues
by accident, though I suspect that's just my imagination, but they do
look good).
This commit is contained in:
Bill Currie 2021-12-08 21:11:36 +09:00
parent 6fbce335bb
commit 11492d77ce
5 changed files with 122 additions and 144 deletions

View file

@ -46,6 +46,7 @@ typedef struct vulktex_s {
struct elechain_s *elechain;
struct elechain_s **elechain_tail;
struct qfv_tex_s *tex;
int texind;
} vulktex_t;
typedef struct bspvert_s {
@ -75,10 +76,6 @@ typedef enum {
qfv_bsp_skysheet,
qfv_bsp_skycube,
} qfv_bsp_tex;
// view matrix
#define BSP_BUFFER_INFOS 1
// Texture, GlowMap, LightMap, SkySheet, SkyCube
#define BSP_IMAGE_INFOS 5
typedef enum {
QFV_bspDepth,
@ -94,14 +91,12 @@ typedef struct bspframe_s {
uint32_t index_offset; // offset of index_data within mega-buffer (c)
uint32_t index_count; // number if indices queued (d)
qfv_cmdbufferset_t cmdSet;
VkDescriptorBufferInfo bufferInfo[BSP_BUFFER_INFOS];
VkDescriptorImageInfo imageInfo[BSP_IMAGE_INFOS];
VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS];
} bspframe_t;
typedef struct fragconst_s {
quat_t fog;
float time;
int texind;
} fragconst_t;
typedef struct bspframeset_s
@ -157,13 +152,18 @@ typedef struct bspctx_s {
struct bsppoly_s *polys;
VkSampler sampler;
VkDescriptorSet descriptors;
VkDescriptorPool pool;
VkDescriptorSetLayout setLayout;
VkPipelineLayout layout;
unsigned maxImages;
VkDeviceMemory texture_memory;
VkPipeline depth;
VkPipeline gbuf;
VkPipeline skysheet;
VkPipeline skybox;
VkPipeline turb;
VkPipelineLayout layout;
size_t vertex_buffer_size;
size_t index_buffer_size;
VkBuffer vertex_buffer;

View file

@ -107,6 +107,20 @@
},
);
};
quakebsp_pool = {
flags = 0;
maxSets = 1;
bindings = (
{
type = sampler;
descriptorCount = 1;
},
{
type = sampled_image;
descriptorCount = $properties.limits.maxImages;
},
);
};
lighting_attach_pool = {
flags = 0;
maxSets = $frames.size;

View file

@ -38,10 +38,11 @@ main (void)
vec4 c = vec4 (0);
vec4 e;
vec3 t_st = vec3 (tl_st.xy, 0);
vec3 l_st = vec3 (tl_st.zw, 1);
vec3 e_st = vec3 (tl_st.xy, 1);
vec2 l_st = vec2 (tl_st.zw);
c = texture (sampler2DArray (textures[texind], samp), t_st);
e = texture (sampler2DArray (textures[texind], samp), t_st);
e = texture (sampler2DArray (textures[texind], samp), e_st);
frag_color = c;//fogBlend (c);
frag_emission = e;
frag_normal = vec4 (normal, 0);

View file

@ -3,7 +3,7 @@
layout (constant_id = 0) const int MaxTextures = 256;
layout (set = 1, binding = 0) uniform sampler samp;
layout (set = 1, binding = 1) uniform texture2D textures[MaxTextures];
layout (set = 1, binding = 1) uniform texture2DArray textures[MaxTextures];
layout (push_constant) uniform PushConstants {
layout (offset = 64)
@ -47,10 +47,8 @@ main (void)
{
vec4 c = vec4 (0);
vec4 e;
vec2 t_st = tl_st.xy;
vec2 l_st = tl_st.zw;
vec3 t_st = vec3 (warp_st (tl_st.xy, time), 0);
t_st = warp_st (t_st, time);
c = texture (sampler2D (textures[texind], samp), t_st);
c = texture (sampler2DArray (textures[texind], samp), t_st);
frag_color = c;//fogBlend (c);
}

View file

@ -54,6 +54,7 @@
#include "QF/Vulkan/qf_bsp.h"
#include "QF/Vulkan/qf_lightmap.h"
#include "QF/Vulkan/qf_matrices.h"
#include "QF/Vulkan/qf_texture.h"
#include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/barrier.h"
@ -161,6 +162,7 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx)
bspctx_t *bctx = ctx->bsp_context;
vulktex_t *tex = tx->render;
tex->texind = bctx->texture_chains.size;
DARRAY_APPEND (&bctx->texture_chains, tex);
tex->tex_chain = 0;
tex->tex_chain_tail = &tex->tex_chain;
@ -259,9 +261,29 @@ clear_textures (vulkan_ctx_t *ctx)
bctx->texture_chains.size = 0;
}
static VkDescriptorImageInfo base_sampler_info = { };
static VkDescriptorImageInfo base_image_info = {
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
};
static VkWriteDescriptorSet base_sampler_write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstBinding = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
};
static VkWriteDescriptorSet base_image_write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstBinding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
};
void
Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context;
int i;
model_t *m;
mod_brush_t *brush = &r_worldentity.renderer.model->brush;
@ -284,6 +306,33 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
brush->numsubmodels = 1; // no support for submodels in non-world model
register_textures (brush, ctx);
}
if (bctx->texture_chains.size > bctx->maxImages) {
Sys_Error ("smart texture handling not implemented, want %zd textures,"
"can support %d.",
bctx->texture_chains.size, bctx->maxImages);
}
VkDescriptorImageInfo samplerInfo[1];
samplerInfo[0] = base_sampler_info;
samplerInfo[0].sampler = bctx->sampler;
VkDescriptorImageInfo imageInfo[bctx->maxImages];
for (unsigned i = 0; i < bctx->maxImages; i++) {
imageInfo[i] = base_image_info;
imageInfo[i].imageView = ctx->default_magenta_array->view;
if (i && i < bctx->texture_chains.size) {
imageInfo[i].imageView = bctx->texture_chains.a[i]->tex->view;
}
}
VkWriteDescriptorSet write[2];
write[0] = base_sampler_write;
write[0].dstSet = bctx->descriptors;
write[0].pImageInfo = samplerInfo;
write[1] = base_image_write;
write[1].dstSet = bctx->descriptors;
write[1].descriptorCount = bctx->maxImages;
write[1].pImageInfo = imageInfo;
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
}
static elechain_t *
@ -745,17 +794,6 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
visit_leaf ((mleaf_t *) node);
}
static void
bind_view (qfv_bsp_tex tex, VkImageView view, bspframe_t *bframe,
VkCommandBuffer cmd, VkPipelineLayout layout, qfv_devfuncs_t *dfunc)
{
bframe->imageInfo[tex].imageView = view;
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, 1,
bframe->descriptors + tex
+ BSP_BUFFER_INFOS);
}
static void
push_transform (vec_t *transform, VkPipelineLayout layout,
qfv_devfuncs_t *dfunc, VkCommandBuffer cmd)
@ -764,6 +802,15 @@ push_transform (vec_t *transform, VkPipelineLayout layout,
0, 16 * sizeof (float), transform);
}
static void
push_texind (int32_t texind, VkPipelineLayout layout,
qfv_devfuncs_t *dfunc, VkCommandBuffer cmd)
{
dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT,
/*FIXME 64*/ 64 + field_offset (fragconst_t, texind),
sizeof (int32_t), &texind);
}
static void
push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout,
qfv_devfuncs_t *dfunc, VkCommandBuffer cmd)
@ -772,15 +819,6 @@ push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout,
64, sizeof (fragconst_t), fragconst);//FIXME 64
}
static void
push_descriptors (int count, VkWriteDescriptorSet *descriptors,
VkPipelineLayout layout, qfv_devfuncs_t *dfunc,
VkCommandBuffer cmd)
{
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, count, descriptors);
}
static void
draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc,
VkCommandBuffer cmd)
@ -812,21 +850,9 @@ reset_elechain (elechain_t *ec)
}
}
static VkImageView
get_view (qfv_tex_t *tex, qfv_tex_t *default_tex)
{
if (tex) {
return tex->view;
}
if (default_tex) {
return default_tex->view;
}
return 0;
}
static void
bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
qfv_renderframe_t *rFrame)
VkPipelineLayout layout, qfv_renderframe_t *rFrame)
{
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
qfv_device_t *device = ctx->device;
@ -864,14 +890,12 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset,
VK_INDEX_TYPE_UINT32);
// push VP matrices
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
bctx->layout,
0, 1, bframe->descriptors + 0);
// push static images
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
bctx->layout,
0, 3, bframe->descriptors + 3);
VkDescriptorSet set[2] = {
Vulkan_Matrix_Descrptors (ctx, ctx->curFrame),
bctx->descriptors,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, 2, set, 0, 0);
//XXX glsl_Fog_GetColor (fog);
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
@ -904,18 +928,8 @@ bsp_begin (qfv_renderframe_t *rFrame)
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer],
bframe->cmdSet.a[QFV_bspGBuffer]);
//FIXME need per frame matrices
//XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
bframe->imageInfo[0].imageView = 0; // set by tex chain loop
bframe->imageInfo[1].imageView = 0; // set by tex chain loop
bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap);
bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex,
bctx->default_skysheet);
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
bctx->default_skybox);
bsp_begin_subpass (QFV_bspDepth, bctx->depth, rFrame);
bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, rFrame);
bsp_begin_subpass (QFV_bspDepth, bctx->depth, bctx->layout, rFrame);
bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, bctx->layout, rFrame);
}
static void
@ -943,15 +957,7 @@ turb_begin (qfv_renderframe_t *rFrame)
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
bframe->cmdSet.a[QFV_bspTurb]);
//FIXME need per frame matrices
//XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
bframe->imageInfo[0].imageView = ctx->default_magenta->view;
bframe->imageInfo[1].imageView = ctx->default_magenta->view;
bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap);
bframe->imageInfo[3].imageView = bctx->default_skysheet->view;
bframe->imageInfo[4].imageView = bctx->default_skybox->view;
bsp_begin_subpass (QFV_bspTurb, bctx->turb, rFrame);
bsp_begin_subpass (QFV_bspTurb, bctx->turb, bctx->layout, rFrame);
}
static void
@ -1002,20 +1008,10 @@ sky_begin (qfv_renderframe_t *rFrame)
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
bframe->cmdSet.a[QFV_bspSky]);
//FIXME need per frame matrices
//XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
bframe->imageInfo[0].imageView = ctx->default_magenta->view;
bframe->imageInfo[1].imageView = ctx->default_magenta->view;
bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap);
bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex,
bctx->default_skysheet);
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
bctx->default_skybox);
if (bctx->skybox_tex) {
bsp_begin_subpass (QFV_bspSky, bctx->skybox, rFrame);
bsp_begin_subpass (QFV_bspSky, bctx->skybox, bctx->layout, rFrame);
} else {
bsp_begin_subpass (QFV_bspSky, bctx->skysheet, rFrame);
bsp_begin_subpass (QFV_bspSky, bctx->skysheet, bctx->layout, rFrame);
}
}
@ -1118,11 +1114,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
build_tex_elechain (tex, bctx, bframe);
bframe->imageInfo[0].imageView = get_view (tex->tex,
ctx->default_white);
push_descriptors (2, bframe->descriptors + 1, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspGBuffer]);
push_texind (tex->texind, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspGBuffer]);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,
@ -1178,11 +1171,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame)
msurface_t *surf = is->surface;
if (tex != surf->texinfo->texture->render) {
if (tex) {
bind_view (qfv_bsp_texture,
get_view (tex->tex, ctx->default_black),
bframe,
bframe->cmdSet.a[QFV_bspTurb],
bctx->layout, dfunc);
push_texind (tex->texind, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
@ -1198,9 +1188,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame)
add_surf_elements (tex, is, &ec, &el, bctx, bframe);
}
if (tex) {
bind_view (qfv_bsp_texture, get_view (tex->tex, ctx->default_black),
bframe, bframe->cmdSet.a[QFV_bspTurb],
bctx->layout, dfunc);
push_texind (tex->texind, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
@ -1241,11 +1230,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame)
msurface_t *surf = is->surface;
if (tex != surf->texinfo->texture->render) {
if (tex) {
bind_view (qfv_bsp_skysheet,
get_view (tex->tex, ctx->default_black),
bframe,
bframe->cmdSet.a[QFV_bspSky],
bctx->layout, dfunc);
push_texind (tex->texind, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspSky]);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspSky]);
@ -1261,9 +1247,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame)
add_surf_elements (tex, is, &ec, &el, bctx, bframe);
}
if (tex) {
bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black),
bframe, bframe->cmdSet.a[QFV_bspSky],
bctx->layout, dfunc);
push_texind (tex->texind, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspSky]);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspSky]);
@ -1385,25 +1370,6 @@ create_default_skys (vulkan_ctx_t *ctx)
QFV_PacketSubmit (packet);
}
static VkDescriptorBufferInfo base_buffer_info = {
0, 0, VK_WHOLE_SIZE
};
static VkDescriptorImageInfo base_image_info = {
0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
};
static VkWriteDescriptorSet base_buffer_write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
0, 0, 1,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0, 0, 0
};
static VkWriteDescriptorSet base_image_write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
0, 0, 1,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, 0, 0
};
void
Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
{
@ -1444,6 +1410,20 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout");
bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler");
//FIXME too many places
__auto_type limits = device->physDev->properties.limits;
bctx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8);
bctx->pool = Vulkan_CreateDescriptorPool (ctx, "quakebsp_pool");
bctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "quakebsp_set");
//FIXME kinda dumb
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca);
for (size_t i = 0; i < layouts->size; i++) {
layouts->a[i] = bctx->setLayout;
}
__auto_type sets = QFV_AllocateDescriptorSet (device, bctx->pool, layouts);
bctx->descriptors = sets->a[0];
free (sets);
for (size_t i = 0; i < frames; i++) {
__auto_type bframe = &bctx->frames.a[i];
@ -1459,21 +1439,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
va (ctx->va_ctx, "cmd:bsp:%zd:%s", i,
bsp_pass_names[j]));
}
for (int j = 0; j < BSP_BUFFER_INFOS; j++) {
bframe->bufferInfo[j] = base_buffer_info;
bframe->descriptors[j] = base_buffer_write;
bframe->descriptors[j].dstBinding = j;
bframe->descriptors[j].pBufferInfo = &bframe->bufferInfo[j];
}
for (int j = 0; j < BSP_IMAGE_INFOS; j++) {
bframe->imageInfo[j] = base_image_info;
bframe->imageInfo[j].sampler = bctx->sampler;
int k = j + BSP_BUFFER_INFOS;
bframe->descriptors[k] = base_image_write;
bframe->descriptors[k].dstBinding = k;
bframe->descriptors[k].pImageInfo = &bframe->imageInfo[j];
}
}
qfvPopDebug (ctx);
}