diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index b4f555ea0..6288241e2 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -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, diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index e0acf580e..e50f72f3c 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_renderpass_h #define __QF_Vulkan_renderpass_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + #include "QF/darray.h" #include "QF/simd/types.h" diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h new file mode 100644 index 000000000..dcb3c760c --- /dev/null +++ b/include/QF/Vulkan/qf_translucent.h @@ -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 diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 1d74e90c1..595c920a7 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.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; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index f5569ed7f..19d8ac3be 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -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; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 03f698aa9..23d221fda 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -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 \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0c572e001..f859154b5 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -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); diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index 2ef03860a..37d45bdf0 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -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, diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 1d42f0c87..0a43ce36b 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -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, diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index c747fe651..595ec9f7a 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -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, { diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist index 008cb6b5a..fb2f279eb 100644 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ b/libs/video/renderer/vulkan/rp_deferred.plist @@ -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; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 133f23517..82d8c3547 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -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) }, diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 0c1df1795..eeaff7db7 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.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; diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index f6e35ceee..c85c42a1f 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -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); } diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index a98d91c02..c4726e5eb 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -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); } diff --git a/libs/video/renderer/vulkan/shader/oit.h b/libs/video/renderer/vulkan/shader/oit.h new file mode 100644 index 000000000..5569460ea --- /dev/null +++ b/libs/video/renderer/vulkan/shader/oit.h @@ -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; diff --git a/libs/video/renderer/vulkan/shader/oit_blend.frag b/libs/video/renderer/vulkan/shader/oit_blend.frag new file mode 100644 index 000000000..a32a5459d --- /dev/null +++ b/libs/video/renderer/vulkan/shader/oit_blend.frag @@ -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; +} diff --git a/libs/video/renderer/vulkan/shader/oit_store.finc b/libs/video/renderer/vulkan/shader/oit_store.finc new file mode 100644 index 000000000..539ed9e34 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/oit_store.finc @@ -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; + } +} diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag index 5a5f5a887..6499cdd35 100644 --- a/libs/video/renderer/vulkan/shader/particle.frag +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -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); } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 869ff825b..9cf245fff 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -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 diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 4cb3c0b70..5eed63d84 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -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, diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 09efc86e7..467b4546d 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -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 diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 763012428..79daf4755 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -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); } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 714f4c492..e624577cb 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -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); diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 992771803..95612b9b6 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -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 diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c new file mode 100644 index 000000000..1aff84ecd --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -0,0 +1,358 @@ +/* + vulkan_translucent.c + + Vulkan translucent pass pipeline + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + 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 +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#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); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d1f5153e9..f7df0a5b7 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -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);