[vulkan] Implement deferred emission (fullbrights)

That was... easier than expected. A little more tedious that I would
have liked, but my scripting system isn't perfect (I suspect it's best
suited as the output of a code generator), and the C side could do with
a little more automation.
This commit is contained in:
Bill Currie 2021-03-22 19:08:16 +09:00
parent 5173414d97
commit 4eecbe867d
8 changed files with 116 additions and 28 deletions

View file

@ -59,7 +59,7 @@ typedef struct qfv_light_buffer_s {
} qfv_light_buffer_t;
#define LIGHTING_BUFFER_INFOS 1
#define LIGHTING_IMAGE_INFOS 4
#define LIGHTING_IMAGE_INFOS 5
typedef struct lightingframe_s {
VkCommandBuffer cmd;

View file

@ -49,6 +49,7 @@ enum {
enum {
QFV_attachDepth,
QFV_attachColor,
QFV_attachEmission,
QFV_attachNormal,
QFV_attachPosition,
QFV_attachOpaque,

View file

@ -30,6 +30,21 @@
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
emission = {
imageType = VK_IMAGE_TYPE_2D;
format = r16g16b16a16_sfloat;
samples = 1;
extent = {
width = $swapchain.extent.width;
height = $swapchain.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
normal = {
imageType = VK_IMAGE_TYPE_2D;
format = r16g16b16a16_sfloat;
@ -124,6 +139,22 @@
layerCount = 1;
};
};
emission = {
image = emission;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.emission.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
normal = {
image = normal;
viewType = VK_IMAGE_VIEW_TYPE_2D;
@ -191,8 +222,8 @@
};
framebuffer = {
renderPass = $properties.renderpass;
attachments = (depth, color, normal, position, opaque, translucent,
"$swapchain.views[$swapImageIndex]");
attachments = (depth, color, emission, normal, position, opaque,
translucent, "$swapchain.views[$swapImageIndex]");
width = $swapchain.extent.width;
height = $swapchain.extent.height;
layers = 1;
@ -200,6 +231,7 @@
clearValues = (
{ depthStencil = { depth = 1; stencil = 0; }; },
{ color = "[0, 0, 0, 1]"; }, // color
{ color = "[0, 0, 0, 1]"; }, // emission
{ color = "[0, 0, 0, 1]"; }, // normal
{ color = "[0, 0, 0, 1]"; }, // position
{ color = "[0, 0, 0, 1]"; }, // opaque
@ -228,6 +260,16 @@
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
format = $properties.images.emission.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
format = $properties.images.normal.format;
samples = 1;
@ -294,20 +336,24 @@
attachment = 1;
layout = color_attachment_optimal;
},
{ // normal
{ // emission
attachment = 2;
layout = color_attachment_optimal;
},
{ // position
{ // normal
attachment = 3;
layout = color_attachment_optimal;
},
{ // position
attachment = 4;
layout = color_attachment_optimal;
},
);
depthStencilAttachment = {
attachment = 0;
layout = depth_stencil_attachment_optimal;
};
preserveAttachments = (5);
preserveAttachments = (6);
},
{ // 2 lighting
pipelineBindPoint = graphics;
@ -320,52 +366,56 @@
attachment = 1;
layout = shader_read_only_optimal;
},
{ // normal
{ // emission
attachment = 2;
layout = shader_read_only_optimal;
},
{ // position
{ // normal
attachment = 3;
layout = shader_read_only_optimal;
},
{ // position
attachment = 4;
layout = shader_read_only_optimal;
},
);
colorAttachments = (
{ // opaque
attachment = 4;
attachment = 5;
layout = color_attachment_optimal;
},
);
preserveAttachments = (5);
preserveAttachments = (6);
},
{ // 3 translucent
pipelineBindPoint = graphics;
colorAttachments = (
{ // translucent
attachment = 5;
attachment = 6;
layout = color_attachment_optimal;
},
);
preserveAttachments = (0, 1, 2, 3, 4);
preserveAttachments = (0, 1, 2, 3, 4, 5);
},
{ // 4 compose
pipelineBindPoint = graphics;
inputAttachments = (
{ // opaque
attachment = 4;
attachment = 5;
layout = shader_read_only_optimal;
},
{ // translucent
attachment = 5;
attachment = 6;
layout = shader_read_only_optimal;
},
);
colorAttachments = (
{ // swapchain
attachment = 6;
attachment = 7;
layout = color_attachment_optimal;
},
);
preserveAttachments = (0, 1, 2, 3);
preserveAttachments = (0, 1, 2, 3, 4);
},
);
dependencies = (

View file

@ -83,7 +83,7 @@
bindings = (
{
type = input_attachment;
descriptorCount = "4z * $frames.size";
descriptorCount = "5z * $frames.size";
},
);
};
@ -258,6 +258,12 @@
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 4;
descriptorType = input_attachment;
descriptorCount = 1;
stageFlags = fragment;
},
);
};
lighting_lights = {
@ -515,6 +521,16 @@
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 = {
@ -674,6 +690,16 @@
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;
},
{
blendEnable = false;
srcColorBlendFactor = src_alpha;

View file

@ -15,20 +15,24 @@ layout (location = 1) in vec4 position;
layout (location = 2) in vec3 normal;
layout (location = 0) out vec4 frag_color;
layout (location = 1) out vec4 frag_normal;
layout (location = 2) out vec4 frag_position;
layout (location = 1) out vec4 frag_emission;
layout (location = 2) out vec4 frag_normal;
layout (location = 3) out vec4 frag_position;
void
main (void)
{
vec4 c;
vec4 e;
int i;
vec3 light = vec3 (0);
c = texture (Skin, vec3 (st, 0)) * unpackUnorm4x8(base_color);
c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA);
c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB);
e = texture (Skin, vec3 (st, 3));
frag_color = c;
frag_emission = e;
frag_normal = vec4(normal, 1);
frag_position = position;
}

View file

@ -18,8 +18,9 @@ layout (location = 2) in vec3 normal;
layout (location = 3) in vec4 position;
layout (location = 0) out vec4 frag_color;
layout (location = 1) out vec4 frag_normal;
layout (location = 2) out vec4 frag_position;
layout (location = 1) out vec4 frag_emission;
layout (location = 2) out vec4 frag_normal;
layout (location = 3) out vec4 frag_position;
layout (constant_id = 0) const bool doWarp = false;
layout (constant_id = 1) const bool doLight = true;
@ -107,7 +108,8 @@ sky_color (vec3 dir, float time)
void
main (void)
{
vec4 c;
vec4 c = vec4 (0);
vec4 e;
vec2 t_st = tl_st.xy;
vec2 l_st = tl_st.zw;
@ -115,15 +117,16 @@ main (void)
t_st = warp_st (t_st, time);
}
if (doSkyCube || doSkySheet) {
c = sky_color (direction, time);
e = 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);
e = texture (GlowMap, t_st);
}
frag_color = c;//fogBlend (c);
frag_emission = e;
frag_normal = vec4 (normal, 0);
frag_position = position;
}

