[vulkan] Add a module to handle output

When working, this will handle the output to the swap-chain images and
any final post-processing effects (gamma correction, screen scaling,
etc). However, currently the screen is just black because the image
for getting the main render pass output isn't hooked up yet.
This commit is contained in:
Bill Currie 2022-11-22 17:47:36 +09:00
parent 7b15caee04
commit 2cee2f2ab8
13 changed files with 626 additions and 8 deletions

View file

@ -42,6 +42,9 @@ typedef struct qfv_matrix_buffer_s {
mat4f_t View; mat4f_t View;
mat4f_t Sky; mat4f_t Sky;
mat4f_t Projection2d; mat4f_t Projection2d;
vec2f_t ScreenSize;
vec2f_t pad; //FIXME shouldn't need this (for gpu align)
vec4f_t pad2[3];
} qfv_matrix_buffer_t; } qfv_matrix_buffer_t;
#define LIGHTING_BUFFER_INFOS 1 #define LIGHTING_BUFFER_INFOS 1

View file

@ -0,0 +1,59 @@
/*
qf_output.h
Vulkan output pass
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/11/21
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_output_h
#define __QF_Vulkan_qf_output_h
#include "QF/darray.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
typedef struct outputframe_s {
VkCommandBuffer cmd;
VkImageView view;
VkDescriptorSet set;
} outputframe_t;
typedef struct outputframeset_s
DARRAY_TYPE (outputframe_t) outputframeset_t;
typedef struct outputctx_s {
outputframeset_t frames;
VkPipeline pipeline;
VkPipelineLayout layout;
VkSampler sampler;
} outputctx_t;
struct vulkan_ctx_s;
void Vulkan_Output_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_Output_CreateRenderPasses (struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_output_h

View file

@ -40,6 +40,7 @@
enum { enum {
QFV_rp_shadowmap, QFV_rp_shadowmap,
QFV_rp_preoutput,
QFV_rp_main, QFV_rp_main,
QFV_rp_output, QFV_rp_output,
}; };

View file

@ -75,14 +75,14 @@ typedef struct vulkan_ctx_s {
struct drawctx_s *draw_context; struct drawctx_s *draw_context;
struct lightingctx_s *lighting_context; struct lightingctx_s *lighting_context;
struct composectx_s *compose_context; struct composectx_s *compose_context;
struct outputctx_s *output_context;
VkCommandPool cmdpool; VkCommandPool cmdpool;
struct qfv_stagebuf_s *staging; struct qfv_stagebuf_s *staging;
size_t curFrame; size_t curFrame;
vulkan_frameset_t frames; vulkan_frameset_t frames;
qfv_renderpassset_t renderPasses; qfv_renderpassset_t renderPasses;
//FIXME for resize, but should be a set struct qfv_renderpass_s *output_renderpass;
struct qfv_renderpass_s *main_renderpass;
struct qfv_capture_s *capture; struct qfv_capture_s *capture;
void (*capture_callback) (const byte *data, int width, int height); void (*capture_callback) (const byte *data, int width, int height);

View file

@ -195,10 +195,14 @@ libs_video_renderer_librender_sw_la_SOURCES = \
pl_quake_def_src = libs/video/renderer/vulkan/pl_quake_def.plist pl_quake_def_src = libs/video/renderer/vulkan/pl_quake_def.plist
pl_quake_def_gen = libs/video/renderer/vulkan/pl_quake_def.plc pl_quake_def_gen = libs/video/renderer/vulkan/pl_quake_def.plc
pl_output_src = libs/video/renderer/vulkan/pl_output.plist
pl_output_gen = libs/video/renderer/vulkan/pl_output.plc
rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist
rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc
rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist
rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc
rp_output_src = libs/video/renderer/vulkan/rp_output.plist
rp_output_gen = libs/video/renderer/vulkan/rp_output.plc
rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist
rp_shadow_gen = libs/video/renderer/vulkan/rp_shadow.plc rp_shadow_gen = libs/video/renderer/vulkan/rp_shadow.plc
@ -243,6 +247,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
libs/video/renderer/vulkan/vulkan_lighting.c \ libs/video/renderer/vulkan/vulkan_lighting.c \
libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_main.c \
libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_matrices.c \
libs/video/renderer/vulkan/vulkan_output.c \
libs/video/renderer/vulkan/vulkan_palette.c \ libs/video/renderer/vulkan/vulkan_palette.c \
libs/video/renderer/vulkan/vulkan_particles.c \ libs/video/renderer/vulkan/vulkan_particles.c \
libs/video/renderer/vulkan/vulkan_renderpass.c \ libs/video/renderer/vulkan/vulkan_renderpass.c \
@ -259,8 +264,10 @@ libs/video/renderer/vulkan/vulkan_vid_common.lo: \
libs/video/renderer/vulkan/vulkan_vid_common.c \ libs/video/renderer/vulkan/vulkan_vid_common.c \
$(vkparse_src) \ $(vkparse_src) \
$(pl_quake_def_gen) \ $(pl_quake_def_gen) \
$(pl_output_gen) \
${rp_deferred_gen} \ ${rp_deferred_gen} \
$(rp_forward_gen) \ $(rp_forward_gen) \
$(rp_output_gen) \
${rp_shadow_gen} ${rp_shadow_gen}
@ -346,6 +353,8 @@ iqmv_src = $(vkshaderpath)/iqm.vert
iqmv_c = $(vkshaderpath)/iqm.vert.spvc iqmv_c = $(vkshaderpath)/iqm.vert.spvc
iqmf_src = $(vkshaderpath)/iqm.frag iqmf_src = $(vkshaderpath)/iqm.frag
iqmf_c = $(vkshaderpath)/iqm.frag.spvc iqmf_c = $(vkshaderpath)/iqm.frag.spvc
output_src = $(vkshaderpath)/output.frag
output_c = $(vkshaderpath)/output.frag.spvc
passthrough_src = $(vkshaderpath)/passthrough.vert passthrough_src = $(vkshaderpath)/passthrough.vert
passthrough_c = $(vkshaderpath)/passthrough.vert.spvc passthrough_c = $(vkshaderpath)/passthrough.vert.spvc
fstriangle_src = $(vkshaderpath)/fstriangle.vert fstriangle_src = $(vkshaderpath)/fstriangle.vert
@ -417,6 +426,8 @@ $(iqmv_c): $(iqmv_src)
$(iqmf_c): $(iqmf_src) $(iqmf_c): $(iqmf_src)
$(output_c): $(output_src)
$(passthrough_c): $(passthrough_src) $(passthrough_c): $(passthrough_src)
$(fstriangle_c): $(fstriangle_src) $(fstriangle_c): $(fstriangle_src)
@ -457,6 +468,7 @@ vkshader_c = \
$(alias_shadow_c) \ $(alias_shadow_c) \
$(iqmv_c) \ $(iqmv_c) \
$(iqmf_c) \ $(iqmf_c) \
$(output_c) \
$(passthrough_c) \ $(passthrough_c) \
$(fstriangle_c) \ $(fstriangle_c) \
$(pushcolor_c) \ $(pushcolor_c) \
@ -494,8 +506,10 @@ BUILT_SOURCES += $(shader_gen)
EXTRA_DIST += \ EXTRA_DIST += \
$(rp_deferred_src) \ $(rp_deferred_src) \
$(rp_forward_src) \ $(rp_forward_src) \
$(rp_output_src) \
$(rp_shadow_src) \ $(rp_shadow_src) \
$(pl_quake_def_src) \ $(pl_quake_def_src) \
$(pl_output_src) \
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 \

View file

@ -50,6 +50,7 @@
#include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_lightmap.h"
#include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_main.h"
#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_matrices.h"
#include "QF/Vulkan/qf_output.h"
#include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_palette.h"
#include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_particles.h"
#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_renderpass.h"
@ -94,7 +95,9 @@ vulkan_R_Init (void)
Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx);
Vulkan_CreateCapture (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx);
Vulkan_CreateRenderPasses (vulkan_ctx); Vulkan_CreateRenderPasses (vulkan_ctx);
Vulkan_Output_Init (vulkan_ctx);
Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Matrix_Init (vulkan_ctx);
Vulkan_Scene_Init (vulkan_ctx); Vulkan_Scene_Init (vulkan_ctx);
@ -318,11 +321,11 @@ vulkan_begin_frame (void)
.format = vulkan_ctx->swapchain->format, .format = vulkan_ctx->swapchain->format,
.view_list = vulkan_ctx->swapchain->imageViews->a, .view_list = vulkan_ctx->swapchain->imageViews->a,
}; };
vulkan_ctx->main_renderpass->viewport.width = output.extent.width; vulkan_ctx->output_renderpass->viewport.width = output.extent.width;
vulkan_ctx->main_renderpass->viewport.height = output.extent.height; vulkan_ctx->output_renderpass->viewport.height = output.extent.height;
vulkan_ctx->main_renderpass->scissor.extent = output.extent; vulkan_ctx->output_renderpass->scissor.extent = output.extent;
vulkan_ctx->output = output; vulkan_ctx->output = output;
Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->main_renderpass); Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->output_renderpass);
QFV_AcquireNextImage (vulkan_ctx->swapchain, QFV_AcquireNextImage (vulkan_ctx->swapchain,
frame->imageAvailableSemaphore, frame->imageAvailableSemaphore,
0, &imageIndex); 0, &imageIndex);
@ -373,7 +376,7 @@ vulkan_set_2d (int scaled)
float right = left + vid.width / scale; float right = left + vid.width / scale;
float bottom = top + vid.height / scale; float bottom = top + vid.height / scale;
QFV_Orthographic (mat->Projection2d, left, right, top, bottom, 0, 99999); QFV_Orthographic (mat->Projection2d, left, right, top, bottom, 0, 99999);
mat->ScreenSize = (vec2f_t) { 1.0 / vid.width, 1.0 / vid.height };
mctx->dirty = mctx->frames.size; mctx->dirty = mctx->frames.size;
} }
@ -776,6 +779,7 @@ vulkan_vid_render_shutdown (void)
Vulkan_Matrix_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx);
Vulkan_DestroyRenderPasses (vulkan_ctx); Vulkan_DestroyRenderPasses (vulkan_ctx);
Vulkan_Output_Shutdown (vulkan_ctx);
Vulkan_Palette_Shutdown (vulkan_ctx); Vulkan_Palette_Shutdown (vulkan_ctx);
Vulkan_Texture_Shutdown (vulkan_ctx); Vulkan_Texture_Shutdown (vulkan_ctx);

View file

@ -0,0 +1,209 @@
{
samplers = {
linear = {
magFilter = linear;
minFilter = linear;
mipmapMode = linear;
addressModeU = clamp_to_edge;
addressModeV = clamp_to_edge;
addressModeW = clamp_to_edge;
mipLodBias = 0;
anisotropyEnable = false;
maxAnisotropy = 0;
compareEnable = false;
compareOp = always;
minLod = 0;
maxLod = 0;
borderColor = float_transparent_black;
unnormalizedCoordinates = false;
};
};
descriptorPools = {
output_pool = {
flags = 0;
maxSets = "$frames.size * 2z";
bindings = (
{
type = combined_image_sampler;
descriptorCount = "$frames.size * 2z";
},
);
};
};
setLayouts = {
matrix_set = {
bindings = (
{
binding = 0;
descriptorType = uniform_buffer;
descriptorCount = 1;
stageFlags = vertex|geometry|fragment;
},
);
};
output_set = {
bindings = (
{
binding = 0;
descriptorType = combined_image_sampler;
descriptorCount = 1;
stageFlags = fragment;
},
);
};
};
pipelineLayouts = {
output_layout = {
setLayouts = (matrix_set, output_set);
};
};
depthStencil = {
disable = {
depthTestEnable = false;
depthWriteEnable = false;
depthCompareOp = less_or_equal;
depthBoundsTestEnable = false;
stencilTestEnable = false;
};
};
inputAssembly = {
};
vertexInput = {
index_only = {
bindings = ();
attributes = ();
};
};
rasterization = {
cw_cull_back = {
depthClampEnable = false;
rasterizerDiscardEnable = false;
polygonMode = fill;
cullMode = back;
frontFace = clockwise;
depthBiasEnable = false;
lineWidth = 1;
};
counter_cw_cull_back = {
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;
};
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; };
},
);
};
attachmentBlendOp = {
disabled = {
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;
};
alpha_blend = {
blendEnable = true;
srcColorBlendFactor = one;
dstColorBlendFactor = one_minus_src_alpha;
colorBlendOp = add;
srcAlphaBlendFactor = one;
dstAlphaBlendFactor = one_minus_src_alpha;
alphaBlendOp = add;
colorWriteMask = r|g|b|a;
};
};
fstriangle = {
vertexStage = {
stage = vertex;
name = main;
module = $builtin/fstriangle.vert;
};
vertexInput = {
bindings = ();
attributes = ();
};
inputAssembly = {
topology = triangle_list;
primitiveRestartEnable = false;
};
colorBlend = {
logicOpEnable = false;
attachments = ($properties.attachmentBlendOp.disabled);
};
};
pipelines = {
base = {
viewport = $properties.viewport;
rasterization = $properties.rasterization.counter_cw_cull_back;
multisample = $properties.multisample;
depthStencil = $properties.depthStencil.disable;
colorBlend = {
logicOpEnable = false;
attachments = (
$properties.attachmentBlendOp.disabled,
$properties.attachmentBlendOp.disabled,
$properties.attachmentBlendOp.disabled,
$properties.attachmentBlendOp.disabled,
);
};
dynamic = {
dynamicState = ( viewport, scissor );
};
renderPass = output;
};
output_base = {
@inherit = $properties.pipelines.base;
vertexInput = $properties.fstriangle.vertexInput;
inputAssembly = $properties.fstriangle.inputAssembly;
colorBlend = $properties.fstriangle.colorBlend;
};
output = {
@inherit = $properties.pipelines.output_base;
subpass = 0;
stages = (
$properties.fstriangle.vertexStage,
{
stage = fragment;
name = main;
module = $builtin/output.frag;
},
);
layout = output_layout;
};
};
}

View file

@ -0,0 +1,90 @@
{
flat_color_image_template = {
imageType = `2d;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|sampled;
initialLayout = undefined;
};
images = {
color = {
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
};
};
flat_color_view_template = {
viewType = VK_IMAGE_VIEW_TYPE_2D;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
imageViews = {
color = {
@inherit = $properties.flat_color_view_template;
image = color;
format = $properties.images.color.format;
};
};
framebuffer = {
renderPass = output;
attachments = ($output.view);
width = $output.extent.width;
height = $output.extent.height;
layers = 1;
};
clearValues = (
{ color = "[0, 0, 0, 1]"; }, // output
);
attachment_template = {
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
};
info = {
color = "[0.9, 0.9, 0.9, 1]";
subpass_info = (
{ name = compose; color = "[ 0.9, 0.9, 0.9, 1]" },
);
};
renderpass = {
attachments = (
{
@inherit = $properties.attachment_template;
format = $output.format;
loadOp = clear;
storeOp = store;
finalLayout = present_src_khr;
},
);
subpasses = (
{ // 0 output
pipelineBindPoint = graphics;
colorAttachments = (
{ // output
attachment = 0;
layout = color_attachment_optimal;
},
);
},
);
};
}

View file

@ -109,6 +109,8 @@ static
static static
#include "libs/video/renderer/vulkan/shader/iqm.frag.spvc" #include "libs/video/renderer/vulkan/shader/iqm.frag.spvc"
static static
#include "libs/video/renderer/vulkan/shader/output.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc" #include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc"
static static
#include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc" #include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc"
@ -157,6 +159,7 @@ static shaderdata_t builtin_shaders[] = {
{ "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) }, { "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) },
{ "iqm.vert", iqm_vert, sizeof (iqm_vert) }, { "iqm.vert", iqm_vert, sizeof (iqm_vert) },
{ "iqm.frag", iqm_frag, sizeof (iqm_frag) }, { "iqm.frag", iqm_frag, sizeof (iqm_frag) },
{ "output.frag", output_frag, sizeof (output_frag) },
{ "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) },
{ "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) },
{ "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) },

View file

@ -0,0 +1,15 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
layout (set = 0, binding = 0) uniform
#include "matrices.h"
;
layout (set = 1, binding = 0) uniform sampler2D Input;
layout (location = 0) out vec4 frag_color;
void
main (void)
{
frag_color = texture (Input, gl_FragCoord.xy * ScreenSize);
}

View file

@ -185,5 +185,4 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx)
&output, main_draw); &output, main_draw);
rp->order = QFV_rp_main; rp->order = QFV_rp_main;
DARRAY_APPEND (&ctx->renderPasses, rp); DARRAY_APPEND (&ctx->renderPasses, rp);
ctx->main_renderpass = rp;
} }

View file

@ -0,0 +1,211 @@
/*
vulkan_main.c
Vulkan output
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/11/21
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 "QF/cvar.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/Vulkan/qf_matrices.h"
#include "QF/Vulkan/qf_output.h"
#include "QF/Vulkan/qf_renderpass.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/debug.h"
#include "QF/Vulkan/descriptor.h"
#include "QF/Vulkan/device.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/instance.h"
#include "QF/Vulkan/swapchain.h"
#include "vid_vulkan.h"
static void
update_input (qfv_renderframe_t *rFrame)
{
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
outputctx_t *octx = ctx->output_context;
uint32_t curFrame = ctx->curFrame;
outputframe_t *oframe = &octx->frames.a[curFrame];
qfv_renderpass_t *rp = ctx->output_renderpass;
if (rp->attachment_views->a[0] == oframe->view) {
return;
}
oframe->view = rp->attachment_views->a[0];
VkDescriptorImageInfo imageInfo = {
octx->sampler, oframe->view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
VkWriteDescriptorSet write[] = {
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
oframe->set, 0, 0, 1,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
&imageInfo, 0, 0 }
};
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
}
static void
output_draw (qfv_renderframe_t *rFrame)
{
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
outputctx_t *octx = ctx->output_context;
outputframe_t *oframe = &octx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = oframe->cmd;
dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
rFrame->renderpass->renderpass, 0,
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, "output:output");
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
octx->pipeline);
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
VkDescriptorSet set[] = {
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
oframe->set,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
octx->layout, 0, 2, set, 0, 0);
dfunc->vkCmdDraw (cmd, 3, 1, 0, 0);
QFV_duCmdEndLabel (device, cmd);
dfunc->vkEndCommandBuffer (cmd);
}
void
Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx)
{
qfv_output_t output = {
.extent = ctx->swapchain->extent,
.view = ctx->swapchain->imageViews->a[0],
.format = ctx->swapchain->format,
.view_list = ctx->swapchain->imageViews->a,
};
__auto_type out = Vulkan_CreateRenderPass (ctx, "output",
&output, output_draw);
out->order = QFV_rp_output;
DARRAY_APPEND (&ctx->renderPasses, out);
ctx->output_renderpass = out;
__auto_type pre = Vulkan_CreateFunctionPass (ctx, "preoutput",
update_input);
pre->order = QFV_rp_preoutput;
DARRAY_APPEND (&ctx->renderPasses, pre);
}
void
Vulkan_Output_Init (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfvPushDebug (ctx, "output init");
outputctx_t *octx = calloc (1, sizeof (outputctx_t));
ctx->output_context = octx;
size_t frames = ctx->frames.size;
DARRAY_INIT (&octx->frames, frames);
DARRAY_RESIZE (&octx->frames, frames);
octx->frames.grow = 0;
__auto_type pld = ctx->pipelineDef;
ctx->pipelineDef = Vulkan_GetConfig (ctx, "qf_output");
octx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "output");
octx->layout = Vulkan_CreatePipelineLayout (ctx, "output_layout");
octx->sampler = Vulkan_CreateSampler (ctx, "linear");
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "output_set");
for (size_t i = 0; i < frames; i++) {
layouts->a[i] = layouts->a[0];
}
__auto_type pool = Vulkan_CreateDescriptorPool (ctx, "output_pool");
__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts);
__auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca);
for (size_t i = 0; i < frames; i++) {
__auto_type oframe = &octx->frames.a[i];
oframe->set = sets->a[i];
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet);
oframe->cmd = cmdSet->a[0];
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
oframe->cmd, "cmd:output");
}
ctx->pipelineDef = pld;
free (sets);
qfvPopDebug (ctx);
}
void
Vulkan_Output_Shutdown (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
outputctx_t *octx = ctx->output_context;
dfunc->vkDestroyPipeline (device->dev, octx->pipeline, 0);
free (octx->frames.a);
free (octx);
}

View file

@ -53,6 +53,7 @@
#include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lighting.h"
#include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_main.h"
#include "QF/Vulkan/qf_output.h"
#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_renderpass.h"
#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_vid.h"
@ -67,6 +68,10 @@ static exprsym_t builtin_plist_syms[] = {
.value = (void *) .value = (void *)
#include "libs/video/renderer/vulkan/pl_quake_def.plc" #include "libs/video/renderer/vulkan/pl_quake_def.plc"
}, },
{ .name = "qf_output",
.value = (void *)
#include "libs/video/renderer/vulkan/pl_output.plc"
},
{ .name = "deferred", { .name = "deferred",
.value = (void *) .value = (void *)
#include "libs/video/renderer/vulkan/rp_deferred.plc" #include "libs/video/renderer/vulkan/rp_deferred.plc"
@ -79,6 +84,10 @@ static exprsym_t builtin_plist_syms[] = {
.value = (void *) .value = (void *)
#include "libs/video/renderer/vulkan/rp_forward.plc" #include "libs/video/renderer/vulkan/rp_forward.plc"
}, },
{ .name = "output",
.value = (void *)
#include "libs/video/renderer/vulkan/rp_output.plc"
},
{} {}
}; };
static plitem_t **builtin_plists; static plitem_t **builtin_plists;
@ -378,6 +387,7 @@ renderpass_cmp (const void *_a, const void *_b)
void void
Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
{ {
Vulkan_Output_CreateRenderPasses (ctx);
Vulkan_Main_CreateRenderPasses (ctx); Vulkan_Main_CreateRenderPasses (ctx);
Vulkan_Lighting_CreateRenderPasses (ctx); Vulkan_Lighting_CreateRenderPasses (ctx);