mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
[vulkan] Implement order implement transparency
It's a bit flaky for particles, especially at higher frame rates, but that's due to supporting only 64 overlapping pixels. A reasonable solution is probably switching to a priority heap for the "sort" and upping the limit.
This commit is contained in:
parent
ecd5e1de9f
commit
00cade072c
27 changed files with 694 additions and 50 deletions
|
@ -21,7 +21,9 @@ typedef struct qfv_bufferbarrier_s {
|
|||
// image layout transitions
|
||||
enum {
|
||||
qfv_LT_Undefined_to_TransferDst,
|
||||
qfv_LT_Undefined_to_General,
|
||||
qfv_LT_TransferDst_to_TransferSrc,
|
||||
qfv_LT_TransferDst_to_General,
|
||||
qfv_LT_TransferDst_to_ShaderReadOnly,
|
||||
qfv_LT_TransferSrc_to_ShaderReadOnly,
|
||||
qfv_LT_ShaderReadOnly_to_TransferDst,
|
||||
|
@ -35,6 +37,7 @@ enum {
|
|||
qfv_BB_TransferWrite_to_VertexAttrRead,
|
||||
qfv_BB_TransferWrite_to_IndexRead,
|
||||
qfv_BB_TransferWrite_to_UniformRead,
|
||||
qfv_BB_TransferWrite_to_ShaderRW,
|
||||
qfv_BB_ShaderRW_to_ShaderRO,
|
||||
qfv_BB_ShaderRW_to_ShaderRO_VA,
|
||||
qfv_BB_ShaderRO_to_ShaderWrite,
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#ifndef __QF_Vulkan_renderpass_h
|
||||
#define __QF_Vulkan_renderpass_h
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
#define VK_NO_PROTOTYPES
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "QF/darray.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
|
|
61
include/QF/Vulkan/qf_translucent.h
Normal file
61
include/QF/Vulkan/qf_translucent.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
#ifndef __QF_Vulkan_qf_translucent_h
|
||||
#define __QF_Vulkan_qf_translucent_h
|
||||
|
||||
#include "QF/darray.h"
|
||||
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
#include "QF/Vulkan/command.h"
|
||||
|
||||
typedef struct qfv_transfrag_s {
|
||||
vec4f_t color;
|
||||
float depth;
|
||||
int32_t next;
|
||||
} qfv_transfrag_t;
|
||||
|
||||
typedef struct qfv_transtate_s {
|
||||
int32_t numFragments;
|
||||
int32_t maxFragments;
|
||||
} qfv_transtate_t;
|
||||
|
||||
typedef enum {
|
||||
QFV_translucentClear,
|
||||
QFV_translucentBlend,
|
||||
|
||||
QFV_translucentNumPasses
|
||||
} QFV_TranslucentSubpass;
|
||||
|
||||
typedef struct translucentframe_s {
|
||||
VkDescriptorSet descriptors;
|
||||
VkImage heads;
|
||||
VkBuffer state;
|
||||
qfv_cmdbufferset_t cmdSet;
|
||||
} translucentframe_t;
|
||||
|
||||
typedef struct translucentframeset_s
|
||||
DARRAY_TYPE (translucentframe_t) translucentframeset_t;
|
||||
|
||||
typedef struct translucentctx_s {
|
||||
translucentframeset_t frames;
|
||||
|
||||
struct qfv_resource_s *resources;
|
||||
|
||||
VkPipeline pipeline;
|
||||
VkPipelineLayout layout;
|
||||
VkDescriptorPool pool;
|
||||
VkDescriptorSetLayout setLayout;
|
||||
} translucentctx_t;
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
struct qfv_renderframe_s;
|
||||
|
||||
void Vulkan_Translucent_Init (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Translucent_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Translucent_Draw (struct qfv_renderframe_s *rFrame);
|
||||
VkDescriptorSet Vulkan_Translucent_Descriptors (struct vulkan_ctx_s *ctx,
|
||||
int frame)__attribute__((pure));
|
||||
void Vulkan_Translucent_CreateBuffers (struct vulkan_ctx_s *ctx,
|
||||
VkExtent2D extent);
|
||||
void Vulkan_Translucent_CreateRenderPasses (struct vulkan_ctx_s *ctx);
|
||||
|
||||
#endif//__QF_Vulkan_qf_translucent_h
|
|
@ -42,17 +42,19 @@ enum {
|
|||
QFV_rp_particles,
|
||||
QFV_rp_shadowmap,
|
||||
QFV_rp_preoutput,
|
||||
QFV_rp_translucent,
|
||||
QFV_rp_main,
|
||||
QFV_rp_output,
|
||||
};
|
||||
|
||||
//FIXME location
|
||||
typedef enum {
|
||||
QFV_passDepth, // geometry
|
||||
QFV_passTranslucent, // geometry
|
||||
QFV_passGBuffer, // geometry
|
||||
QFV_passLighting, // single triangle
|
||||
QFV_passCompose, // single triangle
|
||||
QFV_passDepth, // geometry
|
||||
QFV_passTranslucentFrag, // geometry
|
||||
QFV_passGBuffer, // geometry
|
||||
QFV_passLighting, // single triangle
|
||||
QFV_passTranslucentFinal, // single triangle
|
||||
QFV_passCompose, // single triangle
|
||||
|
||||
QFV_NumPasses
|
||||
} QFV_Subpass;
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef struct vulkan_ctx_s {
|
|||
struct scriptctx_s *script_context;
|
||||
struct texturectx_s *texture_context;
|
||||
struct matrixctx_s *matrix_context;
|
||||
struct translucentctx_s *translucent_context;
|
||||
struct aliasctx_s *alias_context;
|
||||
struct bspctx_s *bsp_context;
|
||||
struct iqmctx_s *iqm_context;
|
||||
|
|
|
@ -254,6 +254,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
|
|||
libs/video/renderer/vulkan/vulkan_scene.c \
|
||||
libs/video/renderer/vulkan/vulkan_sprite.c \
|
||||
libs/video/renderer/vulkan/vulkan_texture.c \
|
||||
libs/video/renderer/vulkan/vulkan_translucent.c \
|
||||
libs/video/renderer/vulkan/vulkan_vid_common.c
|
||||
|
||||
libs/video/renderer/vulkan/vkparse.lo: \
|
||||
|
@ -339,6 +340,10 @@ lightingf_src = $(vkshaderpath)/lighting.frag
|
|||
lightingf_c = $(vkshaderpath)/lighting.frag.spvc
|
||||
composef_src = $(vkshaderpath)/compose.frag
|
||||
composef_c = $(vkshaderpath)/compose.frag.spvc
|
||||
oit_store = $(vkshaderpath)/oit_store.finc
|
||||
oit_h = $(vkshaderpath)/oit.h
|
||||
oit_blendf_src = $(vkshaderpath)/oit_blend.frag
|
||||
oit_blendf_c = $(vkshaderpath)/oit_blend.frag.spvc
|
||||
aliasv_src = $(vkshaderpath)/alias.vert
|
||||
aliasv_c = $(vkshaderpath)/alias.vert.spvc
|
||||
aliasf_src = $(vkshaderpath)/alias.frag
|
||||
|
@ -378,7 +383,7 @@ $(partphysicsc_c): $(partphysicsc_src)
|
|||
$(partupdatec_c): $(partupdatec_src)
|
||||
$(particlev_c): $(particlev_src)
|
||||
$(particleg_c): $(particleg_src)
|
||||
$(particlef_c): $(particlef_src)
|
||||
$(particlef_c): $(particlef_src) $(oit_store) $(oit_h)
|
||||
|
||||
$(sprite_gbufv_c): $(sprite_gbufv_src)
|
||||
|
||||
|
@ -408,14 +413,16 @@ $(bsp_gbuff_c): $(bsp_gbuff_src)
|
|||
|
||||
$(bsp_shadow_c): $(bsp_shadow_src)
|
||||
|
||||
$(bsp_skyf_c): $(bsp_skyf_src)
|
||||
$(bsp_skyf_c): $(bsp_skyf_src) $(oit_store) $(oit_h)
|
||||
|
||||
$(bsp_turbf_c): $(bsp_turbf_src)
|
||||
$(bsp_turbf_c): $(bsp_turbf_src) $(oit_store) $(oit_h)
|
||||
|
||||
$(lightingf_c): $(lightingf_src)
|
||||
|
||||
$(composef_c): $(composef_src)
|
||||
|
||||
$(oit_blendf_c): $(oit_blendf_src) $(oit_h)
|
||||
|
||||
$(aliasv_c): $(aliasv_src)
|
||||
|
||||
$(alias_depth_c): $(alias_depth_src)
|
||||
|
@ -471,6 +478,7 @@ vkshader_c = \
|
|||
$(bsp_turbf_c) \
|
||||
$(lightingf_c) \
|
||||
$(composef_c) \
|
||||
$(oit_blendf_c) \
|
||||
$(aliasv_c) \
|
||||
$(alias_depth_c) \
|
||||
$(aliasf_c) \
|
||||
|
@ -537,6 +545,7 @@ EXTRA_DIST += \
|
|||
libs/video/renderer/vulkan/shader/bsp_sky.frag \
|
||||
libs/video/renderer/vulkan/shader/bsp_turb.frag \
|
||||
libs/video/renderer/vulkan/shader/compose.frag \
|
||||
libs/video/renderer/vulkan/shader/oit_blend.frag \
|
||||
libs/video/renderer/vulkan/shader/iqm.frag \
|
||||
libs/video/renderer/vulkan/shader/iqm.vert \
|
||||
libs/video/renderer/vulkan/shader/lighting.frag \
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "QF/Vulkan/qf_scene.h"
|
||||
#include "QF/Vulkan/qf_sprite.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/qf_translucent.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/capture.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
|
@ -109,6 +110,7 @@ vulkan_R_Init (void)
|
|||
Vulkan_Sprite_Init (vulkan_ctx);
|
||||
Vulkan_Draw_Init (vulkan_ctx);
|
||||
Vulkan_Lighting_Init (vulkan_ctx);
|
||||
Vulkan_Translucent_Init (vulkan_ctx);
|
||||
Vulkan_Compose_Init (vulkan_ctx);
|
||||
|
||||
Skin_Init ();
|
||||
|
@ -740,6 +742,7 @@ vulkan_vid_render_shutdown (void)
|
|||
Mod_ClearAll ();
|
||||
|
||||
Vulkan_Compose_Shutdown (vulkan_ctx);
|
||||
Vulkan_Translucent_Shutdown (vulkan_ctx);
|
||||
Vulkan_Lighting_Shutdown (vulkan_ctx);
|
||||
Vulkan_Draw_Shutdown (vulkan_ctx);
|
||||
Vulkan_Sprite_Shutdown (vulkan_ctx);
|
||||
|
|
|
@ -44,6 +44,19 @@ const qfv_imagebarrier_t imageBarriers[] = {
|
|||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
},
|
||||
},
|
||||
[qfv_LT_Undefined_to_General] = {
|
||||
.srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
.dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
.barrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
|
||||
0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0,
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
},
|
||||
},
|
||||
[qfv_LT_TransferDst_to_TransferSrc] = {
|
||||
.srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
.dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
|
@ -57,6 +70,19 @@ const qfv_imagebarrier_t imageBarriers[] = {
|
|||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
},
|
||||
},
|
||||
[qfv_LT_TransferDst_to_General] = {
|
||||
.srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
.dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
.barrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0,
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
},
|
||||
},
|
||||
[qfv_LT_TransferDst_to_ShaderReadOnly] = {
|
||||
.srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
.dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
|
@ -164,6 +190,16 @@ const qfv_bufferbarrier_t bufferBarriers[] = {
|
|||
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||
},
|
||||
},
|
||||
[qfv_BB_TransferWrite_to_ShaderRW] = {
|
||||
.srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
.dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
.barrier = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||
},
|
||||
},
|
||||
[qfv_BB_ShaderRW_to_ShaderRO] = {
|
||||
.srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
.dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
|
|
|
@ -156,6 +156,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions)
|
|||
VkPhysicalDeviceFeatures features = {
|
||||
.geometryShader = 1,
|
||||
.multiViewport = 1,
|
||||
.fragmentStoresAndAtomics = 1,
|
||||
};
|
||||
VkDeviceCreateInfo dCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, &multiview_features, 0,
|
||||
|
|
|
@ -233,6 +233,20 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
oit_pool = {
|
||||
flags = 0;
|
||||
maxSets = $frames.size;
|
||||
bindings = (
|
||||
{
|
||||
type = storage_buffer;
|
||||
descriptorCount = "2z * $frames.size";
|
||||
},
|
||||
{
|
||||
type = storage_image;
|
||||
descriptorCount = "1z * $frames.size";
|
||||
},
|
||||
);
|
||||
};
|
||||
compose_attach_pool = {
|
||||
flags = 0;
|
||||
maxSets = $frames.size;
|
||||
|
@ -293,6 +307,28 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
oit_set = {
|
||||
bindings = (
|
||||
{
|
||||
binding = 0;
|
||||
descriptorType = storage_buffer;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
{
|
||||
binding = 1;
|
||||
descriptorType = storage_buffer;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
{
|
||||
binding = 2;
|
||||
descriptorType = storage_image;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
);
|
||||
};
|
||||
entity_set = {
|
||||
bindings = (
|
||||
{
|
||||
|
@ -433,7 +469,7 @@
|
|||
setLayouts = (matrix_set);
|
||||
};
|
||||
quakebsp_layout = {
|
||||
setLayouts = (matrix_set, entity_set, texture_set, texture_set);
|
||||
setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set);
|
||||
pushConstantRanges = (
|
||||
{
|
||||
stageFlags = fragment;
|
||||
|
@ -490,6 +526,9 @@
|
|||
lighting_layout = {
|
||||
setLayouts = (lighting_attach, lighting_lights, lighting_shadow);
|
||||
};
|
||||
oit_layout = {
|
||||
setLayouts = (oit_set);
|
||||
};
|
||||
compose_layout = {
|
||||
setLayouts = (compose_attach);
|
||||
};
|
||||
|
@ -507,7 +546,7 @@
|
|||
setLayouts = (particle_set, particle_set, particle_set);
|
||||
};
|
||||
partdraw_layout = {
|
||||
setLayouts = (matrix_set, texture_set);
|
||||
setLayouts = (matrix_set, texture_set, oit_set);
|
||||
pushConstantRanges = (
|
||||
{
|
||||
stageFlags = vertex;
|
||||
|
@ -1225,9 +1264,22 @@
|
|||
);
|
||||
layout = lighting_layout;
|
||||
};
|
||||
compose = {
|
||||
oit = {
|
||||
@inherit = $properties.pipelines.comp_base;
|
||||
subpass = 4;
|
||||
stages = (
|
||||
$properties.fstriangle.vertexStage,
|
||||
{
|
||||
stage = fragment;
|
||||
name = main;
|
||||
module = $builtin/oit_blend.frag;
|
||||
},
|
||||
);
|
||||
layout = oit_layout;
|
||||
};
|
||||
compose = {
|
||||
@inherit = $properties.pipelines.comp_base;
|
||||
subpass = 5;
|
||||
stages = (
|
||||
$properties.fstriangle.vertexStage,
|
||||
{
|
||||
|
|
|
@ -146,6 +146,7 @@
|
|||
{ 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 = translucent; color = "[ 0.25, 0.6, 0.25, 1]" },
|
||||
{ name = compose; color = "[ 0.7, 0.3, 0.3, 1]" },
|
||||
);
|
||||
};
|
||||
|
@ -200,14 +201,8 @@
|
|||
layout = depth_stencil_attachment_optimal;
|
||||
};
|
||||
},
|
||||
{ // 1 translucent
|
||||
{ // 1 translucent-frags
|
||||
pipelineBindPoint = graphics;
|
||||
colorAttachments = (
|
||||
{ // translucent
|
||||
attachment = 6;
|
||||
layout = color_attachment_optimal;
|
||||
},
|
||||
);
|
||||
depthStencilAttachment = {
|
||||
attachment = 0;
|
||||
layout = depth_stencil_read_only_optimal;
|
||||
|
@ -272,7 +267,17 @@
|
|||
);
|
||||
preserveAttachments = (6);
|
||||
},
|
||||
{ // 4 compose
|
||||
{ // 4 translucent-final
|
||||
pipelineBindPoint = graphics;
|
||||
colorAttachments = (
|
||||
{ // translucent
|
||||
attachment = 6;
|
||||
layout = color_attachment_optimal;
|
||||
},
|
||||
);
|
||||
preserveAttachments = (1, 2, 3, 4, 5);
|
||||
},
|
||||
{ // 5 compose
|
||||
pipelineBindPoint = graphics;
|
||||
inputAttachments = (
|
||||
{ // opaque
|
||||
|
@ -305,11 +310,11 @@
|
|||
},
|
||||
/*{
|
||||
srcSubpass = ~0u; // external
|
||||
dstSubpass = 1; // translucent
|
||||
srcStageMask = compute_shader;
|
||||
dstStageMask = vertex_input|draw_indirect;
|
||||
srcAccessMask = shader_write;
|
||||
dstAccessMask = vertex_attribute_read|indirect_command_read;
|
||||
dstSubpass = 1; // translucent-frags
|
||||
srcStageMask = transfer;
|
||||
dstStageMask = fragment_shader|early_fragment_tests;
|
||||
srcAccessMask = transfer_write;
|
||||
dstAccessMask = shader_read|shader_write;
|
||||
},*/
|
||||
{
|
||||
srcSubpass = 0; // depth
|
||||
|
@ -331,7 +336,7 @@
|
|||
},
|
||||
{
|
||||
srcSubpass = 3; // lighting
|
||||
dstSubpass = 4; // compose
|
||||
dstSubpass = 5; // compose
|
||||
srcStageMask = color_attachment_output;
|
||||
dstStageMask = fragment_shader;
|
||||
srcAccessMask = color_attachment_write;
|
||||
|
@ -339,8 +344,17 @@
|
|||
dependencyFlags = by_region;
|
||||
},
|
||||
{
|
||||
srcSubpass = 1; // translucent
|
||||
dstSubpass = 4; // compose
|
||||
srcSubpass = 1; // translucent-frags
|
||||
dstSubpass = 4; // translucent-final
|
||||
srcStageMask = color_attachment_output;
|
||||
dstStageMask = fragment_shader;
|
||||
srcAccessMask = color_attachment_write;
|
||||
dstAccessMask = input_attachment_read;
|
||||
dependencyFlags = by_region;
|
||||
},
|
||||
{
|
||||
srcSubpass = 4; // translucent-final
|
||||
dstSubpass = 5; // compose
|
||||
srcStageMask = color_attachment_output;
|
||||
dstStageMask = fragment_shader;
|
||||
srcAccessMask = color_attachment_write;
|
||||
|
|
|
@ -95,6 +95,8 @@ static
|
|||
static
|
||||
#include "libs/video/renderer/vulkan/shader/compose.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/oit_blend.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/alias.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc"
|
||||
|
@ -156,6 +158,7 @@ static shaderdata_t builtin_shaders[] = {
|
|||
{ "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) },
|
||||
{ "lighting.frag", lighting_frag, sizeof (lighting_frag) },
|
||||
{ "compose.frag", compose_frag, sizeof (compose_frag) },
|
||||
{ "oit_blend.frag", oit_blend_frag, sizeof (oit_blend_frag) },
|
||||
{ "alias.vert", alias_vert, sizeof (alias_vert) },
|
||||
{ "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) },
|
||||
{ "alias.frag", alias_frag, sizeof (alias_frag) },
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#version 450
|
||||
|
||||
layout (set = 2, binding = 0) uniform sampler2DArray Texture;
|
||||
layout (set = 3, binding = 0) uniform sampler2DArray Texture;
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
vec4 fog;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#include "oit_store.finc"
|
||||
|
||||
layout (constant_id = 0) const bool doSkyBox = false;
|
||||
layout (constant_id = 1) const bool doSkySheet = false;
|
||||
|
||||
layout (set = 2, binding = 0) uniform sampler2DArray SkySheet;
|
||||
layout (set = 3, binding = 0) uniform samplerCube SkyBox;
|
||||
layout (set = 3, binding = 0) uniform sampler2DArray SkySheet;
|
||||
layout (set = 4, binding = 0) uniform samplerCube SkyBox;
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
vec4 fog;
|
||||
|
@ -17,7 +19,8 @@ layout (location = 0) in vec4 tl_st;
|
|||
layout (location = 1) in vec3 direction;
|
||||
layout (location = 2) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
layout(early_fragment_tests) in;
|
||||
//layout (location = 0) out vec4 frag_color;
|
||||
|
||||
const float SCALE = 189.0 / 64.0;
|
||||
|
||||
|
@ -95,5 +98,6 @@ main (void)
|
|||
} else {
|
||||
c = vec4 (0, 0, 0, 1);
|
||||
}
|
||||
frag_color = c;//fogBlend (c);
|
||||
//frag_color = c;//fogBlend (c);
|
||||
StoreFrag (c, gl_FragCoord.z);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#include "oit_store.finc"
|
||||
|
||||
layout (set = 2, binding = 0) uniform sampler2DArray Texture;
|
||||
layout (set = 3, binding = 0) uniform sampler2DArray Texture;
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
vec4 fog;
|
||||
|
@ -13,7 +15,8 @@ layout (location = 0) in vec4 tl_st;
|
|||
layout (location = 1) in vec3 direction;
|
||||
layout (location = 2) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
layout(early_fragment_tests) in;
|
||||
//layout (location = 0) out vec4 frag_color;
|
||||
|
||||
const float PI = 3.14159265;
|
||||
const float SPEED = 20.0;
|
||||
|
@ -49,5 +52,6 @@ main (void)
|
|||
float a = c.a * e.a * alpha;
|
||||
c += e;
|
||||
c.a = a;
|
||||
frag_color = c * color;//fogBlend (c);
|
||||
//frag_color = c * color;//fogBlend (c);
|
||||
StoreFrag (c * color, gl_FragCoord.z);
|
||||
}
|
||||
|
|
20
libs/video/renderer/vulkan/shader/oit.h
Normal file
20
libs/video/renderer/vulkan/shader/oit.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef OIT_SET
|
||||
#define OIT_SET 2
|
||||
#endif
|
||||
|
||||
struct FragData {
|
||||
vec4 color;
|
||||
float depth;
|
||||
int next;
|
||||
};
|
||||
|
||||
layout (set = OIT_SET, binding = 0) coherent buffer FragCount {
|
||||
int numFragments;
|
||||
int maxFragments;
|
||||
};
|
||||
|
||||
layout (set = OIT_SET, binding = 1) buffer Fragments {
|
||||
FragData fragments[];
|
||||
};
|
||||
|
||||
layout (set = OIT_SET, binding = 2, r32i) coherent uniform iimage2D heads;
|
40
libs/video/renderer/vulkan/shader/oit_blend.frag
Normal file
40
libs/video/renderer/vulkan/shader/oit_blend.frag
Normal file
|
@ -0,0 +1,40 @@
|
|||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#define OIT_SET 0
|
||||
#include "oit.h"
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
#define MAX_FRAGMENTS 64
|
||||
FragData frags[MAX_FRAGMENTS];
|
||||
int numFrags = 0;
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
int index = imageLoad (heads, coord).r;
|
||||
|
||||
//FIXME use a heap and prioritize closer fragments
|
||||
while (index != -1 && numFrags < MAX_FRAGMENTS) {
|
||||
frags[numFrags] = fragments[index];
|
||||
numFrags++;
|
||||
index = fragments[index].next;
|
||||
}
|
||||
//insertion sort
|
||||
for (int i = 1; i < numFrags; i++) {
|
||||
FragData toInsert = frags[i];
|
||||
int j = i;
|
||||
while (j > 0 && toInsert.depth > frags[j - 1].depth) {
|
||||
frags[j] = frags[j - 1];
|
||||
j--;
|
||||
}
|
||||
frags[j] = toInsert;
|
||||
}
|
||||
|
||||
vec4 color = vec4 (0, 0, 0, 0);
|
||||
for (int i = 0; i < numFrags; i++) {
|
||||
color = mix (color, frags[i].color,
|
||||
clamp (frags[i].color.a, 0.0f, 1.0f));
|
||||
}
|
||||
frag_color = color;
|
||||
}
|
14
libs/video/renderer/vulkan/shader/oit_store.finc
Normal file
14
libs/video/renderer/vulkan/shader/oit_store.finc
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "oit.h"
|
||||
|
||||
void
|
||||
StoreFrag (vec4 color, float depth)
|
||||
{
|
||||
int index = atomicAdd (numFragments, 1);
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
if (index < maxFragments) {
|
||||
int prevIndex = imageAtomicExchange (heads, coord, index);
|
||||
fragments[index].color = color;
|
||||
fragments[index].depth = depth;
|
||||
fragments[index].next = prevIndex;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#include "oit_store.finc"
|
||||
|
||||
layout (location = 0) in vec4 uv_tr;
|
||||
layout (location = 1) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
layout(early_fragment_tests) in;
|
||||
|
||||
void
|
||||
main (void)
|
||||
|
@ -16,5 +18,5 @@ main (void)
|
|||
discard;
|
||||
}
|
||||
c *= (a);
|
||||
frag_color = c;
|
||||
StoreFrag (c, gl_FragCoord.z);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ static const char * __attribute__((used)) alias_pass_names[] = {
|
|||
static QFV_Subpass subpass_map[] = {
|
||||
QFV_passDepth, // QFV_aliasDepth
|
||||
QFV_passGBuffer, // QFV_aliasGBuffer
|
||||
QFV_passTranslucent, // QFV_aliasTranslucent
|
||||
QFV_passTranslucentFrag,// QFV_aliasTranslucent
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_scene.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/qf_translucent.h"
|
||||
#include "QF/Vulkan/buffer.h"
|
||||
#include "QF/Vulkan/barrier.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
|
@ -76,6 +77,9 @@
|
|||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
#define TEX_SET 3
|
||||
#define SKYBOX_SET 4
|
||||
|
||||
typedef struct bsp_push_constants_s {
|
||||
quat_t fog;
|
||||
float time;
|
||||
|
@ -93,8 +97,8 @@ static const char * __attribute__((used)) bsp_pass_names[] = {
|
|||
static QFV_Subpass subpass_map[] = {
|
||||
[QFV_bspDepth] = QFV_passDepth,
|
||||
[QFV_bspGBuffer] = QFV_passGBuffer,
|
||||
[QFV_bspSky] = QFV_passTranslucent,
|
||||
[QFV_bspTurb] = QFV_passTranslucent,
|
||||
[QFV_bspSky] = QFV_passTranslucentFrag,
|
||||
[QFV_bspTurb] = QFV_passTranslucentFrag,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -828,9 +832,10 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline,
|
|||
VkDescriptorSet sets[] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
Vulkan_Scene_Descriptors (ctx),
|
||||
Vulkan_Translucent_Descriptors (ctx, ctx->curFrame),
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 2, sets, 0, 0);
|
||||
layout, 0, 3, sets, 0, 0);
|
||||
|
||||
//XXX glsl_Fog_GetColor (fog);
|
||||
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
|
||||
|
@ -884,7 +889,7 @@ turb_begin (qfv_renderframe_t *rFrame)
|
|||
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag],
|
||||
bframe->cmdSet.a[QFV_bspTurb]);
|
||||
|
||||
qfvPushDebug (ctx, "bsp_begin_subpass");
|
||||
|
@ -909,7 +914,7 @@ sky_begin (qfv_renderframe_t *rFrame)
|
|||
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag],
|
||||
bframe->cmdSet.a[QFV_bspSky]);
|
||||
|
||||
qfvPushDebug (ctx, "bsp_begin_subpass");
|
||||
|
@ -1020,7 +1025,7 @@ draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout,
|
|||
__auto_type d = pass->draw_queues[queue].a[i];
|
||||
if (pass->textures) {
|
||||
vulktex_t *tex = pass->textures->a[d.tex_id];
|
||||
bind_texture (tex, 2, layout, dfunc, cmd);
|
||||
bind_texture (tex, TEX_SET, layout, dfunc, cmd);
|
||||
}
|
||||
dfunc->vkCmdDrawIndexed (cmd, d.index_count, d.instance_count,
|
||||
d.first_index, 0, d.first_instance);
|
||||
|
@ -1189,7 +1194,7 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame)
|
|||
|
||||
sky_begin (rFrame);
|
||||
vulktex_t skybox = { .descriptor = bctx->skybox_descriptor };
|
||||
bind_texture (&skybox, 3, bctx->layout, dfunc,
|
||||
bind_texture (&skybox, SKYBOX_SET, bctx->layout, dfunc,
|
||||
bframe->cmdSet.a[QFV_bspSky]);
|
||||
bsp_push_constants_t frag_constants = { .time = vr_data.realtime };
|
||||
push_fragconst (&frag_constants, bctx->layout, device,
|
||||
|
|
|
@ -70,7 +70,7 @@ static const char * __attribute__((used)) iqm_pass_names[] = {
|
|||
static QFV_Subpass subpass_map[] = {
|
||||
QFV_passDepth, // QFV_iqmDepth
|
||||
QFV_passGBuffer, // QFV_iqmGBuffer
|
||||
QFV_passTranslucent, // QFV_iqmTranslucent
|
||||
QFV_passTranslucentFrag,// QFV_iqmTranslucent
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_scene.h"
|
||||
#include "QF/Vulkan/qf_sprite.h"
|
||||
#include "QF/Vulkan/qf_translucent.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
|
||||
|
@ -140,6 +141,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame)
|
|||
Vulkan_Bsp_Flush (ctx);
|
||||
Vulkan_RenderEntities (r_ent_queue, rFrame);
|
||||
Vulkan_Scene_Flush (ctx);
|
||||
Vulkan_Translucent_Draw (rFrame);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -187,4 +189,5 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx)
|
|||
DARRAY_APPEND (&ctx->renderPasses, rp);
|
||||
|
||||
Vulkan_Output_SetInput (ctx, rp->output.view);
|
||||
Vulkan_Translucent_CreateBuffers (ctx, rp->output.extent);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "QF/Vulkan/qf_palette.h"
|
||||
#include "QF/Vulkan/qf_particles.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_translucent.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
@ -83,7 +84,7 @@ particle_begin_subpass (VkPipeline pipeline, qfv_renderframe_t *rFrame)
|
|||
dfunc->vkResetCommandBuffer (cmd, 0);
|
||||
VkCommandBufferInheritanceInfo inherit = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
|
||||
rFrame->renderpass->renderpass, QFV_passTranslucent,
|
||||
rFrame->renderpass->renderpass, QFV_passTranslucentFrag,
|
||||
rFrame->framebuffer,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
@ -100,9 +101,10 @@ particle_begin_subpass (VkPipeline pipeline, qfv_renderframe_t *rFrame)
|
|||
VkDescriptorSet sets[] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
Vulkan_Palette_Descriptor (ctx),
|
||||
Vulkan_Translucent_Descriptors (ctx, ctx->curFrame),
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pctx->draw_layout, 0, 2, sets, 0, 0);
|
||||
pctx->draw_layout, 0, 3, sets, 0, 0);
|
||||
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
|
||||
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
|
||||
}
|
||||
|
@ -128,7 +130,7 @@ Vulkan_DrawParticles (qfv_renderframe_t *rFrame)
|
|||
particleframe_t *pframe = &pctx->frames.a[curFrame];
|
||||
VkCommandBuffer cmd = pframe->cmdSet.a[0];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag],
|
||||
pframe->cmdSet.a[0]);
|
||||
|
||||
particle_begin_subpass (pctx->draw, rFrame);
|
||||
|
|
|
@ -76,7 +76,7 @@ static const char * __attribute__((used)) sprite_pass_names[] = {
|
|||
static QFV_Subpass subpass_map[] = {
|
||||
QFV_passDepth, // QFV_spriteDepth
|
||||
QFV_passGBuffer, // QFV_spriteGBuffer
|
||||
QFV_passTranslucent, // QFV_spriteTranslucent
|
||||
QFV_passTranslucentFrag,// QFV_spriteTranslucent
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
358
libs/video/renderer/vulkan/vulkan_translucent.c
Normal file
358
libs/video/renderer/vulkan/vulkan_translucent.c
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
vulkan_translucent.c
|
||||
|
||||
Vulkan translucent pass pipeline
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2022/11/30
|
||||
|
||||
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/cvar.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_translucent.h"
|
||||
#include "QF/Vulkan/barrier.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/resource.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
#define MAX_FRAGMENTS (1<<24)
|
||||
|
||||
static const char * __attribute__((used)) translucent_pass_names[] = {
|
||||
"clear",
|
||||
"blend",
|
||||
};
|
||||
|
||||
void
|
||||
Vulkan_Translucent_Draw (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
qfv_renderpass_t *renderpass = rFrame->renderpass;
|
||||
|
||||
translucentctx_t *tctx = ctx->translucent_context;
|
||||
translucentframe_t *tframe = &tctx->frames.a[ctx->curFrame];
|
||||
VkCommandBuffer cmd = tframe->cmdSet.a[QFV_translucentBlend];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFinal], cmd);
|
||||
|
||||
dfunc->vkResetCommandBuffer (cmd, 0);
|
||||
VkCommandBufferInheritanceInfo inherit = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
|
||||
renderpass->renderpass, QFV_passTranslucentFinal,
|
||||
rFrame->framebuffer,
|
||||
0, 0, 0,
|
||||
};
|
||||
VkCommandBufferBeginInfo beginInfo = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||
| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit,
|
||||
};
|
||||
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
||||
|
||||
QFV_duCmdBeginLabel (device, cmd, "translucent", { 0, 0.2, 0.6, 1});
|
||||
|
||||
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
tctx->pipeline);
|
||||
VkDescriptorSet set[] = {
|
||||
tframe->descriptors,
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
tctx->layout, 0, 1, set, 0, 0);
|
||||
|
||||
|
||||
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
|
||||
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
|
||||
|
||||
dfunc->vkCmdDraw (cmd, 3, 1, 0, 0);
|
||||
|
||||
QFV_duCmdEndLabel (device, cmd);
|
||||
dfunc->vkEndCommandBuffer (cmd);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Translucent_Init (vulkan_ctx_t *ctx)
|
||||
{
|
||||
if (ctx->translucent_context) {//FIXME
|
||||
return;
|
||||
}
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
||||
qfvPushDebug (ctx, "translucent init");
|
||||
|
||||
translucentctx_t *tctx = calloc (1, sizeof (translucentctx_t));
|
||||
ctx->translucent_context = tctx;
|
||||
|
||||
size_t frames = ctx->frames.size;
|
||||
DARRAY_INIT (&tctx->frames, frames);
|
||||
DARRAY_RESIZE (&tctx->frames, frames);
|
||||
tctx->frames.grow = 0;
|
||||
|
||||
tctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "oit");
|
||||
tctx->layout = Vulkan_CreatePipelineLayout (ctx, "oit_layout");
|
||||
|
||||
__auto_type setLayout = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
setLayout->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "oit_set");
|
||||
}
|
||||
__auto_type pool = Vulkan_CreateDescriptorPool (ctx, "oit_pool");
|
||||
|
||||
__auto_type sets = QFV_AllocateDescriptorSet (device, pool, setLayout);
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
__auto_type tframe = &tctx->frames.a[i];
|
||||
|
||||
DARRAY_INIT (&tframe->cmdSet, QFV_translucentNumPasses);
|
||||
DARRAY_RESIZE (&tframe->cmdSet, QFV_translucentNumPasses);
|
||||
tframe->cmdSet.grow = 0;
|
||||
|
||||
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &tframe->cmdSet);
|
||||
|
||||
tframe->descriptors = sets->a[i];
|
||||
|
||||
for (int j = 0; j < QFV_translucentNumPasses; j++) {
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
||||
tframe->cmdSet.a[j],
|
||||
va (ctx->va_ctx, "cmd:translucent:%zd:%s", i,
|
||||
translucent_pass_names[j]));
|
||||
}
|
||||
}
|
||||
free (sets);
|
||||
qfvPopDebug (ctx);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
translucentctx_t *tctx = ctx->translucent_context;
|
||||
|
||||
if (tctx->resources) {
|
||||
QFV_DestroyResource (device, tctx->resources);
|
||||
free (tctx->resources);
|
||||
tctx->resources = 0;
|
||||
}
|
||||
|
||||
dfunc->vkDestroyPipeline (device->dev, tctx->pipeline, 0);
|
||||
free (tctx->frames.a);
|
||||
free (tctx);
|
||||
}
|
||||
|
||||
VkDescriptorSet
|
||||
Vulkan_Translucent_Descriptors (vulkan_ctx_t *ctx, int frame)
|
||||
{
|
||||
__auto_type tctx = ctx->translucent_context;
|
||||
return tctx->frames.a[frame].descriptors;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent)
|
||||
{
|
||||
if (!ctx->translucent_context) {//FIXME
|
||||
Vulkan_Translucent_Init (ctx);
|
||||
}
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
__auto_type tctx = ctx->translucent_context;
|
||||
size_t frames = ctx->frames.size;
|
||||
|
||||
if (tctx->resources) {
|
||||
QFV_DestroyResource (device, tctx->resources);
|
||||
free (tctx->resources);
|
||||
tctx->resources = 0;
|
||||
}
|
||||
tctx->resources = malloc (sizeof (qfv_resource_t)
|
||||
// heads image
|
||||
+ frames * sizeof (qfv_resobj_t)
|
||||
// heads image view
|
||||
+ frames * sizeof (qfv_resobj_t)
|
||||
// fragment buffer
|
||||
+ frames * sizeof (qfv_resobj_t)
|
||||
// fragment count
|
||||
+ frames * sizeof (qfv_resobj_t));
|
||||
__auto_type heads_objs = (qfv_resobj_t *) &tctx->resources[1];
|
||||
__auto_type head_views_objs = &heads_objs[frames];
|
||||
__auto_type buffer_objs = &head_views_objs[frames];
|
||||
__auto_type count_objs = &buffer_objs[frames];
|
||||
tctx->resources[0] = (qfv_resource_t) {
|
||||
.name = "oit",
|
||||
.va_ctx = ctx->va_ctx,
|
||||
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
.num_objects = 4 * frames,
|
||||
.objects = heads_objs,
|
||||
};
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
heads_objs[i] = (qfv_resobj_t) {
|
||||
.name = va (ctx->va_ctx, "heads:%zd", i),
|
||||
.type = qfv_res_image,
|
||||
.image = {
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.format = VK_FORMAT_R32_SINT,
|
||||
.extent = { extent.width, extent.height, 1 },
|
||||
.num_mipmaps = 1,
|
||||
.num_layers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.usage = VK_IMAGE_USAGE_STORAGE_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||
},
|
||||
};
|
||||
head_views_objs[i] = (qfv_resobj_t) {
|
||||
.name = "head view",
|
||||
.type = qfv_res_image_view,
|
||||
.image_view = {
|
||||
.image = i,
|
||||
.type = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = VK_FORMAT_R32_SINT,
|
||||
.aspect = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
},
|
||||
};
|
||||
buffer_objs[i] = (qfv_resobj_t) {
|
||||
.name = va (ctx->va_ctx, "frags:%zd", i),
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = sizeof (qfv_transfrag_t) * MAX_FRAGMENTS,
|
||||
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
count_objs[i] = (qfv_resobj_t) {
|
||||
.name = va (ctx->va_ctx, "count:%zd", i),
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = 2 * sizeof (qfv_transtate_t),
|
||||
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
},
|
||||
};
|
||||
}
|
||||
QFV_CreateResource (device, tctx->resources);
|
||||
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
__auto_type tframe = &tctx->frames.a[i];
|
||||
tframe->heads = heads_objs[i].image.image;
|
||||
tframe->state = count_objs[i].buffer.buffer;
|
||||
|
||||
VkDescriptorImageInfo imageInfo[] = {
|
||||
{ 0, head_views_objs[i].image_view.view, VK_IMAGE_LAYOUT_GENERAL },
|
||||
};
|
||||
VkDescriptorBufferInfo bufferInfo[] = {
|
||||
{ count_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE },
|
||||
{ buffer_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE },
|
||||
};
|
||||
VkWriteDescriptorSet write[] = {
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
tframe->descriptors, 2, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.pImageInfo = imageInfo },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
tframe->descriptors, 0, 0, 2,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.pBufferInfo = bufferInfo },
|
||||
};
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
translucent_clear (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
translucentctx_t *tctx = ctx->translucent_context;
|
||||
__auto_type tframe = &tctx->frames.a[ctx->curFrame];
|
||||
VkCommandBuffer cmd = tframe->cmdSet.a[QFV_translucentClear];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd);
|
||||
dfunc->vkResetCommandBuffer (cmd, 0);
|
||||
VkCommandBufferInheritanceInfo inherit = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
};
|
||||
VkCommandBufferBeginInfo beginInfo = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &inherit,
|
||||
};
|
||||
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
||||
|
||||
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
|
||||
ib.barrier.image = tframe->heads;
|
||||
dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &ib.barrier);
|
||||
VkClearColorValue clear_color[] = {
|
||||
{ .int32 = {-1, -1, -1, -1} },
|
||||
};
|
||||
VkImageSubresourceRange ranges[] = {
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 },
|
||||
};
|
||||
dfunc->vkCmdClearColorImage (cmd, tframe->heads,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
clear_color, 1, ranges);
|
||||
ib = imageBarriers[qfv_LT_TransferDst_to_General];
|
||||
ib.barrier.image = tframe->heads;
|
||||
dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &ib.barrier);
|
||||
|
||||
dfunc->vkEndCommandBuffer (cmd);
|
||||
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
||||
qfv_transtate_t *state = QFV_PacketExtend (packet, 2 * sizeof (*state));
|
||||
*state = (qfv_transtate_t) { 0, MAX_FRAGMENTS };
|
||||
__auto_type bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW];
|
||||
QFV_PacketCopyBuffer (packet, tframe->state, bb);
|
||||
QFV_PacketSubmit (packet);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Translucent_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
__auto_type rp = QFV_RenderPass_New (ctx, "translucent", translucent_clear);
|
||||
rp->order = QFV_rp_translucent;
|
||||
DARRAY_APPEND (&ctx->renderPasses, rp);
|
||||
}
|
|
@ -56,6 +56,7 @@
|
|||
#include "QF/Vulkan/qf_output.h"
|
||||
#include "QF/Vulkan/qf_particles.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_translucent.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
|
@ -169,6 +170,7 @@ Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
|
|||
Vulkan_Main_CreateRenderPasses (ctx);
|
||||
Vulkan_Particles_CreateRenderPasses (ctx);
|
||||
Vulkan_Lighting_CreateRenderPasses (ctx);
|
||||
Vulkan_Translucent_CreateRenderPasses (ctx);
|
||||
|
||||
heapsort (ctx->renderPasses.a, ctx->renderPasses.size,
|
||||
sizeof (qfv_renderpass_t *), renderpass_cmp);
|
||||
|
|
Loading…
Reference in a new issue