View file

@ -2,8 +2,9 @@
layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput depth;
layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput color;
layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput normal;
layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput position;
layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput emission;
layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput normal;
layout (input_attachment_index = 4, set = 0, binding = 4) uniform subpassInput position;
struct LightData {
vec3 color;
@ -47,6 +48,7 @@ main (void)
{
//float d = subpassLoad (depth).r;
vec3 c = subpassLoad (color).rgb;
vec3 e = subpassLoad (emission).rgb;
vec3 n = subpassLoad (normal).rgb;
vec3 p = subpassLoad (position).rgb;
vec3 light = vec3 (0);
@ -56,5 +58,5 @@ main (void)
light += calc_light (lights[i], p, n);
}
}
frag_color = vec4 (c * light, 1);
frag_color = vec4 (c * light + e, 1);
}

View file

@ -214,8 +214,10 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx)
lframe->imageInfo[0].imageView = ctx->attachment_views->a[QFV_attachDepth];
lframe->imageInfo[1].imageView = ctx->attachment_views->a[QFV_attachColor];
lframe->imageInfo[2].imageView
= ctx->attachment_views->a[QFV_attachNormal];
= ctx->attachment_views->a[QFV_attachEmission];
lframe->imageInfo[3].imageView
= ctx->attachment_views->a[QFV_attachNormal];
lframe->imageInfo[4].imageView
= ctx->attachment_views->a[QFV_attachPosition];
dfunc->vkUpdateDescriptorSets (device->dev,
LIGHTING_BUFFER_INFOS + LIGHTING_IMAGE_INFOS,