diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index a1601f814..e4a21d52a 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -179,6 +179,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindIndexBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindDescriptorSets) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDraw) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDrawIndexed) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h new file mode 100644 index 000000000..f8fd497a1 --- /dev/null +++ b/include/QF/Vulkan/qf_compose.h @@ -0,0 +1,62 @@ +/* + qf_compose.h + + Vulkan compose pass + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/24 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_compose_h +#define __QF_Vulkan_qf_compose_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" + +#define COMPOSE_IMAGE_INFOS 2 + +typedef struct composeframe_s { + VkCommandBuffer cmd; + VkDescriptorImageInfo imageInfo[COMPOSE_IMAGE_INFOS]; + VkWriteDescriptorSet descriptors[COMPOSE_IMAGE_INFOS]; +} composeframe_t; + +typedef struct composeframeset_s + DARRAY_TYPE (composeframe_t) composeframeset_t; + +typedef struct composectx_s { + composeframeset_t frames; + VkPipeline pipeline; + VkPipelineLayout layout; +} composectx_t; + +struct vulkan_ctx_s; + +void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_Compose_Draw (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_compose_h diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h new file mode 100644 index 000000000..d2cee31ac --- /dev/null +++ b/include/QF/Vulkan/qf_lighting.h @@ -0,0 +1,65 @@ +/* + qf_lighting.h + + Vulkan lighting pass + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/23 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_lighting_h +#define __QF_Vulkan_qf_lighting_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" + +#define LIGHTING_BUFFER_INFOS 1 +#define LIGHTING_IMAGE_INFOS 3 + +typedef struct lightingframe_s { + VkCommandBuffer cmd; + VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS]; + VkDescriptorImageInfo imageInfo[LIGHTING_IMAGE_INFOS]; + VkWriteDescriptorSet descriptors[LIGHTING_BUFFER_INFOS + + LIGHTING_IMAGE_INFOS]; +} lightingframe_t; + +typedef struct lightingframeset_s + DARRAY_TYPE (lightingframe_t) lightingframeset_t; + +typedef struct lightingctx_s { + lightingframeset_t frames; + VkPipeline pipeline; + VkPipelineLayout layout; +} lightingctx_t; + +struct vulkan_ctx_s; + +void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_Lighting_Draw (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_lighting_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index a672f02d1..080b8079f 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -79,6 +79,11 @@ typedef struct vulkan_ctx_s { struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; struct drawctx_s *draw_context; + struct lightingctx_s *lighting_context; + struct composectx_s *compose_context; + + VkBuffer quad_buffer; + VkDeviceMemory quad_memory; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 93f6a51b4..8789de037 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -240,7 +240,9 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vkparse.c \ libs/video/renderer/vulkan/vulkan_alias.c \ libs/video/renderer/vulkan/vulkan_bsp.c \ + libs/video/renderer/vulkan/vulkan_compose.c \ libs/video/renderer/vulkan/vulkan_draw.c \ + libs/video/renderer/vulkan/vulkan_lighting.c \ libs/video/renderer/vulkan/vulkan_lightmap.c \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ @@ -285,6 +287,10 @@ bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc bsp_skyf_src = $(vkshaderpath)/bsp_sky.frag bsp_skyf_c = $(vkshaderpath)/bsp_sky.frag.spvc +lightingf_src = $(vkshaderpath)/lighting.frag +lightingf_c = $(vkshaderpath)/lighting.frag.spvc +composef_src = $(vkshaderpath)/compose.frag +composef_c = $(vkshaderpath)/compose.frag.spvc aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag @@ -316,6 +322,10 @@ $(bsp_gbuff_c): $(bsp_gbuff_src) $(bsp_skyf_c): $(bsp_skyf_src) +$(lightingf_c): $(lightingf_src) + +$(composef_c): $(composef_src) + $(aliasv_c): $(aliasv_src) $(alias_depth_c): $(alias_depth_src) @@ -338,6 +348,8 @@ vkshader_c = \ $(bsp_gbufg_c) \ $(bsp_gbuff_c) \ $(bsp_skyf_c) \ + $(lightingf_c) \ + $(composef_c) \ $(aliasv_c) \ $(alias_depth_c) \ $(aliasf_c) \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 9893c08da..059250fff 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -38,7 +38,9 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" +#include "QF/Vulkan/qf_compose.h" #include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" @@ -98,6 +100,8 @@ vulkan_R_Init (void) Vulkan_Bsp_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); + Vulkan_Lighting_Init (vulkan_ctx); + Vulkan_Compose_Init (vulkan_ctx); Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); @@ -140,6 +144,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) Vulkan_FlushText (vulkan_ctx); + Vulkan_Lighting_Draw (vulkan_ctx); + Vulkan_Compose_Draw (vulkan_ctx); + VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; VkRenderPassBeginInfo renderPassInfo = { @@ -602,6 +609,8 @@ vulkan_vid_render_shutdown (void) QFV_DeviceWaitIdle (device); df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Vulkan_Compose_Shutdown (vulkan_ctx); + Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index c03c30625..0245906da 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -179,7 +179,7 @@ { format = $properties.images.depth.format; samples = 1; - loadOp = dont_care; + loadOp = clear; storeOp = dont_care; stencilLoadOp = dont_care; stencilStoreOp = dont_care; @@ -238,14 +238,14 @@ }, ); subpasses = ( - { // depth + { // 0 depth pipelineBindPoint = graphics; depthStencilAttachment = { attachment = 0; layout = depth_stencil_attachment_optimal; }; }, - { // g-buffer generation + { // 1 g-buffer generation pipelineBindPoint = graphics; colorAttachments = ( { // color @@ -261,8 +261,9 @@ attachment = 0; layout = depth_stencil_attachment_optimal; }; + preserveAttachments = (4); }, - { // lighting + { // 2 lighting pipelineBindPoint = graphics; inputAttachments = ( { // depth @@ -284,8 +285,9 @@ layout = color_attachment_optimal; }, ); + preserveAttachments = (4); }, - { // translucent + { // 3 translucent pipelineBindPoint = graphics; colorAttachments = ( { // translucent @@ -293,8 +295,9 @@ layout = color_attachment_optimal; }, ); + preserveAttachments = (0, 1, 2, 3); }, - { // compose + { // 4 compose pipelineBindPoint = graphics; inputAttachments = ( { // opaque @@ -312,12 +315,13 @@ layout = color_attachment_optimal; }, ); + preserveAttachments = (0, 1, 2); }, ); dependencies = ( { - srcSubpass = 0; - dstSubpass = 1; + srcSubpass = 0; // depth + dstSubpass = 1; // g-buffer srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -325,8 +329,8 @@ dependencyFlags = by_region; }, { - srcSubpass = 1; - dstSubpass = 2; + srcSubpass = 1; // g-buffer + dstSubpass = 2; // lighting srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -334,8 +338,8 @@ dependencyFlags = by_region; }, { - srcSubpass = 2; - dstSubpass = 4; + srcSubpass = 2; // lighting + dstSubpass = 4; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -343,8 +347,8 @@ dependencyFlags = by_region; }, { - srcSubpass = 3; - dstSubpass = 4; + srcSubpass = 3; // translucent + dstSubpass = 4; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 03e200fc7..825f71a59 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -77,6 +77,36 @@ }, ); }; + lighting_attach_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = input_attachment; + descriptorCount = "3z * $frames.size"; + }, + ); + }; + lighting_lights_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = uniform_buffer; + descriptorCount = $frames.size; + }, + ); + }; + compose_attach_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = input_attachment; + descriptorCount = "2z * $frames.size"; + }, + ); + }; }; setLayouts = { twod_set = { @@ -208,20 +238,51 @@ }, ); }; - something = { - flags = 0; + lighting_attach = { bindings = ( { binding = 0; - descriptorType = sampled_image; + descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, { binding = 1; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_lights = { + bindings = ( + { + binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; - stageFlags = vertex; + stageFlags = fragment; + }, + ); + }; + compose_attach = { + bindings = ( + { + binding = 0; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; }, ); }; @@ -261,15 +322,11 @@ }, ); }; - something = { - setLayouts = (something); - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4 * 4"; - }, - ); + lighting_layout = { + setLayouts = (lighting_attach, lighting_lights); + }; + compose_layout = { + setLayouts = (compose_attach); }; }; pipelines = { @@ -758,6 +815,194 @@ layout = twod_layout; //renderPass = renderpass; }; + lighting = { + subpass = 2; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/passthrough.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/lighting.frag; + }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + ); + }; + inputAssembly = { + topology = triangle_strip; + primitiveRestartEnable = false; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ( + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + ); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = lighting_layout; + //renderPass = renderpass; + }; + compose = { + subpass = 4; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/passthrough.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/compose.frag; + }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + ); + }; + inputAssembly = { + topology = triangle_strip; + primitiveRestartEnable = false; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ( + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + ); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = compose_layout; + //renderPass = renderpass; + }; }; renderpass = { attachments = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 4063e6f33..4168d9b63 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -73,6 +73,10 @@ static static #include "libs/video/renderer/vulkan/shader/bsp_sky.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/lighting.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/compose.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static #include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" @@ -101,6 +105,8 @@ static shaderdata_t builtin_shaders[] = { { "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) }, { "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) }, { "bsp_sky.frag", bsp_sky_frag, sizeof (bsp_sky_frag) }, + { "lighting.frag", lighting_frag, sizeof (lighting_frag) }, + { "compose.frag", compose_frag, sizeof (compose_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/compose.frag b/libs/video/renderer/vulkan/shader/compose.frag new file mode 100644 index 000000000..39ac94845 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/compose.frag @@ -0,0 +1,19 @@ +#version 450 + +layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput opaque; +layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput translucent; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec3 o; + vec4 t; + vec3 c; + + o = subpassLoad (opaque).rgb; + t = subpassLoad (translucent); + c = mix (o, t.rgb, t.a); + frag_color = vec4 (c, 1); +} diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag new file mode 100644 index 000000000..555682645 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -0,0 +1,33 @@ +#version 450 + +layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput depth; +layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput color; +layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput normal; + +struct LightData { + vec3 color; + float dist; + vec3 position; + int type; + vec3 direction; + float cone; +}; + +layout (constant_id = 0) const int MaxLights = 8; +/*layout (set = 1, binding = 0) uniform Lights { + int lightCount; + LightData lights[MaxLights]; +};*/ + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + float d = subpassLoad (depth).r; + vec4 c; + + //c = vec4 (d, d, d, 1); + c = vec4 (subpassLoad (color).rgb, 1); + frag_color = c; +} diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 72ec5abbb..de12d60c0 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1259,6 +1259,8 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]); const char *name = PL_KeyAtIndex (item, i); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, set->a[i], + va (ctx->va_ctx, "image:%s", name)); name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 8468335c1..d3663d0df 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -176,8 +176,7 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); //VkDescriptorSet sets[] = { // aframe->descriptors[0].dstSet, // aframe->descriptors[1].dstSet, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 8b33cebb3..046ba6c0a 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -827,6 +827,15 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, continue; dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index, 0, 0); + } +} + +static void +reset_elechain (elechain_t *ec) +{ + elements_t *el; + + for (el = ec->elements; el; el = el->next) { el->first_index = 0; el->index_count = 0; } @@ -1167,6 +1176,7 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) bframe->cmdSet.a[QFV_bspDepth]); draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspGBuffer]); + reset_elechain (ec); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1280,6 +1290,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc,//FIXME bframe->cmdSet.a[QFV_bspTranslucent]); + reset_elechain (ec); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1295,6 +1306,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc,//FIXME bframe->cmdSet.a[QFV_bspTranslucent]); + reset_elechain (ec); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c new file mode 100644 index 000000000..e2748dcb3 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -0,0 +1,175 @@ +/* + vulkan_compose.c + + Vulkan compose pass pipeline + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/23 + + 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/sys.h" + +#include "QF/Vulkan/qf_compose.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +void +Vulkan_Compose_Draw (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + composectx_t *cctx = ctx->compose_context; + __auto_type frame = &ctx->frames.a[ctx->curFrame]; + composeframe_t *cframe = &cctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = cframe->cmd; + + DARRAY_APPEND (&frame->cmdSets[QFV_passCompose], cmd); + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass, QFV_passCompose, + frame->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); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + cctx->pipeline); + + cframe->imageInfo[0].imageView = ctx->attachment_views->a[3]; + cframe->imageInfo[1].imageView = ctx->attachment_views->a[4]; + dfunc->vkUpdateDescriptorSets (device->dev, 2, cframe->descriptors, 0, 0); + + VkDescriptorSet sets[] = { + cframe->descriptors[0].dstSet, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + cctx->layout, 0, 1, sets, 0, 0); + + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + + VkDeviceSize offset = 0; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); + dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + + dfunc->vkEndCommandBuffer (cmd); +} + +static VkDescriptorImageInfo base_image_info = { + 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL +}; +static VkWriteDescriptorSet base_image_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + 0, 0, 0 +}; + +void +Vulkan_Compose_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + composectx_t *cctx = calloc (1, sizeof (composectx_t)); + ctx->compose_context = cctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&cctx->frames, frames); + DARRAY_RESIZE (&cctx->frames, frames); + cctx->frames.grow = 0; + + cctx->pipeline = Vulkan_CreatePipeline (ctx, "compose"); + cctx->layout = Vulkan_CreatePipelineLayout (ctx, "compose_layout"); + + __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); + + __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < frames; i++) { + attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, + "compose_attach"); + } + __auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx, + "compose_attach_pool"); + + __auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool, + attach); + for (size_t i = 0; i < frames; i++) { + __auto_type cframe = &cctx->frames.a[i]; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); + cframe->cmd = cmdSet->a[0]; + + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + cframe->cmd, "cmd:compose"); + for (int j = 0; j < COMPOSE_IMAGE_INFOS; j++) { + cframe->imageInfo[j] = base_image_info; + cframe->imageInfo[j].sampler = 0; + cframe->descriptors[j] = base_image_write; + cframe->descriptors[j].dstSet = attach_set->a[i]; + cframe->descriptors[j].dstBinding = j; + cframe->descriptors[j].pImageInfo = &cframe->imageInfo[j]; + } + } + free (attach_set); +} + +void +Vulkan_Compose_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + composectx_t *cctx = ctx->compose_context; + + dfunc->vkDestroyPipeline (device->dev, cctx->pipeline, 0); + free (cctx->frames.a); + free (cctx); +} diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c new file mode 100644 index 000000000..604e7ff94 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -0,0 +1,202 @@ +/* + vulkan_lighting.c + + Vulkan lighting pass pipeline + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/23 + + 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/sys.h" + +#include "QF/Vulkan/qf_lighting.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +void +Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + lightingctx_t *lctx = ctx->lighting_context; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; + lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = lframe->cmd; + + DARRAY_APPEND (&cframe->cmdSets[QFV_passLighting], cmd); + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass, QFV_passLighting, + cframe->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); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + lctx->pipeline); + + lframe->imageInfo[0].imageView = ctx->attachment_views->a[0]; + lframe->imageInfo[1].imageView = ctx->attachment_views->a[1]; + lframe->imageInfo[2].imageView = ctx->attachment_views->a[2]; + dfunc->vkUpdateDescriptorSets (device->dev, 3, lframe->descriptors+1, 0, 0); + + VkDescriptorSet sets[] = { + lframe->descriptors[1].dstSet, + lframe->descriptors[0].dstSet, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + lctx->layout, 0, 2, sets, 0, 0); + + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + + VkDeviceSize offset = 0; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); + dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + + dfunc->vkEndCommandBuffer (cmd); +} + +static VkDescriptorBufferInfo base_buffer_info = { + 0, 0, VK_WHOLE_SIZE +}; +static VkDescriptorImageInfo base_image_info = { + 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL +}; +static VkWriteDescriptorSet base_buffer_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, 0, 0 +}; +static VkWriteDescriptorSet base_image_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + 0, 0, 0 +}; + +void +Vulkan_Lighting_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); + ctx->lighting_context = lctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&lctx->frames, frames); + DARRAY_RESIZE (&lctx->frames, frames); + lctx->frames.grow = 0; + + lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting"); + lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); + + __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); + + __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + __auto_type lights = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < frames; i++) { + attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, + "lighting_attach"); + lights->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, + "lighting_lights"); + } + __auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx, + "lighting_attach_pool"); + __auto_type lights_pool = Vulkan_CreateDescriptorPool (ctx, + "lighting_lights_pool"); + + __auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool, + attach); + __auto_type lights_set = QFV_AllocateDescriptorSet (device, lights_pool, + lights); + for (size_t i = 0; i < frames; i++) { + __auto_type lframe = &lctx->frames.a[i]; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); + lframe->cmd = cmdSet->a[0]; + + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + lframe->cmd, "cmd:lighting"); + for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) { + lframe->bufferInfo[j] = base_buffer_info; + lframe->descriptors[j] = base_buffer_write; + lframe->descriptors[j].dstSet = lights_set->a[i]; + lframe->descriptors[j].dstBinding = j; + lframe->descriptors[j].pBufferInfo = &lframe->bufferInfo[j]; + } + for (int j = 0; j < LIGHTING_IMAGE_INFOS; j++) { + lframe->imageInfo[j] = base_image_info; + lframe->imageInfo[j].sampler = 0; + int k = j + LIGHTING_BUFFER_INFOS; + lframe->descriptors[k] = base_image_write; + lframe->descriptors[k].dstSet = attach_set->a[i]; + lframe->descriptors[k].dstBinding = j; + lframe->descriptors[k].pImageInfo = &lframe->imageInfo[j]; + } + } + free (attach_set); + free (lights_set); +} + +void +Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + lightingctx_t *lctx = ctx->lighting_context; + + dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); + free (lctx->frames.a); + free (lctx); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 98fec5945..909f26236 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -324,6 +324,53 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) item = qfv_load_renderpass (ctx, "clearValues"); QFV_ParseClearValues (ctx, item, ctx->renderpassDef); printf ("renderpass: %p\n", ctx->renderpass); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + static float quad_vertices[] = { + -1, -1, 0, 1, + -1, 1, 0, 1, + 1, -1, 0, 1, + 1, 1, 0, 1, + }; + ctx->quad_buffer = QFV_CreateBuffer (device, sizeof (quad_vertices), + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT); + ctx->quad_memory = QFV_AllocBufferMemory (device, ctx->quad_buffer, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_BindBufferMemory (device, ctx->quad_buffer, ctx->quad_memory, 0); + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + float *verts = QFV_PacketExtend (packet, sizeof (quad_vertices)); + memcpy (verts, quad_vertices, sizeof (quad_vertices)); + + VkBufferMemoryBarrier wr_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ctx->quad_buffer, 0, sizeof (quad_vertices) }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 1, wr_barriers, 0, 0); + VkBufferCopy copy_region[] = { + { packet->offset, 0, sizeof (quad_vertices) }, + }; + dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, + ctx->quad_buffer, 1, ©_region[0]); + VkBufferMemoryBarrier rd_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ctx->quad_buffer, 0, sizeof (quad_vertices) }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, 0, 1, rd_barriers, 0, 0); + QFV_PacketSubmit (packet); } void @@ -333,6 +380,9 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroyRenderPass (device->dev, ctx->renderpass, 0); + + dfunc->vkFreeMemory (device->dev, ctx->quad_memory, 0); + dfunc->vkDestroyBuffer (device->dev, ctx->quad_buffer, 0); } VkPipeline