[vulkan] Convert bsp and draw to deferred

This has bsp and draw passing muster with the validation layers.
This commit is contained in:
Bill Currie 2021-02-19 11:14:54 +09:00
parent 4245c6ad3b
commit cbc8ad271a
14 changed files with 304 additions and 39 deletions

View file

@ -65,13 +65,13 @@ typedef struct qfv_alias_skin_s {
#define ALIAS_BUFFER_INFOS 1
#define ALIAS_IMAGE_INFOS 1
enum {
typedef enum {
QFV_aliasDepth,
QFV_aliasGBuffer,
//QFV_aliasTranslucent,
QFV_aliasTranslucent,
QFV_aliasNumPasses
};
} QFV_AliasSubpass;
typedef struct aliasframe_s {
qfv_cmdbufferset_t cmdSet;

View file

@ -70,13 +70,13 @@ typedef enum {
// Texture, GlowMap, LightMap, SkySheet, SkyCube
#define BSP_IMAGE_INFOS 5
enum {
typedef enum {
QFV_bspDepth,
QFV_bspGBuffer,
QFV_bspTranslucent,
QFV_bspNumPasses
};
} QFV_BspSubpass;
typedef struct bspframe_s {
uint32_t *index_data; // pointer into mega-buffer for this frame (c)
@ -143,7 +143,8 @@ typedef struct bspctx_s {
VkSampler sampler;
VkDeviceMemory texture_memory;
VkPipeline main;
VkPipeline depth;
VkPipeline gbuf;
VkPipeline sky;
VkPipelineLayout layout;
size_t vertex_buffer_size;

View file

@ -39,8 +39,8 @@
enum {
QFV_passDepth, // geometry
QFV_passGBuffer, // geometry
QFV_passTranslucent, // geometry
QFV_passLighting, // single quad
QFV_passTranslucent, // geometry
QFV_passCompose, // single quad
QFV_NumPasses

View file

@ -274,6 +274,15 @@ quakebspv_src = $(vkshaderpath)/quakebsp.vert
quakebspv_c = $(vkshaderpath)/quakebsp.vert.spvc
quakebspf_src = $(vkshaderpath)/quakebsp.frag
quakebspf_c = $(vkshaderpath)/quakebsp.frag.spvc
bsp_depth_src = $(vkshaderpath)/bsp_depth.vert
bsp_depth_c = $(vkshaderpath)/bsp_depth.vert.spvc
bsp_gbufv_src = $(vkshaderpath)/bsp_gbuf.vert
bsp_gbufv_c = $(vkshaderpath)/bsp_gbuf.vert.spvc
bsp_gbufg_src = $(vkshaderpath)/bsp_gbuf.geom
bsp_gbufg_c = $(vkshaderpath)/bsp_gbuf.geom.spvc
bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag
bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc
aliasv_src = $(vkshaderpath)/alias.vert
aliasv_c = $(vkshaderpath)/alias.vert.spvc
aliasf_src = $(vkshaderpath)/alias.frag
@ -295,6 +304,14 @@ $(quakebspv_c): $(quakebspv_src)
$(quakebspf_c): $(quakebspf_src)
$(bsp_depth_c): $(bsp_depth_src)
$(bsp_gbufv_c): $(bsp_gbufv_src)
$(bsp_gbufg_c): $(bsp_gbufg_src)
$(bsp_gbuff_c): $(bsp_gbuff_src)
$(aliasv_c): $(aliasv_src)
$(alias_depth_c): $(alias_depth_src)
@ -312,6 +329,10 @@ vkshader_c = \
$(twodf_c) \
$(quakebspv_c) \
$(quakebspf_c) \
$(bsp_depth_c) \
$(bsp_gbufv_c) \
$(bsp_gbufg_c) \
$(bsp_gbuff_c) \
$(aliasv_c) \
$(alias_depth_c) \
$(aliasf_c) \

View file

@ -167,7 +167,9 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions)
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0,
family, 1, &priority
};
VkPhysicalDeviceFeatures features = {};
VkPhysicalDeviceFeatures features = {
.geometryShader = 1,
};
VkDeviceCreateInfo dCreateInfo = {
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0,
1, &qCreateInfo,

View file

@ -457,6 +457,7 @@
//renderPass = renderpass;
};
bsp_depth = {
subpass = 0;
stages = (
{
stage = vertex;
@ -472,10 +473,10 @@
"$properties.pipelines.bsp_gbuf.vertexInput.attributes[0]",
);
};
inputAssembly = $properties.pipelines.bsp_main.inputAssembly;
viewport = $properties.pipelines.bsp_main.viewport;
rasterization = $properties.pipelines.bsp_main.rasterization;
multisample = $properties.pipelines.bsp_main.multisample;
inputAssembly = $properties.pipelines.bsp_gbuf.inputAssembly;
viewport = $properties.pipelines.bsp_gbuf.viewport;
rasterization = $properties.pipelines.bsp_gbuf.rasterization;
multisample = $properties.pipelines.bsp_gbuf.multisample;
depthStencil = {
depthTestEnable = true;
depthWriteEnable = true;
@ -491,12 +492,18 @@
//renderPass = renderpass;
};
bsp_gbuf = {
subpass = 1;
stages = (
{
stage = vertex;
name = main;
module = $builtin/bsp_gbuf.vert;
},
{
stage = geometry;
name = main;
module = $builtin/bsp_gbuf.geom;
},
{
stage = fragment;
name = main;
@ -570,16 +577,28 @@
};
colorBlend = {
logicOpEnable = false;
attachments = ({
blendEnable = true;
srcColorBlendFactor = src_alpha;
dstColorBlendFactor = one_minus_src_alpha;
colorBlendOp = add;
srcAlphaBlendFactor = src_alpha;
dstAlphaBlendFactor = one_minus_src_alpha;
alphaBlendOp = add;
colorWriteMask = r|g|b|a;
});
attachments = (
{
blendEnable = false;
srcColorBlendFactor = src_alpha;
dstColorBlendFactor = one_minus_src_alpha;
colorBlendOp = add;
srcAlphaBlendFactor = src_alpha;
dstAlphaBlendFactor = one_minus_src_alpha;
alphaBlendOp = add;
colorWriteMask = r|g|b|a;
},
{
blendEnable = false;
srcColorBlendFactor = src_alpha;
dstColorBlendFactor = one_minus_src_alpha;
colorBlendOp = add;
srcAlphaBlendFactor = src_alpha;
dstAlphaBlendFactor = one_minus_src_alpha;
alphaBlendOp = add;
colorWriteMask = r|g|b|a;
}
);
};
dynamic = {
dynamicState = ( viewport, scissor, blend_constants );
@ -587,17 +606,23 @@
layout = quakebsp_layout;
//renderPass = renderpass;
};
quakebsp_skysheet = {
bsp_skysheet = {
subpass = 1;
stages = (
{
stage = vertex;
name = main;
module = $builtin/quakebsp.vert;
module = $builtin/bsp_gbuf.vert;
},
{
stage = geometry;
name = main;
module = $builtin/bsp_gbuf.geom;
},
{
stage = fragment;
name = main;
module = $builtin/quakebsp.frag;
module = $builtin/bsp_gbuf.frag;
specializationInfo = {
mapEntries = (
{ size = 4; offset = 0; constantID = 0; },
@ -623,6 +648,7 @@
//renderPass = renderpass;
};
twod = {
subpass = 3;
stages = (
{
stage = vertex;

View file

@ -63,6 +63,14 @@ static
static
#include "libs/video/renderer/vulkan/shader/quakebsp.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/bsp_depth.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/bsp_gbuf.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/bsp_gbuf.geom.spvc"
static
#include "libs/video/renderer/vulkan/shader/bsp_gbuf.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/alias.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc"
@ -86,6 +94,10 @@ static shaderdata_t builtin_shaders[] = {
{ "twod.frag", twod_frag, sizeof (twod_frag) },
{ "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) },
{ "quakebsp.frag", quakebsp_frag, sizeof (quakebsp_frag) },
{ "bsp_depth.vert", bsp_depth_vert, sizeof (bsp_depth_vert) },
{ "bsp_gbuf.vert", bsp_gbuf_vert, sizeof (bsp_gbuf_vert) },
{ "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) },
{ "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) },
{ "alias.vert", alias_vert, sizeof (alias_vert) },
{ "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) },
{ "alias.frag", alias_frag, sizeof (alias_frag) },

View file

@ -0,0 +1,19 @@
#version 450
layout (set = 0, binding = 0) uniform Matrices {
mat4 Projection;
mat4 View;
mat4 Sky;
};
layout (push_constant) uniform PushConstants {
mat4 Model;
};
layout (location = 0) in vec4 vertex;
void
main (void)
{
gl_Position = Projection * (View * (Model * vertex));
}

View file

@ -0,0 +1,126 @@
#version 450
layout (set = 0, binding = 1) uniform sampler2D Texture;
layout (set = 0, binding = 2) uniform sampler2D GlowMap;
layout (set = 0, binding = 3) uniform sampler2D LightMap;
layout (set = 0, binding = 4) uniform sampler2DArray SkySheet;
layout (set = 0, binding = 5) uniform samplerCube SkyCube;
layout (push_constant) uniform PushConstants {
layout (offset = 64)
vec4 fog;
float time;
};
layout (location = 0) in vec4 tl_st;
layout (location = 1) in vec3 direction;
layout (location = 2) in vec3 normal;
layout (location = 0) out vec4 frag_color;
layout (location = 1) out vec4 frag_normal;
layout (constant_id = 0) const bool doWarp = false;
layout (constant_id = 1) const bool doLight = true;
layout (constant_id = 2) const bool doSkyCube = false;
layout (constant_id = 3) const bool doSkySheet = false;
const float PI = 3.14159265;
const float SPEED = 20.0;
const float CYCLE = 128.0;
const float FACTOR = PI * 2.0 / CYCLE;
const vec2 BIAS = vec2 (1.0, 1.0);
const float SCALE = 8.0;
vec2
warp_st (vec2 st, float time)
{
vec2 angle = st.ts * CYCLE / 2.0;
vec2 phase = vec2 (time, time) * SPEED;
return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE;
}
vec4
fogBlend (vec4 color)
{
float az = fog.a * gl_FragCoord.z / gl_FragCoord.w;
vec3 fog_color = fog.rgb;
float fog_factor = exp (-az * az);
return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a);
}
vec4
sky_sheet (vec3 dir, float time)
{
float len;
vec2 flow = vec2 (1.0, 1.0);
vec2 base;
vec3 st1, st2;
vec4 c1, c2, c;
dir.z *= 3.0;
len = dot (dir, dir);
len = SCALE * inversesqrt (len);
base = dir.yx * vec2(1.0, -1.0) * len;
st1 = vec3 (base + flow * time / 8.0, 0);
st2 = vec3 (base + flow * time / 16.0, 1);
c1 = texture (SkySheet, st1);
c2 = texture (SkySheet, st2);
c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a));
return c;
}
vec4
sky_cube (vec3 dir, float time)
{
// NOTE: quake's world is right-handed with Z up and X forward, but
// Vulkan's cube maps are left-handed with Y up and Z forward. The
// rotation to X foward is done by the Sky matrix so all that's left
// to do here is swizzle the Y and Z coordinates
return texture (SkyCube, dir.xzy);
}
vec4
sky_color (vec3 dir, float time)
{
if (!doSkySheet) {
return vec4 (1, 0, 1, 1);
//return sky_cube (dir, time);
} if (!doSkyCube) {
return sky_sheet (dir, time);
} else {
// can see through the sheet (may look funny when looking down)
// maybe have 4 sheet layers instead of 2?
vec4 c1 = sky_sheet (dir, time);
vec4 c2 = sky_cube (dir, time);
return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a));
return vec4 (1, 0, 1, 1);
}
}
void
main (void)
{
vec4 c;
vec2 t_st = tl_st.xy;
vec2 l_st = tl_st.zw;
if (doWarp) {
t_st = warp_st (t_st, time);
}
if (doSkyCube || doSkySheet) {
c = sky_color (direction, time);
} else {
c = texture (Texture, t_st);
if (doLight) {
c *= vec4 (texture (LightMap, l_st).xyz, 1);
}
c += texture (GlowMap, t_st);
}
frag_color = c;//fogBlend (c);
frag_normal = vec4 (normal, 0);
}

View file

@ -0,0 +1,29 @@
#version 450
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
layout (location = 0) in vec4 v_tl_st[];
layout (location = 1) in vec3 v_direction[];
layout (location = 0) out vec4 tl_st;
layout (location = 1) out vec3 direction;
layout (location = 2) out vec3 normal;
void
main()
{
vec3 a = gl_in[0].gl_Position.xyz;
vec3 b = gl_in[1].gl_Position.xyz;
vec3 c = gl_in[2].gl_Position.xyz;
vec3 n = normalize (cross (b - a, c - a));
for (int vert = 0; vert < 3; vert++) {
gl_Position = gl_in[vert].gl_Position;
tl_st = v_tl_st[vert];
direction = v_direction[vert];
normal = n;
EmitVertex ();
}
EndPrimitive ();
}

View file

@ -0,0 +1,25 @@
#version 450
layout (set = 0, binding = 0) uniform Matrices {
mat4 Projection;
mat4 View;
mat4 Sky;
};
layout (push_constant) uniform PushConstants {
mat4 Model;
};
layout (location = 0) in vec4 vertex;
layout (location = 1) in vec4 tl_uv;
layout (location = 0) out vec4 tl_st;
layout (location = 1) out vec3 direction;
void
main (void)
{
gl_Position = Projection * (View * (Model * vertex));
direction = (Sky * vertex).xyz;
tl_st = tl_uv;
}

View file

@ -152,7 +152,7 @@ Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx)
}
static void
alias_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline,
alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline,
vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
@ -160,11 +160,12 @@ alias_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline,
aliasctx_t *actx = ctx->alias_context;
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = aframe->cmdSet.a[subpass];
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass, 0,
ctx->renderpass, subpass,
cframe->framebuffer,
0, 0, 0,
};
@ -222,8 +223,8 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx)
//FIXME need per frame matrices
aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
alias_begin_subpass (aframe->cmdSet.a[QFV_aliasDepth], actx->depth, ctx);
alias_begin_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], actx->gbuf, ctx);
alias_begin_subpass (QFV_aliasDepth, actx->depth, ctx);
alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, ctx);
}
void

View file

@ -845,18 +845,20 @@ get_view (qfv_tex_t *tex, qfv_tex_t *default_tex)
}
static void
bsp_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, vulkan_ctx_t *ctx)
bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context;
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = bframe->cmdSet.a[subpass];
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass, 0,
ctx->renderpass, subpass,
cframe->framebuffer,
0, 0, 0,
};
@ -928,9 +930,8 @@ bsp_begin (vulkan_ctx_t *ctx)
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
bctx->default_skybox);
//FIXME pipeline
bsp_begin_subpass (bframe->cmdSet.a[QFV_bspDepth], bctx->main, ctx);
bsp_begin_subpass (bframe->cmdSet.a[QFV_bspGBuffer], bctx->main, ctx);
bsp_begin_subpass (QFV_bspDepth, bctx->depth, ctx);
bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, ctx);
}
static void
@ -1047,7 +1048,7 @@ sky_begin (vulkan_ctx_t *ctx)
bctx->default_skybox);
//FIXME sky pass
bsp_begin_subpass (bframe->cmdSet.a[QFV_bspTranslucent], bctx->sky, ctx);
bsp_begin_subpass (QFV_bspTranslucent, bctx->sky, ctx);
}
static void
@ -1457,8 +1458,9 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
DARRAY_RESIZE (&bctx->frames, frames);
bctx->frames.grow = 0;
bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp_main");
bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp_skysheet");
bctx->depth = Vulkan_CreatePipeline (ctx, "bsp_depth");
bctx->gbuf = Vulkan_CreatePipeline (ctx, "bsp_gbuf");
bctx->sky = Vulkan_CreatePipeline (ctx, "bsp_skysheet");
bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout");
bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler");
@ -1507,7 +1509,8 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
free (bframe->cmdSet.a);
}
dfunc->vkDestroyPipeline (device->dev, bctx->main, 0);
dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0);
dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0);
dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0);
DARRAY_CLEAR (&bctx->texture_chains);
DARRAY_CLEAR (&bctx->frames);

View file

@ -709,7 +709,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx)
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass, 0,
ctx->renderpass, QFV_passTranslucent,
cframe->framebuffer,
0, 0, 0
};