[vulkan] Move oit blending into compose subpass

I had debated putting the blending in the compose subpass or a separate
pass but went with the separate pass originally, but it turns out that
removing the separate pass gains 1-3% (5-15/545 fps in a timedemo of
demo1).
This commit is contained in:
Bill Currie 2022-12-01 23:03:55 +09:00
parent 7a64bb1149
commit 966ef949c5
12 changed files with 23 additions and 161 deletions

View file

@ -36,7 +36,7 @@
#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h" #include "QF/Vulkan/command.h"
#define COMPOSE_IMAGE_INFOS 2 #define COMPOSE_IMAGE_INFOS 1
typedef struct composeframe_s { typedef struct composeframe_s {
VkCommandBuffer cmd; VkCommandBuffer cmd;

View file

@ -40,8 +40,6 @@ typedef struct translucentctx_s {
struct qfv_resource_s *resources; struct qfv_resource_s *resources;
VkPipeline pipeline;
VkPipelineLayout layout;
VkDescriptorPool pool; VkDescriptorPool pool;
VkDescriptorSetLayout setLayout; VkDescriptorSetLayout setLayout;
} translucentctx_t; } translucentctx_t;

View file

@ -53,7 +53,6 @@ typedef enum {
QFV_passTranslucentFrag, // geometry QFV_passTranslucentFrag, // geometry
QFV_passGBuffer, // geometry QFV_passGBuffer, // geometry
QFV_passLighting, // single triangle QFV_passLighting, // single triangle
QFV_passTranslucentFinal, // single triangle
QFV_passCompose, // single triangle QFV_passCompose, // single triangle
QFV_NumPasses QFV_NumPasses
@ -66,7 +65,6 @@ enum {
QFV_attachNormal, QFV_attachNormal,
QFV_attachPosition, QFV_attachPosition,
QFV_attachOpaque, QFV_attachOpaque,
QFV_attachTranslucent,
QFV_attachSwapchain, QFV_attachSwapchain,
}; };

View file

@ -340,10 +340,9 @@ lightingf_src = $(vkshaderpath)/lighting.frag
lightingf_c = $(vkshaderpath)/lighting.frag.spvc lightingf_c = $(vkshaderpath)/lighting.frag.spvc
composef_src = $(vkshaderpath)/compose.frag composef_src = $(vkshaderpath)/compose.frag
composef_c = $(vkshaderpath)/compose.frag.spvc composef_c = $(vkshaderpath)/compose.frag.spvc
oit_blend = $(vkshaderpath)/oit_blend.finc
oit_store = $(vkshaderpath)/oit_store.finc oit_store = $(vkshaderpath)/oit_store.finc
oit_h = $(vkshaderpath)/oit.h oit_h = $(vkshaderpath)/oit.h
oit_blendf_src = $(vkshaderpath)/oit_blend.frag
oit_blendf_c = $(vkshaderpath)/oit_blend.frag.spvc
aliasv_src = $(vkshaderpath)/alias.vert aliasv_src = $(vkshaderpath)/alias.vert
aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasv_c = $(vkshaderpath)/alias.vert.spvc
aliasf_src = $(vkshaderpath)/alias.frag aliasf_src = $(vkshaderpath)/alias.frag
@ -419,9 +418,7 @@ $(bsp_turbf_c): $(bsp_turbf_src) $(oit_store) $(oit_h)
$(lightingf_c): $(lightingf_src) $(lightingf_c): $(lightingf_src)
$(composef_c): $(composef_src) $(composef_c): $(composef_src) $(oit_blend) $(oit_h)
$(oit_blendf_c): $(oit_blendf_src) $(oit_h)
$(aliasv_c): $(aliasv_src) $(aliasv_c): $(aliasv_src)
@ -478,7 +475,6 @@ vkshader_c = \
$(bsp_turbf_c) \ $(bsp_turbf_c) \
$(lightingf_c) \ $(lightingf_c) \
$(composef_c) \ $(composef_c) \
$(oit_blendf_c) \
$(aliasv_c) \ $(aliasv_c) \
$(alias_depth_c) \ $(alias_depth_c) \
$(aliasf_c) \ $(aliasf_c) \
@ -530,6 +526,9 @@ EXTRA_DIST += \
$(rp_shadow_src) \ $(rp_shadow_src) \
$(pl_quake_def_src) \ $(pl_quake_def_src) \
$(pl_output_src) \ $(pl_output_src) \
$(oit_blend) \
$(oit_store) \
$(oit_h) \
libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.plist \
libs/video/renderer/vulkan/vkparse.h \ libs/video/renderer/vulkan/vkparse.h \
libs/video/renderer/vulkan/shader/alias.frag \ libs/video/renderer/vulkan/shader/alias.frag \
@ -545,7 +544,6 @@ EXTRA_DIST += \
libs/video/renderer/vulkan/shader/bsp_sky.frag \ libs/video/renderer/vulkan/shader/bsp_sky.frag \
libs/video/renderer/vulkan/shader/bsp_turb.frag \ libs/video/renderer/vulkan/shader/bsp_turb.frag \
libs/video/renderer/vulkan/shader/compose.frag \ libs/video/renderer/vulkan/shader/compose.frag \
libs/video/renderer/vulkan/shader/oit_blend.frag \
libs/video/renderer/vulkan/shader/iqm.frag \ libs/video/renderer/vulkan/shader/iqm.frag \
libs/video/renderer/vulkan/shader/iqm.vert \ libs/video/renderer/vulkan/shader/iqm.vert \
libs/video/renderer/vulkan/shader/lighting.frag \ libs/video/renderer/vulkan/shader/lighting.frag \

View file

@ -427,12 +427,6 @@
descriptorCount = 1; descriptorCount = 1;
stageFlags = fragment; stageFlags = fragment;
}, },
{
binding = 1;
descriptorType = input_attachment;
descriptorCount = 1;
stageFlags = fragment;
},
); );
}; };
particle_set = { particle_set = {
@ -526,11 +520,8 @@
lighting_layout = { lighting_layout = {
setLayouts = (lighting_attach, lighting_lights, lighting_shadow); setLayouts = (lighting_attach, lighting_lights, lighting_shadow);
}; };
oit_layout = {
setLayouts = (oit_set);
};
compose_layout = { compose_layout = {
setLayouts = (compose_attach); setLayouts = (compose_attach, oit_set);
}; };
partphysics_layout = { partphysics_layout = {
setLayouts = (particle_set); setLayouts = (particle_set);
@ -1264,22 +1255,9 @@
); );
layout = lighting_layout; layout = lighting_layout;
}; };
oit = {
@inherit = $properties.pipelines.comp_base;
subpass = 4;
stages = (
$properties.fstriangle.vertexStage,
{
stage = fragment;
name = main;
module = $builtin/oit_blend.frag;
},
);
layout = oit_layout;
};
compose = { compose = {
@inherit = $properties.pipelines.comp_base; @inherit = $properties.pipelines.comp_base;
subpass = 5; subpass = 4;
stages = ( stages = (
$properties.fstriangle.vertexStage, $properties.fstriangle.vertexStage,
{ {

View file

@ -39,10 +39,6 @@
@inherit = $properties.flat_color_image_template; @inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat; format = r16g16b16a16_sfloat;
}; };
translucent = {
@inherit = $properties.flat_color_image_template;
format = r8g8b8a8_unorm;
};
}; };
flat_color_view_template = { flat_color_view_template = {
viewType = VK_IMAGE_VIEW_TYPE_2D; viewType = VK_IMAGE_VIEW_TYPE_2D;
@ -92,11 +88,6 @@
image = opaque; image = opaque;
format = $properties.images.opaque.format; format = $properties.images.opaque.format;
}; };
translucent = {
@inherit = $properties.flat_color_view_template;
image = translucent;
format = $properties.images.translucent.format;
};
}; };
output = { output = {
image = { image = {
@ -115,7 +106,7 @@
framebuffer = { framebuffer = {
renderPass = deferred; renderPass = deferred;
attachments = (depth, color, emission, normal, position, opaque, attachments = (depth, color, emission, normal, position, opaque,
translucent, $output.view); $output.view);
width = $output.extent.width; width = $output.extent.width;
height = $output.extent.height; height = $output.extent.height;
layers = 1; layers = 1;
@ -127,7 +118,6 @@
{ color = "[0, 0, 0, 1]"; }, // normal { color = "[0, 0, 0, 1]"; }, // normal
{ color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // position
{ color = "[0, 0, 0, 1]"; }, // opaque { color = "[0, 0, 0, 1]"; }, // opaque
{ color = "[0, 0, 0, 0]"; }, // translucent
{ color = "[0, 0, 0, 1]"; }, // output { color = "[0, 0, 0, 1]"; }, // output
); );
attachment_template = { attachment_template = {
@ -146,7 +136,6 @@
{ name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" },
{ name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" },
{ name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" },
{ name = translucent; color = "[ 0.25, 0.6, 0.25, 1]" },
{ name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" },
); );
}; };
@ -180,11 +169,6 @@
@inherit = $properties.attachment_template; @inherit = $properties.attachment_template;
format = $properties.images.opaque.format; format = $properties.images.opaque.format;
}, },
{
@inherit = $properties.attachment_template;
format = $properties.images.translucent.format;
loadOp = clear;
},
{ {
@inherit = $properties.attachment_template; @inherit = $properties.attachment_template;
format = $output.format; format = $output.format;
@ -267,31 +251,17 @@
); );
preserveAttachments = (6); preserveAttachments = (6);
}, },
{ // 4 translucent-final { // 4 compose
pipelineBindPoint = graphics;
colorAttachments = (
{ // translucent
attachment = 6;
layout = color_attachment_optimal;
},
);
preserveAttachments = (1, 2, 3, 4, 5);
},
{ // 5 compose
pipelineBindPoint = graphics; pipelineBindPoint = graphics;
inputAttachments = ( inputAttachments = (
{ // opaque { // opaque
attachment = 5; attachment = 5;
layout = shader_read_only_optimal; layout = shader_read_only_optimal;
}, },
{ // translucent
attachment = 6;
layout = shader_read_only_optimal;
},
); );
colorAttachments = ( colorAttachments = (
{ // output { // output
attachment = 7; attachment = 6;
layout = color_attachment_optimal; layout = color_attachment_optimal;
}, },
); );
@ -308,14 +278,6 @@
dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dstAccessMask = input_attachment_read|depth_stencil_attachment_read;
dependencyFlags = by_region; dependencyFlags = by_region;
}, },
/*{
srcSubpass = ~0u; // external
dstSubpass = 1; // translucent-frags
srcStageMask = transfer;
dstStageMask = fragment_shader|early_fragment_tests;
srcAccessMask = transfer_write;
dstAccessMask = shader_read|shader_write;
},*/
{ {
srcSubpass = 0; // depth srcSubpass = 0; // depth
dstSubpass = 2; // g-buffer dstSubpass = 2; // g-buffer
@ -336,7 +298,7 @@
}, },
{ {
srcSubpass = 3; // lighting srcSubpass = 3; // lighting
dstSubpass = 5; // compose dstSubpass = 4; // compose
srcStageMask = color_attachment_output; srcStageMask = color_attachment_output;
dstStageMask = fragment_shader; dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write; srcAccessMask = color_attachment_write;
@ -345,16 +307,7 @@
}, },
{ {
srcSubpass = 1; // translucent-frags srcSubpass = 1; // translucent-frags
dstSubpass = 4; // translucent-final dstSubpass = 4; // translucent-final/compose
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = input_attachment_read;
dependencyFlags = by_region;
},
{
srcSubpass = 4; // translucent-final
dstSubpass = 5; // compose
srcStageMask = color_attachment_output; srcStageMask = color_attachment_output;
dstStageMask = fragment_shader; dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write; srcAccessMask = color_attachment_write;

View file

@ -95,8 +95,6 @@ static
static static
#include "libs/video/renderer/vulkan/shader/compose.frag.spvc" #include "libs/video/renderer/vulkan/shader/compose.frag.spvc"
static static
#include "libs/video/renderer/vulkan/shader/oit_blend.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/alias.vert.spvc" #include "libs/video/renderer/vulkan/shader/alias.vert.spvc"
static static
#include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" #include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc"
@ -158,7 +156,6 @@ static shaderdata_t builtin_shaders[] = {
{ "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) }, { "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) },
{ "lighting.frag", lighting_frag, sizeof (lighting_frag) }, { "lighting.frag", lighting_frag, sizeof (lighting_frag) },
{ "compose.frag", compose_frag, sizeof (compose_frag) }, { "compose.frag", compose_frag, sizeof (compose_frag) },
{ "oit_blend.frag", oit_blend_frag, sizeof (oit_blend_frag) },
{ "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias.vert", alias_vert, sizeof (alias_vert) },
{ "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) },
{ "alias.frag", alias_frag, sizeof (alias_frag) }, { "alias.frag", alias_frag, sizeof (alias_frag) },

View file

@ -1,7 +1,9 @@
#version 450 #version 450
#extension GL_GOOGLE_include_directive : enable
#define OIT_SET 1
#include "oit_blend.finc"
layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput opaque; layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput opaque;
layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput translucent;
layout (location = 0) out vec4 frag_color; layout (location = 0) out vec4 frag_color;
@ -9,12 +11,10 @@ void
main (void) main (void)
{ {
vec3 o; vec3 o;
vec4 t;
vec3 c; vec3 c;
o = subpassLoad (opaque).rgb; o = subpassLoad (opaque).rgb;
t = subpassLoad (translucent); c = BlendFrags (vec4 (o, 1)).xyz;
c = mix (o, t.rgb, t.a);
c = pow (c, vec3(0.83));//FIXME make gamma correction configurable c = pow (c, vec3(0.83));//FIXME make gamma correction configurable
frag_color = vec4 (c, 1); frag_color = vec4 (c, 1);
} }

View file

@ -1,12 +1,7 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
#define OIT_SET 0
#include "oit.h" #include "oit.h"
layout (location = 0) out vec4 frag_color; vec4
BlendFrags (vec4 color)
void
main (void)
{ {
#define MAX_FRAGMENTS 64 #define MAX_FRAGMENTS 64
FragData frags[MAX_FRAGMENTS]; FragData frags[MAX_FRAGMENTS];
@ -31,10 +26,9 @@ main (void)
frags[j] = toInsert; frags[j] = toInsert;
} }
vec4 color = vec4 (0, 0, 0, 0);
for (int i = 0; i < numFrags; i++) { for (int i = 0; i < numFrags; i++) {
color = mix (color, frags[i].color, color = mix (color, frags[i].color,
clamp (frags[i].color.a, 0.0f, 1.0f)); clamp (frags[i].color.a, 0.0f, 1.0f));
} }
frag_color = color; return color;
} }

View file

@ -46,6 +46,7 @@
#include "QF/Vulkan/qf_compose.h" #include "QF/Vulkan/qf_compose.h"
#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_renderpass.h"
#include "QF/Vulkan/qf_translucent.h"
#include "QF/Vulkan/debug.h" #include "QF/Vulkan/debug.h"
#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/descriptor.h"
#include "QF/Vulkan/device.h" #include "QF/Vulkan/device.h"
@ -90,16 +91,15 @@ Vulkan_Compose_Draw (qfv_renderframe_t *rFrame)
cframe->imageInfo[0].imageView cframe->imageInfo[0].imageView
= renderpass->attachment_views->a[QFV_attachOpaque]; = renderpass->attachment_views->a[QFV_attachOpaque];
cframe->imageInfo[1].imageView
= renderpass->attachment_views->a[QFV_attachTranslucent];
dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS, dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS,
cframe->descriptors, 0, 0); cframe->descriptors, 0, 0);
VkDescriptorSet sets[] = { VkDescriptorSet sets[] = {
cframe->descriptors[0].dstSet, cframe->descriptors[0].dstSet,
Vulkan_Translucent_Descriptors (ctx, ctx->curFrame),
}; };
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
cctx->layout, 0, 1, sets, 0, 0); cctx->layout, 0, 2, sets, 0, 0);
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);

