mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-29 23:52:22 +00:00
[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:
parent
7b15caee04
commit
2cee2f2ab8
13 changed files with 626 additions and 8 deletions
|
@ -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
|
||||||
|
|
59
include/QF/Vulkan/qf_output.h
Normal file
59
include/QF/Vulkan/qf_output.h
Normal 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
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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);
|
||||||
|
|
209
libs/video/renderer/vulkan/pl_output.plist
Normal file
209
libs/video/renderer/vulkan/pl_output.plist
Normal 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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
90
libs/video/renderer/vulkan/rp_output.plist
Normal file
90
libs/video/renderer/vulkan/rp_output.plist
Normal 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;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
|
@ -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) },
|
||||||
|
|
15
libs/video/renderer/vulkan/shader/output.frag
Normal file
15
libs/video/renderer/vulkan/shader/output.frag
Normal 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);
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
211
libs/video/renderer/vulkan/vulkan_output.c
Normal file
211
libs/video/renderer/vulkan/vulkan_output.c
Normal 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue