[vulkan] Implement most of the changes for cube rendering

There are some missing parts from this commit as these are the fairly
clean changes. Missing is building a separate set of pipelines for the
new render pass (might be able to get away from that), OIT heads texture
is flat rather than an array, view matrices aren't set up, and the
fisheye renderer isn't hooked up to the output pass (code exists but is
messy). However, with the missing parts included, testing shows things
mostly working: the cube map is rendered correctly even though it's not
displayed correctly (incorrect view). This has definitely proven to be a
good test for Vulkan's multiview feature (very nice).
This commit is contained in:
Bill Currie 2023-01-23 11:14:06 +09:00
parent 0cf341d1cb
commit 4cb120e878
13 changed files with 419 additions and 0 deletions

View file

@ -47,8 +47,10 @@ typedef struct outputctx_s {
outputframeset_t frames;
VkPipeline output;
VkPipeline waterwarp;
VkPipeline fisheye;
VkPipelineLayout output_layout;
VkPipelineLayout warp_layout;
VkPipelineLayout fish_layout;
VkSampler sampler;
VkImageView input;
} outputctx_t;

View file

@ -195,6 +195,8 @@ 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_output_src = libs/video/renderer/vulkan/pl_output.plist
pl_output_gen = libs/video/renderer/vulkan/pl_output.plc
rp_defcube_src = libs/video/renderer/vulkan/rp_defcube.plist
rp_defcube_gen = libs/video/renderer/vulkan/rp_defcube.plc
rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist
rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc
rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist
@ -260,6 +262,7 @@ libs/video/renderer/vulkan/vkparse.lo: \
$(vkparse_src) \
$(pl_quake_def_gen) \
$(pl_output_gen) \
${rp_defcube_gen} \
${rp_deferred_gen} \
$(rp_forward_gen) \
$(rp_output_gen) \
@ -363,6 +366,8 @@ fstrianglest_src = $(vkshaderpath)/fstrianglest.vert
fstrianglest_c = $(vkshaderpath)/fstrianglest.vert.spvc
pushcolor_src = $(vkshaderpath)/pushcolor.frag
pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc
fisheye_src = $(vkshaderpath)/fisheye.frag
fisheye_c = $(vkshaderpath)/fisheye.frag.spvc
waterwarp_src = $(vkshaderpath)/waterwarp.frag
waterwarp_c = $(vkshaderpath)/waterwarp.frag.spvc
@ -437,6 +442,8 @@ $(fstrianglest_c): $(fstrianglest_src)
$(pushcolor_c): $(pushcolor_src)
$(fisheye_c): $(fisheye_src) $(matrices_h)
$(waterwarp_c): $(waterwarp_src) $(matrices_h)
vkshader_c = \
@ -479,6 +486,7 @@ vkshader_c = \
$(fstrianglest_c) \
$(pushcolor_c) \
$(shadow_c) \
$(fisheye_c) \
$(waterwarp_c)
V_VKGEN = $(V_VKGEN_@AM_V@)
@ -513,6 +521,7 @@ BUILT_SOURCES += $(shader_gen)
EXTRA_DIST += \
libs/video/renderer/vulkan/vkparse.plist \
libs/video/renderer/vulkan/vkparse.h \
$(rp_defcube_src) \
$(rp_deferred_src) \
$(rp_forward_src) \
$(rp_output_src) \
@ -562,4 +571,5 @@ EXTRA_DIST += \
$(fstriangle_src) \
$(fstrianglest_src) \
$(pushcolor_src) \
$(fisheye_src) \
$(waterwarp_src)

View file

@ -152,6 +152,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions)
VkPhysicalDeviceMultiviewFeatures multiview_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
.multiview = 1,
.multiviewGeometryShader = 1,
};
VkPhysicalDeviceFeatures features = {
.geometryShader = 1,

View file

@ -66,6 +66,16 @@
}
);
};
fisheye_layout = {
@inherit = $properties.pipelineLayouts.output_layout;
pushConstantRanges = (
{
stageFlags = fragment;
offset = 0;
size = "2 * 4";
}
);
};
};
depthStencil = {
@ -233,5 +243,18 @@
);
layout = waterwarp_layout;
};
fisheye = {
@inherit = $properties.pipelines.output_base;
subpass = 0;
stages = (
$properties.fstriangle.vertexStageST,
{
stage = fragment;
name = main;
module = $builtin/fisheye.frag;
},
);
layout = fisheye_layout;
};
};
}

View file

@ -0,0 +1,335 @@
{
flat_color_image_template = {
imageType = `2d;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 6;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
images = {
depth = {
@inherit = $properties.flat_color_image_template;
format = x8_d24_unorm_pack32;
usage = depth_stencil_attachment|input_attachment|transient_attachment;
};
color = {
@inherit = $properties.flat_color_image_template;
format = r8g8b8a8_unorm;
};
emission = {
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
};
normal = {
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
};
position = {
@inherit = $properties.flat_color_image_template;
format = r32g32b32a32_sfloat;
};
opaque = {
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
};
};
flat_color_view_template = {
viewType = `2d_array;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 6;
};
};
imageViews = {
depth = {
@inherit = $properties.flat_color_view_template;
image = depth;
format = $properties.images.depth.format;
subresourceRange = {
aspectMask = depth;
};
};
color = {
@inherit = $properties.flat_color_view_template;
image = color;
format = $properties.images.color.format;
};
emission = {
@inherit = $properties.flat_color_view_template;
image = emission;
format = $properties.images.emission.format;
};
normal = {
@inherit = $properties.flat_color_view_template;
image = normal;
format = $properties.images.normal.format;
};
position = {
@inherit = $properties.flat_color_view_template;
image = position;
format = $properties.images.position.format;
};
opaque = {
@inherit = $properties.flat_color_view_template;
image = opaque;
format = $properties.images.opaque.format;
};
aview = {
@inherit = $properties.flat_color_view_template;
image = $output.image;
format = $output.format;
};
};
output = {
image = {
@inherit = $properties.flat_color_image_template;
flags = cube_compatible;
usage = color_attachment|input_attachment|sampled;
format = $output.format;
};
view = {
@inherit = $properties.flat_color_view_template;
viewType = cube;
image = $output.image;
format = $output.format;
};
format = r16g16b16a16_sfloat;
finalLayout = shader_read_only_optimal;
};
framebuffer = {
renderPass = defcube;
attachments = (depth, color, emission, normal, position, opaque,
$properties.imageViews.aview);
width = $output.extent.width;
height = $output.extent.height;
layers = 1;
};
clearValues = (
{ depthStencil = { depth = 1; stencil = 0; }; },
{ color = "[0, 0, 0, 1]"; }, // color
{ color = "[0, 0, 0, 1]"; }, // emission
{ color = "[0, 0, 0, 1]"; }, // normal
{ color = "[0, 0, 0, 1]"; }, // position
{ color = "[0, 0, 0, 1]"; }, // opaque
{ color = "[0, 0, 0, 1]"; }, // output
);
attachment_template = {
samples = 1;
loadOp = dont_care;
storeOp = store;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
};
info = {
color = "[0, 1, 0, 1]";
subpass_info = (
{ name = depth; color = "[ 0.5, 0.5, 0.5, 1]" },
{ name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" },
{ name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" },
{ name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" },
{ name = compose; color = "[ 0.7, 0.3, 0.3, 1]" },
);
};
renderpass = {
attachments = (
{
@inherit = $properties.attachment_template;
format = $properties.images.depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.color.format;
loadOp = clear;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.emission.format;
loadOp = clear;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.normal.format;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.position.format;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.opaque.format;
},
{
@inherit = $properties.attachment_template;
format = $output.format;
loadOp = clear;
storeOp = store;
finalLayout = $output.finalLayout;
},
);
subpasses = (
{ // 0 depth
pipelineBindPoint = graphics;
depthStencilAttachment = {
attachment = 0;
layout = depth_stencil_attachment_optimal;
};
},
{ // 1 translucent-frags
pipelineBindPoint = graphics;
depthStencilAttachment = {
attachment = 0;
layout = depth_stencil_read_only_optimal;
};
preserveAttachments = (1, 2, 3, 4, 5);
},
{ // 2 g-buffer generation
pipelineBindPoint = graphics;
colorAttachments = (
{ // color
attachment = 1;
layout = color_attachment_optimal;
},
{ // emission
attachment = 2;
layout = color_attachment_optimal;
},
{ // normal
attachment = 3;
layout = color_attachment_optimal;
},
{ // position
attachment = 4;
layout = color_attachment_optimal;
},
);
depthStencilAttachment = {
attachment = 0;
layout = depth_stencil_read_only_optimal;
};
preserveAttachments = (6);
},
{ // 3 lighting
pipelineBindPoint = graphics;
inputAttachments = (
{ // depth
attachment = 0;
layout = shader_read_only_optimal;
},
{ // color
attachment = 1;
layout = shader_read_only_optimal;
},
{ // emission
attachment = 2;
layout = shader_read_only_optimal;
},
{ // normal
attachment = 3;
layout = shader_read_only_optimal;
},
{ // position
attachment = 4;
layout = shader_read_only_optimal;
},
);
colorAttachments = (
{ // opaque
attachment = 5;
layout = color_attachment_optimal;
},
);
preserveAttachments = (6);
},
{ // 4 compose
pipelineBindPoint = graphics;
inputAttachments = (
{ // opaque
attachment = 5;
layout = shader_read_only_optimal;
},
);
colorAttachments = (
{ // output
attachment = 6;
layout = color_attachment_optimal;
},
);
preserveAttachments = (0, 1, 2, 3, 4);
},
);
dependencies = (
{
srcSubpass = 0; // depth
dstSubpass = 1; // translucent
srcStageMask = late_fragment_tests;
dstStageMask = fragment_shader|early_fragment_tests;
srcAccessMask = depth_stencil_attachment_write;
dstAccessMask = input_attachment_read|depth_stencil_attachment_read;
dependencyFlags = by_region;
},
{
srcSubpass = 0; // depth
dstSubpass = 2; // g-buffer
srcStageMask = late_fragment_tests;
dstStageMask = early_fragment_tests;
srcAccessMask = depth_stencil_attachment_write;
dstAccessMask = depth_stencil_attachment_read;
dependencyFlags = by_region;
},
{
srcSubpass = 2; // g-buffer
dstSubpass = 3; // lighting
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = input_attachment_read;
dependencyFlags = by_region;
},
{
srcSubpass = 3; // lighting
dstSubpass = 4; // compose
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = input_attachment_read;
dependencyFlags = by_region;
},
{
srcSubpass = 1; // translucent-frags
dstSubpass = 4; // translucent-final/compose
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = input_attachment_read;
dependencyFlags = by_region;
},
);
@next = (VkRenderPassMultiviewCreateInfo, {
viewMasks = (
0x0000003fu,
0x0000003fu,
0x0000003fu,
0x0000003fu,
0x0000003fu,
);
});
};
}

View file

@ -115,6 +115,8 @@ static
static
#include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/fisheye.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/waterwarp.frag.spvc"
typedef struct shaderdata_s {
@ -162,6 +164,7 @@ static shaderdata_t builtin_shaders[] = {
{ "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) },
{ "fstrianglest.vert", fstrianglest_vert, sizeof (fstrianglest_vert) },
{ "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) },
{ "fisheye.frag", fisheye_frag, sizeof (fisheye_frag) },
{ "waterwarp.frag", waterwarp_frag, sizeof (waterwarp_frag) },
{}
};

View file

@ -1,5 +1,7 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_multiview : enable
#include "oit_store.finc"
layout (constant_id = 0) const bool doSkyBox = false;

View file

@ -1,5 +1,7 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_multiview : enable
#include "oit_store.finc"
layout (set = 3, binding = 0) uniform sampler2DArray Texture;

View file

@ -1,5 +1,7 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_multiview : enable
#define OIT_SET 1
#include "oit_blend.finc"

View file

@ -0,0 +1,30 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
layout (set = 0, binding = 0) uniform
#include "matrices.h"
;
layout (set = 1, binding = 0) uniform samplerCube Input;
layout (push_constant) uniform PushConstants {
float fov;
float aspect;
};
layout (location = 0) in vec2 uv;
layout (location = 0) out vec4 frag_color;
void
main ()
{
// slight offset on y is to avoid the singularity straight ahead
vec2 xy = (2.0 * uv - vec2 (1, 1.00002)) * (vec2(1, -aspect));
float r = sqrt (dot (xy, xy));
vec2 cs = vec2 (cos (r * fov), sin (r * fov));
vec3 dir = vec3 (cs.y * xy / r, cs.x);
vec4 c = texture (Input, dir);
frag_color = c;// * 0.001 + vec4(dir, 1);
}

View file

@ -1,5 +1,7 @@
#version 450
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_multiview : enable
#include "oit_store.finc"
layout (location = 0) in vec4 uv_tr;

View file

@ -1724,6 +1724,10 @@ static exprsym_t builtin_plist_syms[] = {
.value = (void *)
#include "libs/video/renderer/vulkan/pl_output.plc"
},
{ .name = "defcube",
.value = (void *)
#include "libs/video/renderer/vulkan/rp_defcube.plc"
},
{ .name = "deferred",
.value = (void *)
#include "libs/video/renderer/vulkan/rp_deferred.plc"

View file

@ -245,8 +245,10 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx)
octx->output = Vulkan_CreateGraphicsPipeline (ctx, "output");
octx->waterwarp = Vulkan_CreateGraphicsPipeline (ctx, "waterwarp");
octx->fisheye = Vulkan_CreateGraphicsPipeline (ctx, "fisheye");
octx->output_layout = Vulkan_CreatePipelineLayout (ctx, "output_layout");
octx->warp_layout = Vulkan_CreatePipelineLayout (ctx, "waterwarp_layout");
octx->fish_layout = Vulkan_CreatePipelineLayout (ctx, "fisheye_layout");
octx->sampler = Vulkan_CreateSampler (ctx, "linear");
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
@ -285,6 +287,7 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx)
dfunc->vkDestroyPipeline (device->dev, octx->output, 0);
dfunc->vkDestroyPipeline (device->dev, octx->waterwarp, 0);
dfunc->vkDestroyPipeline (device->dev, octx->fisheye, 0);
free (octx->frames.a);
free (octx);
}