View file

@ -141,7 +141,6 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame)
Vulkan_Bsp_Flush (ctx); Vulkan_Bsp_Flush (ctx);
Vulkan_RenderEntities (r_ent_queue, rFrame); Vulkan_RenderEntities (r_ent_queue, rFrame);
Vulkan_Scene_Flush (ctx); Vulkan_Scene_Flush (ctx);
Vulkan_Translucent_Draw (rFrame);
} }
void void

View file

@ -66,54 +66,6 @@ static const char * __attribute__((used)) translucent_pass_names[] = {
"blend", "blend",
}; };
void
Vulkan_Translucent_Draw (qfv_renderframe_t *rFrame)
{
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
qfv_renderpass_t *renderpass = rFrame->renderpass;
translucentctx_t *tctx = ctx->translucent_context;
translucentframe_t *tframe = &tctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = tframe->cmdSet.a[QFV_translucentBlend];
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFinal], cmd);
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
renderpass->renderpass, QFV_passTranslucentFinal,
rFrame->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, "translucent", { 0, 0.2, 0.6, 1});
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
tctx->pipeline);
VkDescriptorSet set[] = {
tframe->descriptors,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
tctx->layout, 0, 1, set, 0, 0);
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
dfunc->vkCmdDraw (cmd, 3, 1, 0, 0);
QFV_duCmdEndLabel (device, cmd);
dfunc->vkEndCommandBuffer (cmd);
}
void void
Vulkan_Translucent_Init (vulkan_ctx_t *ctx) Vulkan_Translucent_Init (vulkan_ctx_t *ctx)
{ {
@ -132,9 +84,6 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx)
DARRAY_RESIZE (&tctx->frames, frames); DARRAY_RESIZE (&tctx->frames, frames);
tctx->frames.grow = 0; tctx->frames.grow = 0;
tctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "oit");
tctx->layout = Vulkan_CreatePipelineLayout (ctx, "oit_layout");
__auto_type setLayout = QFV_AllocDescriptorSetLayoutSet (frames, alloca); __auto_type setLayout = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
for (size_t i = 0; i < frames; i++) { for (size_t i = 0; i < frames; i++) {
setLayout->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "oit_set"); setLayout->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "oit_set");
@ -168,7 +117,6 @@ void
Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx) Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
translucentctx_t *tctx = ctx->translucent_context; translucentctx_t *tctx = ctx->translucent_context;
if (tctx->resources) { if (tctx->resources) {
@ -177,7 +125,6 @@ Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx)
tctx->resources = 0; tctx->resources = 0;
} }
dfunc->vkDestroyPipeline (device->dev, tctx->pipeline, 0);
free (tctx->frames.a); free (tctx->frames.a);
free (tctx); free (tctx);
} }