[vulkan] Implement lighting and compose passes

Lighting doesn't actually do lights yet, but it's producing pixels.
Translucent seems to be working (2d draw uses it), and compose seems to
be working.
This commit is contained in:
Bill Currie 2021-02-24 19:58:31 +09:00
parent 9229b67633
commit 10a1b99a92
17 changed files with 930 additions and 29 deletions

View file

@ -179,6 +179,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindIndexBuffer)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindDescriptorSets)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDraw)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDrawIndexed)
#undef DEVICE_LEVEL_VULKAN_FUNCTION

View file

@ -0,0 +1,62 @@
/*
qf_compose.h
Vulkan compose pass
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2021/2/24
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
*/
#ifndef __QF_Vulkan_qf_compose_h
#define __QF_Vulkan_qf_compose_h
#include "QF/darray.h"
#include "QF/model.h"
#include "QF/modelgen.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
#define COMPOSE_IMAGE_INFOS 2
typedef struct composeframe_s {
VkCommandBuffer cmd;
VkDescriptorImageInfo imageInfo[COMPOSE_IMAGE_INFOS];
VkWriteDescriptorSet descriptors[COMPOSE_IMAGE_INFOS];
} composeframe_t;
typedef struct composeframeset_s
DARRAY_TYPE (composeframe_t) composeframeset_t;
typedef struct composectx_s {
composeframeset_t frames;
VkPipeline pipeline;
VkPipelineLayout layout;
} composectx_t;
struct vulkan_ctx_s;
void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_Compose_Draw (struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_compose_h

View file

@ -0,0 +1,65 @@
/*
qf_lighting.h
Vulkan lighting pass
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2021/2/23
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
*/
#ifndef __QF_Vulkan_qf_lighting_h
#define __QF_Vulkan_qf_lighting_h
#include "QF/darray.h"
#include "QF/model.h"
#include "QF/modelgen.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
#define LIGHTING_BUFFER_INFOS 1
#define LIGHTING_IMAGE_INFOS 3
typedef struct lightingframe_s {
VkCommandBuffer cmd;
VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS];
VkDescriptorImageInfo imageInfo[LIGHTING_IMAGE_INFOS];
VkWriteDescriptorSet descriptors[LIGHTING_BUFFER_INFOS
+ LIGHTING_IMAGE_INFOS];
} lightingframe_t;
typedef struct lightingframeset_s
DARRAY_TYPE (lightingframe_t) lightingframeset_t;
typedef struct lightingctx_s {
lightingframeset_t frames;
VkPipeline pipeline;
VkPipelineLayout layout;
} lightingctx_t;
struct vulkan_ctx_s;
void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Draw (struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_lighting_h

View file

@ -79,6 +79,11 @@ typedef struct vulkan_ctx_s {
struct aliasctx_s *alias_context;
struct bspctx_s *bsp_context;
struct drawctx_s *draw_context;
struct lightingctx_s *lighting_context;
struct composectx_s *compose_context;
VkBuffer quad_buffer;
VkDeviceMemory quad_memory;
VkCommandPool cmdpool;
VkCommandBuffer cmdbuffer;

View file

@ -240,7 +240,9 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \
libs/video/renderer/vulkan/vkparse.c \
libs/video/renderer/vulkan/vulkan_alias.c \
libs/video/renderer/vulkan/vulkan_bsp.c \
libs/video/renderer/vulkan/vulkan_compose.c \
libs/video/renderer/vulkan/vulkan_draw.c \
libs/video/renderer/vulkan/vulkan_lighting.c \
libs/video/renderer/vulkan/vulkan_lightmap.c \
libs/video/renderer/vulkan/vulkan_main.c \
libs/video/renderer/vulkan/vulkan_matrices.c \
@ -285,6 +287,10 @@ bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag
bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc
bsp_skyf_src = $(vkshaderpath)/bsp_sky.frag
bsp_skyf_c = $(vkshaderpath)/bsp_sky.frag.spvc
lightingf_src = $(vkshaderpath)/lighting.frag
lightingf_c = $(vkshaderpath)/lighting.frag.spvc
composef_src = $(vkshaderpath)/compose.frag
composef_c = $(vkshaderpath)/compose.frag.spvc
aliasv_src = $(vkshaderpath)/alias.vert
aliasv_c = $(vkshaderpath)/alias.vert.spvc
aliasf_src = $(vkshaderpath)/alias.frag
@ -316,6 +322,10 @@ $(bsp_gbuff_c): $(bsp_gbuff_src)
$(bsp_skyf_c): $(bsp_skyf_src)
$(lightingf_c): $(lightingf_src)
$(composef_c): $(composef_src)
$(aliasv_c): $(aliasv_src)
$(alias_depth_c): $(alias_depth_src)
@ -338,6 +348,8 @@ vkshader_c = \
$(bsp_gbufg_c) \
$(bsp_gbuff_c) \
$(bsp_skyf_c) \
$(lightingf_c) \
$(composef_c) \
$(aliasv_c) \
$(alias_depth_c) \
$(aliasf_c) \

View file

@ -38,7 +38,9 @@
#include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_bsp.h"
#include "QF/Vulkan/qf_compose.h"
#include "QF/Vulkan/qf_draw.h"
#include "QF/Vulkan/qf_lighting.h"
#include "QF/Vulkan/qf_lightmap.h"
#include "QF/Vulkan/qf_main.h"
#include "QF/Vulkan/qf_particles.h"
@ -98,6 +100,8 @@ vulkan_R_Init (void)
Vulkan_Bsp_Init (vulkan_ctx);
Vulkan_Draw_Init (vulkan_ctx);
Vulkan_Particles_Init (vulkan_ctx);
Vulkan_Lighting_Init (vulkan_ctx);
Vulkan_Compose_Init (vulkan_ctx);
Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain,
vulkan_ctx->swapchain->numImages);
@ -140,6 +144,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs)
Vulkan_FlushText (vulkan_ctx);
Vulkan_Lighting_Draw (vulkan_ctx);
Vulkan_Compose_Draw (vulkan_ctx);
VkCommandBufferBeginInfo beginInfo
= { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
VkRenderPassBeginInfo renderPassInfo = {
@ -602,6 +609,8 @@ vulkan_vid_render_shutdown (void)
QFV_DeviceWaitIdle (device);
df->vkDestroyFence (dev, vulkan_ctx->fence, 0);
df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0);
Vulkan_Compose_Shutdown (vulkan_ctx);
Vulkan_Lighting_Shutdown (vulkan_ctx);
Vulkan_Draw_Shutdown (vulkan_ctx);
Vulkan_Bsp_Shutdown (vulkan_ctx);
Vulkan_Alias_Shutdown (vulkan_ctx);

View file

@ -179,7 +179,7 @@
{
format = $properties.images.depth.format;
samples = 1;
loadOp = dont_care;
loadOp = clear;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
@ -238,14 +238,14 @@
},
);
subpasses = (
{ // depth
{ // 0 depth
pipelineBindPoint = graphics;
depthStencilAttachment = {
attachment = 0;
layout = depth_stencil_attachment_optimal;
};
},
{ // g-buffer generation
{ // 1 g-buffer generation
pipelineBindPoint = graphics;
colorAttachments = (
{ // color
@ -261,8 +261,9 @@
attachment = 0;
layout = depth_stencil_attachment_optimal;
};
preserveAttachments = (4);
},
{ // lighting
{ // 2 lighting
pipelineBindPoint = graphics;
inputAttachments = (
{ // depth
@ -284,8 +285,9 @@
layout = color_attachment_optimal;
},
);
preserveAttachments = (4);
},
{ // translucent
{ // 3 translucent
pipelineBindPoint = graphics;
colorAttachments = (
{ // translucent
@ -293,8 +295,9 @@
layout = color_attachment_optimal;
},
);
preserveAttachments = (0, 1, 2, 3);
},
{ // compose
{ // 4 compose
pipelineBindPoint = graphics;
inputAttachments = (
{ // opaque
@ -312,12 +315,13 @@
layout = color_attachment_optimal;
},
);
preserveAttachments = (0, 1, 2);
},
);
dependencies = (
{
srcSubpass = 0;
dstSubpass = 1;
srcSubpass = 0; // depth
dstSubpass = 1; // g-buffer
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
@ -325,8 +329,8 @@
dependencyFlags = by_region;
},
{
srcSubpass = 1;
dstSubpass = 2;
srcSubpass = 1; // g-buffer
dstSubpass = 2; // lighting
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
@ -334,8 +338,8 @@
dependencyFlags = by_region;
},
{
srcSubpass = 2;
dstSubpass = 4;
srcSubpass = 2; // lighting
dstSubpass = 4; // compose
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
@ -343,8 +347,8 @@
dependencyFlags = by_region;
},
{
srcSubpass = 3;
dstSubpass = 4;
srcSubpass = 3; // translucent
dstSubpass = 4; // compose
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;

View file

@ -77,6 +77,36 @@
},
);
};
lighting_attach_pool = {
flags = 0;
maxSets = $frames.size;
bindings = (
{
type = input_attachment;
descriptorCount = "3z * $frames.size";
},
);
};
lighting_lights_pool = {
flags = 0;
maxSets = $frames.size;
bindings = (
{
type = uniform_buffer;
descriptorCount = $frames.size;
},
);
};
compose_attach_pool = {
flags = 0;
maxSets = $frames.size;
bindings = (
{
type = input_attachment;
descriptorCount = "2z * $frames.size";
},
);
};
};
setLayouts = {
twod_set = {
@ -208,20 +238,51 @@
},
);
};
something = {
flags = 0;
lighting_attach = {
bindings = (
{
binding = 0;
descriptorType = sampled_image;
descriptorType = input_attachment;
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 1;
descriptorType = input_attachment;
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 2;
descriptorType = input_attachment;
descriptorCount = 1;
stageFlags = fragment;
},
);
};
lighting_lights = {
bindings = (
{
binding = 0;
descriptorType = uniform_buffer;
descriptorCount = 1;
stageFlags = vertex;
stageFlags = fragment;
},
);
};
compose_attach = {
bindings = (
{
binding = 0;
descriptorType = input_attachment;
descriptorCount = 1;
stageFlags = fragment;
},
{
binding = 1;
descriptorType = input_attachment;
descriptorCount = 1;
stageFlags = fragment;
},
);
};
@ -261,15 +322,11 @@
},
);
};
something = {
setLayouts = (something);
pushConstantRanges = (
{
stageFlags = fragment;
offset = 0;
size = "4 * 4";
},
);
lighting_layout = {
setLayouts = (lighting_attach, lighting_lights);
};
compose_layout = {
setLayouts = (compose_attach);
};
};
pipelines = {
@ -758,6 +815,194 @@
layout = twod_layout;
//renderPass = renderpass;
};
lighting = {
subpass = 2;
stages = (
{
stage = vertex;
name = main;
module = $builtin/passthrough.vert;
},
{
stage = fragment;
name = main;
module = $builtin/lighting.frag;
},
);
vertexInput = {
bindings = (
{
binding = 0;
stride = "4 * 4";
inputRate = vertex;
},
);
attributes = (
{
location = 0;
binding = 0;
format = r32g32b32a32_sfloat;
offset = 0;
},
);
};
inputAssembly = {
topology = triangle_strip;
primitiveRestartEnable = false;
};
viewport = {
viewports = (
{
x = 0; y = 0;
width = 640; height = 480;
minDepth = 0; maxDepth = 1;
}
);
scissors = (
{
offset = { x = 0; y = 0 };
extent = { width = 640; height = 480; };
},
);
};
rasterization = {
depthClampEnable = false;
rasterizerDiscardEnable = false;
polygonMode = fill;
cullMode = back;
frontFace = counter_clockwise;
depthBiasEnable = false;
lineWidth = 1;
};
multisample = {
rasterizationSamples = $msaaSamples;
sampleShadingEnable = false;
minSampleShading = 0.5f;
alphaToCoverageEnable = false;
alphaToOneEnable = false;
};
depthStencil = {
depthTestEnable = false;
depthWriteEnable = false;
depthCompareOp = less_or_equal;
depthBoundsTestEnable = false;
stencilTestEnable = false;
};
colorBlend = {
logicOpEnable = false;
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;
},
);
};
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = lighting_layout;
//renderPass = renderpass;
};
compose = {
subpass = 4;
stages = (
{
stage = vertex;
name = main;
module = $builtin/passthrough.vert;
},
{
stage = fragment;
name = main;
module = $builtin/compose.frag;
},
);
vertexInput = {
bindings = (
{
binding = 0;
stride = "4 * 4";
inputRate = vertex;
},
);
attributes = (
{
location = 0;
binding = 0;
format = r32g32b32a32_sfloat;
offset = 0;
},
);
};
inputAssembly = {
topology = triangle_strip;
primitiveRestartEnable = false;
};
viewport = {
viewports = (
{
x = 0; y = 0;
width = 640; height = 480;
minDepth = 0; maxDepth = 1;
}
);
scissors = (
{
offset = { x = 0; y = 0 };
extent = { width = 640; height = 480; };
},
);
};
rasterization = {
depthClampEnable = false;
rasterizerDiscardEnable = false;
polygonMode = fill;
cullMode = back;
frontFace = counter_clockwise;
depthBiasEnable = false;
lineWidth = 1;
};
multisample = {
rasterizationSamples = $msaaSamples;
sampleShadingEnable = false;
minSampleShading = 0.5f;
alphaToCoverageEnable = false;
alphaToOneEnable = false;
};
depthStencil = {
depthTestEnable = false;
depthWriteEnable = false;
depthCompareOp = less_or_equal;
depthBoundsTestEnable = false;
stencilTestEnable = false;
};
colorBlend = {
logicOpEnable = false;
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;
},
);
};
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = compose_layout;
//renderPass = renderpass;
};
};
renderpass = {
attachments = (

View file

@ -73,6 +73,10 @@ static
static
#include "libs/video/renderer/vulkan/shader/bsp_sky.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/lighting.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/compose.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/alias.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc"
@ -101,6 +105,8 @@ static shaderdata_t builtin_shaders[] = {
{ "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) },
{ "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) },
{ "bsp_sky.frag", bsp_sky_frag, sizeof (bsp_sky_frag) },
{ "lighting.frag", lighting_frag, sizeof (lighting_frag) },
{ "compose.frag", compose_frag, sizeof (compose_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 (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;
void
main (void)
{
vec3 o;
vec4 t;
vec3 c;
o = subpassLoad (opaque).rgb;
t = subpassLoad (translucent);
c = mix (o, t.rgb, t.a);
frag_color = vec4 (c, 1);
}

View file

@ -0,0 +1,33 @@
#version 450
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;
struct LightData {
vec3 color;
float dist;
vec3 position;
int type;
vec3 direction;
float cone;
};
layout (constant_id = 0) const int MaxLights = 8;
/*layout (set = 1, binding = 0) uniform Lights {
int lightCount;
LightData lights[MaxLights];
};*/
layout (location = 0) out vec4 frag_color;
void
main (void)
{
float d = subpassLoad (depth).r;
vec4 c;
//c = vec4 (d, d, d, 1);
c = vec4 (subpassLoad (color).rgb, 1);
frag_color = c;
}

View file

@ -1259,6 +1259,8 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties)
dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]);
const char *name = PL_KeyAtIndex (item, i);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, set->a[i],
va (ctx->va_ctx, "image:%s", name));
name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name);
QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]);
}

View file

@ -176,8 +176,7 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline,
};
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
//VkDescriptorSet sets[] = {
// aframe->descriptors[0].dstSet,
// aframe->descriptors[1].dstSet,

View file

@ -827,6 +827,15 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc,
continue;
dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index,
0, 0);
}
}
static void
reset_elechain (elechain_t *ec)
{
elements_t *el;
for (el = ec->elements; el; el = el->next) {
el->first_index = 0;
el->index_count = 0;
}
@ -1167,6 +1176,7 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx)
bframe->cmdSet.a[QFV_bspDepth]);
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspGBuffer]);
reset_elechain (ec);
}
tex->elechain = 0;
tex->elechain_tail = &tex->elechain;
@ -1280,6 +1290,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx)
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,//FIXME
bframe->cmdSet.a[QFV_bspTranslucent]);
reset_elechain (ec);
}
tex->elechain = 0;
tex->elechain_tail = &tex->elechain;
@ -1295,6 +1306,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx)
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,//FIXME
bframe->cmdSet.a[QFV_bspTranslucent]);
reset_elechain (ec);
}
tex->elechain = 0;
tex->elechain_tail = &tex->elechain;

View file

@ -0,0 +1,175 @@
/*
vulkan_compose.c
Vulkan compose pass pipeline
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2021/2/23
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/sys.h"
#include "QF/Vulkan/qf_compose.h"
#include "QF/Vulkan/debug.h"
#include "QF/Vulkan/descriptor.h"
#include "QF/Vulkan/device.h"
#include "QF/Vulkan/image.h"
#include "r_internal.h"
#include "vid_vulkan.h"
void
Vulkan_Compose_Draw (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
composectx_t *cctx = ctx->compose_context;
__auto_type frame = &ctx->frames.a[ctx->curFrame];
composeframe_t *cframe = &cctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = cframe->cmd;
DARRAY_APPEND (&frame->cmdSets[QFV_passCompose], cmd);
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass, QFV_passCompose,
frame->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);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
cctx->pipeline);
cframe->imageInfo[0].imageView = ctx->attachment_views->a[3];
cframe->imageInfo[1].imageView = ctx->attachment_views->a[4];
dfunc->vkUpdateDescriptorSets (device->dev, 2, cframe->descriptors, 0, 0);
VkDescriptorSet sets[] = {
cframe->descriptors[0].dstSet,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
cctx->layout, 0, 1, sets, 0, 0);
VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1};
VkRect2D scissor = { {0, 0}, {vid.width, vid.height} };
dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor);
VkDeviceSize offset = 0;
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset);
dfunc->vkCmdDraw (cmd, 4, 1, 0, 0);
dfunc->vkEndCommandBuffer (cmd);
}
static VkDescriptorImageInfo base_image_info = {
0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
};
static VkWriteDescriptorSet base_image_write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
0, 0, 1,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
0, 0, 0
};
void
Vulkan_Compose_Init (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
composectx_t *cctx = calloc (1, sizeof (composectx_t));
ctx->compose_context = cctx;
size_t frames = ctx->frames.size;
DARRAY_INIT (&cctx->frames, frames);
DARRAY_RESIZE (&cctx->frames, frames);
cctx->frames.grow = 0;
cctx->pipeline = Vulkan_CreatePipeline (ctx, "compose");
cctx->layout = Vulkan_CreatePipelineLayout (ctx, "compose_layout");
__auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca);
__auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
for (size_t i = 0; i < frames; i++) {
attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx,
"compose_attach");
}
__auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx,
"compose_attach_pool");
__auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool,
attach);
for (size_t i = 0; i < frames; i++) {
__auto_type cframe = &cctx->frames.a[i];
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet);
cframe->cmd = cmdSet->a[0];
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
cframe->cmd, "cmd:compose");
for (int j = 0; j < COMPOSE_IMAGE_INFOS; j++) {
cframe->imageInfo[j] = base_image_info;
cframe->imageInfo[j].sampler = 0;
cframe->descriptors[j] = base_image_write;
cframe->descriptors[j].dstSet = attach_set->a[i];
cframe->descriptors[j].dstBinding = j;
cframe->descriptors[j].pImageInfo = &cframe->imageInfo[j];
}
}
free (attach_set);
}
void
Vulkan_Compose_Shutdown (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
composectx_t *cctx = ctx->compose_context;
dfunc->vkDestroyPipeline (device->dev, cctx->pipeline, 0);
free (cctx->frames.a);
free (cctx);
}

View file

@ -0,0 +1,202 @@
/*
vulkan_lighting.c
Vulkan lighting pass pipeline
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2021/2/23
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/sys.h"
#include "QF/Vulkan/qf_lighting.h"
#include "QF/Vulkan/debug.h"
#include "QF/Vulkan/descriptor.h"
#include "QF/Vulkan/device.h"
#include "QF/Vulkan/image.h"
#include "r_internal.h"
#include "vid_vulkan.h"
void
Vulkan_Lighting_Draw (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
lightingctx_t *lctx = ctx->lighting_context;
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = lframe->cmd;
DARRAY_APPEND (&cframe->cmdSets[QFV_passLighting], cmd);
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass, QFV_passLighting,
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);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
lctx->pipeline);
lframe->imageInfo[0].imageView = ctx->attachment_views->a[0];
lframe->imageInfo[1].imageView = ctx->attachment_views->a[1];
lframe->imageInfo[2].imageView = ctx->attachment_views->a[2];
dfunc->vkUpdateDescriptorSets (device->dev, 3, lframe->descriptors+1, 0, 0);
VkDescriptorSet sets[] = {
lframe->descriptors[1].dstSet,
lframe->descriptors[0].dstSet,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
lctx->layout, 0, 2, sets, 0, 0);
VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1};
VkRect2D scissor = { {0, 0}, {vid.width, vid.height} };
dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor);
VkDeviceSize offset = 0;
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset);
dfunc->vkCmdDraw (cmd, 4, 1, 0, 0);
dfunc->vkEndCommandBuffer (cmd);
}
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_INPUT_ATTACHMENT,
0, 0, 0
};
void
Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t));
ctx->lighting_context = lctx;
size_t frames = ctx->frames.size;
DARRAY_INIT (&lctx->frames, frames);
DARRAY_RESIZE (&lctx->frames, frames);
lctx->frames.grow = 0;
lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting");
lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout");
__auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca);
__auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
__auto_type lights = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
for (size_t i = 0; i < frames; i++) {
attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx,
"lighting_attach");
lights->a[i] = Vulkan_CreateDescriptorSetLayout (ctx,
"lighting_lights");
}
__auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx,
"lighting_attach_pool");
__auto_type lights_pool = Vulkan_CreateDescriptorPool (ctx,
"lighting_lights_pool");
__auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool,
attach);
__auto_type lights_set = QFV_AllocateDescriptorSet (device, lights_pool,
lights);
for (size_t i = 0; i < frames; i++) {
__auto_type lframe = &lctx->frames.a[i];
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet);
lframe->cmd = cmdSet->a[0];
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
lframe->cmd, "cmd:lighting");
for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) {
lframe->bufferInfo[j] = base_buffer_info;
lframe->descriptors[j] = base_buffer_write;
lframe->descriptors[j].dstSet = lights_set->a[i];
lframe->descriptors[j].dstBinding = j;
lframe->descriptors[j].pBufferInfo = &lframe->bufferInfo[j];
}
for (int j = 0; j < LIGHTING_IMAGE_INFOS; j++) {
lframe->imageInfo[j] = base_image_info;
lframe->imageInfo[j].sampler = 0;
int k = j + LIGHTING_BUFFER_INFOS;
lframe->descriptors[k] = base_image_write;
lframe->descriptors[k].dstSet = attach_set->a[i];
lframe->descriptors[k].dstBinding = j;
lframe->descriptors[k].pImageInfo = &lframe->imageInfo[j];
}
}
free (attach_set);
free (lights_set);
}
void
Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
lightingctx_t *lctx = ctx->lighting_context;
dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0);
free (lctx->frames.a);
free (lctx);
}

View file

@ -324,6 +324,53 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
item = qfv_load_renderpass (ctx, "clearValues");
QFV_ParseClearValues (ctx, item, ctx->renderpassDef);
printf ("renderpass: %p\n", ctx->renderpass);
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
static float quad_vertices[] = {
-1, -1, 0, 1,
-1, 1, 0, 1,
1, -1, 0, 1,
1, 1, 0, 1,
};
ctx->quad_buffer = QFV_CreateBuffer (device, sizeof (quad_vertices),
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT);
ctx->quad_memory = QFV_AllocBufferMemory (device, ctx->quad_buffer,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
0, 0);
QFV_BindBufferMemory (device, ctx->quad_buffer, ctx->quad_memory, 0);
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
float *verts = QFV_PacketExtend (packet, sizeof (quad_vertices));
memcpy (verts, quad_vertices, sizeof (quad_vertices));
VkBufferMemoryBarrier wr_barriers[] = {
{ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0,
0, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
ctx->quad_buffer, 0, sizeof (quad_vertices) },
};
dfunc->vkCmdPipelineBarrier (packet->cmd,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0, 0, 0, 1, wr_barriers, 0, 0);
VkBufferCopy copy_region[] = {
{ packet->offset, 0, sizeof (quad_vertices) },
};
dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer,
ctx->quad_buffer, 1, &copy_region[0]);
VkBufferMemoryBarrier rd_barriers[] = {
{ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
ctx->quad_buffer, 0, sizeof (quad_vertices) },
};
dfunc->vkCmdPipelineBarrier (packet->cmd,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
0, 0, 0, 1, rd_barriers, 0, 0);
QFV_PacketSubmit (packet);
}
void
@ -333,6 +380,9 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
qfv_devfuncs_t *dfunc = device->funcs;
dfunc->vkDestroyRenderPass (device->dev, ctx->renderpass, 0);
dfunc->vkFreeMemory (device->dev, ctx->quad_memory, 0);
dfunc->vkDestroyBuffer (device->dev, ctx->quad_buffer, 0);
}
VkPipeline