diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 9942562b2..5e5623137 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -3,8 +3,17 @@ #include "QF/darray.h" -typedef struct qfv_imageset_s DARRAY_TYPE (VkImage) qfv_imageset_t; -typedef struct qfv_imageviewset_s DARRAY_TYPE (VkImageView) qfv_imageviewset_t; +typedef struct qfv_imageset_s + DARRAY_TYPE (VkImage) qfv_imageset_t; + +#define QFV_AllocImages(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_imageset_t, num, allocator) + +typedef struct qfv_imageviewset_s + DARRAY_TYPE (VkImageView) qfv_imageviewset_t; + +#define QFV_AllocImageViews(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_imageviewset_t, num, allocator) typedef struct qfv_imageresource_s { struct qfv_device_s *device; diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 714cb06b3..597888a4d 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -36,6 +36,7 @@ #include "QF/model.h" #include "QF/modelgen.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" typedef struct aliasvrt_s { float vertex[4]; @@ -61,32 +62,22 @@ typedef struct qfv_alias_skin_s { byte colorb[4]; } qfv_alias_skin_t; -typedef struct qfv_light_s { - vec3_t color; - float dist; - vec3_t position; - int type; - vec3_t direction; - float cone; -} qfv_light_t; - -#define ALIAS_LIGHTS 8 - -typedef struct qfv_light_buffer_s { - int light_count; - qfv_light_t lights[ALIAS_LIGHTS] __attribute__((aligned(16))); -} qfv_light_buffer_t; - -#define ALIAS_BUFFER_INFOS 2 +#define ALIAS_BUFFER_INFOS 1 #define ALIAS_IMAGE_INFOS 1 +enum { + QFV_aliasDepth, + QFV_aliasGBuffer, + //QFV_aliasTranslucent, + + QFV_aliasNumPasses +}; + typedef struct aliasframe_s { - VkCommandBuffer cmd; + qfv_cmdbufferset_t cmdSet; VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS]; VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS]; - qfv_light_buffer_t *lights; - VkBuffer light_buffer; } aliasframe_t; typedef struct aliasframeset_s @@ -94,11 +85,10 @@ typedef struct aliasframeset_s typedef struct aliasctx_s { aliasframeset_t frames; - VkPipeline pipeline; + VkPipeline depth; + VkPipeline gbuf; VkPipelineLayout layout; VkSampler sampler; - - VkDeviceMemory light_memory; } aliasctx_t; struct vulkan_ctx_s; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 151e6e7be..b78aaf643 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -35,6 +35,7 @@ #include "QF/darray.h" #include "QF/model.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" typedef struct bspvert_s { quat_t vertex; @@ -69,13 +70,19 @@ typedef enum { // Texture, GlowMap, LightMap, SkySheet, SkyCube #define BSP_IMAGE_INFOS 5 +enum { + QFV_bspDepth, + QFV_bspGBuffer, + QFV_bspTranslucent, + + QFV_bspNumPasses +}; + typedef struct bspframe_s { uint32_t *index_data; // pointer into mega-buffer for this frame (c) uint32_t index_offset; // offset of index_data within mega-buffer (c) uint32_t index_count; // number if indices queued (d) - VkCommandBuffer bsp_cmd; - VkCommandBuffer turb_cmd; - VkCommandBuffer sky_cmd; + qfv_cmdbufferset_t cmdSet; VkDescriptorBufferInfo bufferInfo[BSP_BUFFER_INFOS]; VkDescriptorImageInfo imageInfo[BSP_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS]; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 1102845b5..f81e934a1 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -35,9 +35,22 @@ #endif #include +//FIXME location +enum { + QFV_passDepth, // geometry + QFV_passGBuffer, // geometry + QFV_passTranslucent, // geometry + QFV_passLighting, // single quad + QFV_passCompose, // single quad + + QFV_NumPasses +}; + struct vulkan_ctx_s; -void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); +void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 49134c730..a584d476d 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -27,6 +27,12 @@ typedef struct qfv_subpassdependency_s #define QFV_AllocSubpassDependencies(num, allocator) \ DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator) +typedef struct qfv_framebufferset_s + DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t; + +#define QFV_AllocFrameBuffers(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator) + struct qfv_device_s; struct qfv_imageviewset_s; VkRenderPass diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 4ddab99e3..dcf4f624b 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -8,20 +8,15 @@ #include "QF/darray.h" -typedef struct vulkan_renderpass_s { - VkRenderPass renderpass; - struct qfv_imageresource_s *colorImage; - struct qfv_imageresource_s *depthImage; -} vulkan_renderpass_t; - -typedef struct vulkan_framebuffer_s { +typedef struct vulkan_frame_s { VkFramebuffer framebuffer; VkFence fence; VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; VkCommandBuffer cmdBuffer; - struct qfv_cmdbufferset_s *subCommand; + int cmdSetCount; + struct qfv_cmdbufferset_s *cmdSets; } vulkan_frame_t; typedef struct vulkan_matrices_s { @@ -59,11 +54,22 @@ typedef struct vulkan_ctx_s { VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain struct plitem_s *pipelineDef; + struct plitem_s *renderpassDef; + VkRenderPass renderpass; + struct qfv_imageset_s *attachment_images; + struct qfv_imageviewset_s *attachment_views; + VkDeviceMemory attachmentMemory; + + uint32_t swapImageIndex; + struct qfv_framebufferset_s *framebuffers; + struct hashtab_s *shaderModules; struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; struct hashtab_s *descriptorPools; struct hashtab_s *samplers; + struct hashtab_s *images; + struct hashtab_s *imageViews; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; @@ -72,7 +78,6 @@ typedef struct vulkan_ctx_s { VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only - vulkan_renderpass_t renderpass; struct qfv_stagebuf_s *staging; VkPipeline pipeline; size_t curFrame; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index cb0eec6d1..66db70d11 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -209,6 +209,8 @@ libs_video_renderer_vid_render_sw32_la_SOURCES=\ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc +renderpass_src = libs/video/renderer/vulkan/deferred.plist +renderpass_gen = libs/video/renderer/vulkan/deferred.plc video_renderer_vulkan_libs = \ libs/models/libmodels_vulkan.la @@ -250,7 +252,7 @@ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vk libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) -libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) +libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${renderpass_gen} qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a41a1d960..b8f9dc718 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -87,8 +87,9 @@ vulkan_R_Init (void) Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); - Vulkan_CreateFramebuffers (vulkan_ctx); + Vulkan_CreateFrames (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); + Vulkan_CreateFramebuffers (vulkan_ctx); // FIXME this should be staged so screen updates can begin while pipelines // are being built vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); @@ -111,6 +112,8 @@ vulkan_R_Init (void) static void vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { + const VkSubpassContents subpassContents + = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; static int count = 0; static double startTime; uint32_t imageIndex = 0; @@ -128,20 +131,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) QFV_AcquireNextImage (vulkan_ctx->swapchain, frame->imageAvailableSemaphore, 0, &imageIndex); + vulkan_ctx->swapImageIndex = imageIndex; - int attachCount = vulkan_ctx->msaaSamples > 1 ? 3 : 2; - __auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, - attachCount, alloca); - qfv_swapchain_t *sc = vulkan_ctx->swapchain; - attachments->a[0] = sc->imageViews->a[imageIndex]; - attachments->a[1] = vulkan_ctx->renderpass.depthImage->view; - if (attachCount > 2) { - attachments->a[2] = vulkan_ctx->renderpass.colorImage->view; - } - - VkRenderPass renderpass = vulkan_ctx->renderpass.renderpass; - frame->framebuffer = QFV_CreateFramebuffer (device, renderpass, - attachments, sc->extent, 1); + frame->framebuffer = vulkan_ctx->framebuffers->a[imageIndex]; scr_3dfunc (); while (*scr_funcs) { @@ -160,20 +152,26 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) }; VkRenderPassBeginInfo renderPassInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, - vulkan_ctx->renderpass.renderpass, 0, - { {0, 0}, sc->extent }, + vulkan_ctx->renderpass, 0, + { {0, 0}, vulkan_ctx->swapchain->extent }, 3, clearValues }; dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); renderPassInfo.framebuffer = frame->framebuffer; dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + subpassContents); - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->subCommand->size, - frame->subCommand->a); - // reset for next time around - frame->subCommand->size = 0; + for (int i = 0; i < frame->cmdSetCount; i++) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->cmdSets[i].size, + frame->cmdSets[i].a); + // reset for next time around + frame->cmdSets[i].size = 0; + + if (i < frame->cmdSetCount) { + dfunc->vkCmdNextSubpass (frame->cmdBuffer, subpassContents); + } + } dfunc->vkCmdEndRenderPass (frame->cmdBuffer); dfunc->vkEndCommandBuffer (frame->cmdBuffer); diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist new file mode 100644 index 000000000..e7e7e1f12 --- /dev/null +++ b/libs/video/renderer/vulkan/deferred.plist @@ -0,0 +1,342 @@ +{ + images = { + depth = { + imageType = VK_IMAGE_TYPE_2D; //FIXME short form is 2d... + format = x8_d24_unorm_pack32; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = depth_stencil_attachment|input_attachment; + }; + color = { + imageType = VK_IMAGE_TYPE_2D; + format = r8g8b8a8_unorm; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + normals = { + imageType = VK_IMAGE_TYPE_2D; + format = r16g16b16a16_sfloat; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + opaque = { + imageType = VK_IMAGE_TYPE_2D; + format = r8g8b8a8_unorm; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + translucent = { + imageType = VK_IMAGE_TYPE_2D; + format = r8g8b8a8_unorm; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + }; + imageViews = { + depth = { + image = depth; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.depth.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = depth; + levelCount = 1; + layerCount = 1; + }; + }; + color = { + image = color; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.color.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + normals = { + image = normals; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.normals.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + opaque = { + image = opaque; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.opaque.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + translucent = { + image = translucent; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.translucent.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + }; + framebuffer = { + renderPass = renderpass; + attachments = (depth, color, normals, opaque, translucent, + "$swapchain.views[$swapImageIndex]"); + width = $swapchain.extent.width; + height = $swapchain.extent.height; + }; + renderpass = { + attachments = ( + { + format = $properties.images.depth.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = depth_stencil_attachment_optimal; + }, + { + format = $properties.images.color.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $properties.images.normals.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $properties.images.opaque.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $properties.images.translucent.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $swapchain.format; + samples = 1; + loadOp = clear; + storeOp = store; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = present_src_khr; + }, + ); + subpasses = ( + { // depth + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + }, + { // g-buffer generation + pipelineBindPoint = graphics; + colorAttachments = ( + { // color + attachment = 1; + layout = color_attachment_optimal; + }, + { // normals + attachment = 2; + layout = color_attachment_optimal; + }, + ); + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + }, + { // lighting + pipelineBindPoint = graphics; + inputAttachments = ( + { // depth + attachment = 0; + layout = shader_read_only_optimal; + }, + { // color + attachment = 1; + layout = shader_read_only_optimal; + }, + { // normals + attachment = 2; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // opaque + attachment = 3; + layout = color_attachment_optimal; + }, + ); + }, + { // translucent + pipelineBindPoint = graphics; + colorAttachments = ( + { // translucent + attachment = 4; + layout = color_attachment_optimal; + }, + ); + }, + { // compose + pipelineBindPoint = graphics; + inputAttachments = ( + { // opaque + attachment = 3; + layout = shader_read_only_optimal; + }, + { // translucent + attachment = 4; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // swapchain + attachment = 5; + layout = color_attachment_optimal; + }, + ); + }, + ); + dependencies = ( + { + srcSubpass = 0; + dstSubpass = 1; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 1; + dstSubpass = 2; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 2; + dstSubpass = 4; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 3; + dstSubpass = 4; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + ); + }; +} diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 324e08e7c..2cd110385 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -273,7 +273,45 @@ }; }; pipelines = { - alias = { + alias_depth = { + stages = ( + { + stage = vertex; + name = main; + module = $builtin/alias.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.pipelines.alias_gbuf.vertexInput.bindings[0]", + "$properties.pipelines.alias_gbuf.vertexInput.bindings[1]", + ); + attributes = ( + "$properties.pipelines.alias_gbuf.vertexInput.attributes[0]", + "$properties.pipelines.alias_gbuf.vertexInput.attributes[1]", + "$properties.pipelines.alias_gbuf.vertexInput.attributes[2]", + "$properties.pipelines.alias_gbuf.vertexInput.attributes[3]", + ); + }; + inputAssembly = $properties.pipelines.alias_gbuf.inputAssembly; + viewport = $properties.pipelines.alias_gbuf.viewport; + rasterization = $properties.pipelines.alias_gbuf.rasterization; + multisample = $properties.pipelines.alias_gbuf.multisample; + depthStencil = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = $properties.pipelines.alias_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = alias_layout; + //renderPass = renderpass; + }; + alias_gbuf = { stages = ( { stage = vertex; @@ -404,7 +442,41 @@ layout = alias_layout; //renderPass = renderpass; }; - quakebsp_main = { + bsp_depth = { + stages = ( + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.pipelines.bsp_gbuf.vertexInput.bindings[0]", + ); + attributes = ( + "$properties.pipelines.bsp_gbuf.vertexInput.attributes[0]", + ); + }; + inputAssembly = $properties.pipelines.bsp_main.inputAssembly; + viewport = $properties.pipelines.bsp_main.viewport; + rasterization = $properties.pipelines.bsp_main.rasterization; + multisample = $properties.pipelines.bsp_main.multisample; + depthStencil = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = quakebsp_layout; + //renderPass = renderpass; + }; + bsp_gbuf = { stages = ( { stage = vertex; @@ -523,86 +595,15 @@ }; }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "2 * 4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, - { - location = 1; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 16; - }, - ); - }; - inputAssembly = { - topology = triangle_fan; - primitiveRestartEnable = true; - }; - 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 = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - depthStencil = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - colorBlend = { - logicOpEnable = false; - attachments = ({ - blendEnable = true; - 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; - }); - }; + vertexInput = $properties.pipelines.bsp_gbuf.vertexInput; + inputAssembly = $properties.pipelines.bsp_gbuf.inputAssembly; + viewport = $properties.pipelines.bsp_gbuf.viewport; + rasterization = $properties.pipelines.bsp_gbuf.rasterization; + multisample = $properties.pipelines.bsp_gbuf.multisample; + depthStencil = $properties.pipelines.bsp_gbuf.depthStencil; + colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); + dynamicState = ( viewport, scissor ); }; layout = quakebsp_layout; //renderPass = renderpass; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index ad2696c8f..2d9b3c806 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -460,7 +460,8 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, ret = !cexpr_eval_string (name, &ectx); if (ret) { VkDescriptorSetLayout setLayout; - setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem); + setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem, + pctx->properties); *handle = (VkDescriptorSetLayout) setLayout; QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout); @@ -495,7 +496,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, ret = !cexpr_eval_string (name, &ectx); if (ret) { VkPipelineLayout layout; - layout = QFV_ParsePipelineLayout (ctx, setItem); + layout = QFV_ParsePipelineLayout (ctx, setItem, context->properties); *handle = (VkPipelineLayout) layout; QFV_AddHandle (ctx->pipelineLayouts, name, (uint64_t) layout); @@ -503,6 +504,92 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, return ret; } +static int +parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, + parsectx_t *context) +{ + __auto_type handle = (VkImage *) data[0]; + int ret = 1; + exprctx_t ectx = *context->ectx; + vulkan_ctx_t *ctx = context->vctx; + + const char *name = PL_String (item); + Sys_Printf ("parse_VkImage: %s\n", name); + if (name[0] != '$') { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); + } + + *handle = (VkImage) QFV_GetHandle (ctx->images, name); + if (*handle) { + return 1; + } + + plitem_t *imageItem = 0; + exprval_t result = { &cexpr_plitem, &imageItem }; + ectx.symtab = 0; + ectx.result = &result; + ret = !cexpr_eval_string (name, &ectx); + if (ret) { + VkImage image; + image = QFV_ParseImage (ctx, imageItem, context->properties); + *handle = (VkImage) image; + + QFV_AddHandle (ctx->images, name, (uint64_t) image); + } + return ret; +} + +static exprtype_t imageview_type = { + "VkImageView", + sizeof (VkImageView), + 0, 0, 0 +}; + +static int +parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *_context) +{ + parsectx_t *context = _context; + __auto_type handle = (VkImageView *) data; + int ret = 1; + exprctx_t ectx = *context->ectx; + vulkan_ctx_t *ctx = context->vctx; + + const char *name = PL_String (item); + Sys_Printf ("parse_VkImageView: %s\n", name); + if (name[0] != '$') { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); + } + + *handle = (VkImageView) QFV_GetHandle (ctx->imageViews, name); + if (*handle) { + return 1; + } + + exprval_t *value = 0; + exprval_t result = { &cexpr_exprval, &value }; + ectx.symtab = 0; + ectx.result = &result; + ret = !cexpr_eval_string (name, &ectx); + + plitem_t *imageViewItem = 0; + if (ret) { + VkImageView imageView; + if (value->type == &imageview_type) { + imageView = *(VkImageView *) value->value; + } else if (value->type == &cexpr_plitem) { + imageView = QFV_ParseImageView (ctx, imageViewItem, + context->properties); + QFV_AddHandle (ctx->imageViews, name, (uint64_t) imageView); + } else { + PL_Message (messages, item, "not a VkImageView"); + return 0; + } + *handle = (VkImageView) imageView; + } + return ret; +} + static const char * handleref_getkey (const void *hr, void *unused) { @@ -592,6 +679,36 @@ sampler_free (void *hr, void *_ctx) handleref_free (handleref, ctx); } +static void +image_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type image = (VkImage) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (image) { + dfunc->vkDestroyImage (device->dev, image, 0); + }; + handleref_free (handleref, ctx); +} + +static void +imageView_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type imageView = (VkImageView) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (imageView) { + dfunc->vkDestroyImageView (device->dev, imageView, 0); + }; + handleref_free (handleref, ctx); +} + static hashtab_t *enum_symtab; static int @@ -605,23 +722,71 @@ parse_BasePipeline (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static exprsym_t imageset_symbols[] = { - {"size", &cexpr_size_t, (void *)field_offset (qfv_imageset_t, size)}, +static void +imageviewset_index (const exprval_t *a, size_t index, exprval_t *c, + exprctx_t *ctx) +{ + __auto_type set = *(qfv_imageviewset_t **) a->value; + exprval_t *val = 0; + if (index >= set->size) { + cexpr_error (ctx, "invalid index: %zd", index); + } else { + val = cexpr_value (&imageview_type, ctx); + *(VkImageView *) val->value = set->a[index]; + } + *(exprval_t **) c->value = val; +} + +static void +imageviewset_int (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + size_t index = *(int *) b->value; + imageviewset_index (a, index, c, ctx); +} + +static void +imageviewset_uint (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + size_t index = *(unsigned *) b->value; + imageviewset_index (a, index, c, ctx); +} + +static void +imageviewset_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + size_t index = *(size_t *) b->value; + imageviewset_index (a, index, c, ctx); +} + +binop_t imageviewset_binops[] = { + { '.', &cexpr_field, &cexpr_exprval, cexpr_struct_pointer_getfield }, + { '[', &cexpr_int, &imageview_type, imageviewset_int }, + { '[', &cexpr_uint, &imageview_type, imageviewset_uint }, + { '[', &cexpr_size_t, &imageview_type, imageviewset_size_t }, + {} +}; + +static exprsym_t imageviewset_symbols[] = { + {"size", &cexpr_size_t, (void *)field_offset (qfv_imageviewset_t, size)}, { } }; -static exprtab_t imageset_symtab = { - imageset_symbols, +static exprtab_t imageviewset_symtab = { + imageviewset_symbols, }; -exprtype_t imageset_type = { - "imageset", - sizeof (qfv_imageset_t *), - cexpr_struct_pointer_binops, +exprtype_t imageviewset_type = { + "imageviewset", + sizeof (qfv_imageviewset_t *), + imageviewset_binops, 0, - &imageset_symtab, + &imageviewset_symtab, }; static exprsym_t qfv_swapchain_t_symbols[] = { {"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)}, - {"images", &imageset_type, (void *)field_offset (qfv_swapchain_t, images)}, + {"extent", &VkExtent2D_type, (void *)field_offset (qfv_swapchain_t, extent)}, + {"views", &imageviewset_type, (void *)field_offset (qfv_swapchain_t, imageViews)}, { } }; static exprtab_t qfv_swapchain_t_symtab = { @@ -714,7 +879,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) vkgen_init_symtabs (&context); cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); - cexpr_init_symtab (&imageset_symtab, &context); + cexpr_init_symtab (&imageviewset_symtab, &context); if (!ctx->setLayouts) { ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); @@ -722,6 +887,8 @@ QFV_InitParse (vulkan_ctx_t *ctx) ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx); ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx); ctx->samplers = handlref_symtab (sampler_free, ctx); + ctx->images = handlref_symtab (image_free, ctx); + ctx->imageViews = handlref_symtab (imageView_free, ctx); } } @@ -733,16 +900,17 @@ QFV_GetEnum (const char *name) static int parse_object (vulkan_ctx_t *ctx, plitem_t *plist, - plparser_t parser, void *object) + plparser_t parser, void *object, plitem_t *properties) { plitem_t *messages = PL_NewArray (); exprctx_t exprctx = {}; - parsectx_t parsectx = { &exprctx, ctx }; + parsectx_t parsectx = { &exprctx, ctx, properties }; exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {QFV_PROPERTIES, &cexpr_plitem, &ctx->pipelineDef}, + {"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex}, + {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, {} }; exprtab_t vars_tab = { var_syms, 0 }; @@ -775,13 +943,14 @@ parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data, } VkRenderPass -QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_renderpass_t renderpass_data = {}; - if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data)) { + if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data, + properties)) { return 0; } @@ -805,7 +974,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) } VkPipeline -QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; @@ -813,11 +982,11 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); if (!parse_object (ctx, plist, parse_VkGraphicsPipelineCreateInfo, - &cInfo->a[0])) { + &cInfo->a[0], properties)) { return 0; } - cInfo->a[0].renderPass = ctx->renderpass.renderpass; + cInfo->a[0].renderPass = ctx->renderpass; __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); VkPipeline pipeline = plSet->a[0]; free (plSet); @@ -825,14 +994,16 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) } VkDescriptorPool -QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; VkDescriptorPoolCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo)) { + if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo, + properties)) { return 0; } @@ -843,7 +1014,8 @@ QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist) } VkDescriptorSetLayout -QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -851,7 +1023,7 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) VkDescriptorSetLayoutCreateInfo cInfo = {}; if (!parse_object (ctx, plist, parse_VkDescriptorSetLayoutCreateInfo, - &cInfo)) { + &cInfo, properties)) { return 0; } @@ -862,7 +1034,8 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) } VkPipelineLayout -QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -870,7 +1043,7 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) VkPipelineLayoutCreateInfo cInfo = {}; if (!parse_object (ctx, plist, parse_VkPipelineLayoutCreateInfo, - &cInfo)) { + &cInfo, properties)) { return 0; } @@ -881,14 +1054,15 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) } VkSampler -QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; VkSamplerCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo)) { + if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo, + properties)) { return 0; } @@ -897,3 +1071,195 @@ QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist) return sampler; } + +VkImage +QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkImageCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkImageCreateInfo, &cInfo, + properties)) { + return 0; + } + + VkImage image; + dfunc->vkCreateImage (device->dev, &cInfo, 0, &image); + + return image; +} + +VkImageView +QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkImageViewCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkImageViewCreateInfo, &cInfo, + properties)) { + return 0; + } + + VkImageView imageView; + dfunc->vkCreateImageView (device->dev, &cInfo, 0, &imageView); + + return imageView; +} + +typedef struct { + uint32_t count; + VkImageCreateInfo *info; +} imagecreate_t; + +typedef struct { + uint32_t count; + VkImageViewCreateInfo *info; +} imageviewcreate_t; + +static plelement_t qfv_imagecreate_dict = { + QFDictionary, + sizeof (VkImageCreateInfo), + array_alloc, + parse_VkImageCreateInfo, +}; + +static plelement_t qfv_imageviewcreate_dict = { + QFDictionary, + sizeof (VkImageViewCreateInfo), + array_alloc, + parse_VkImageViewCreateInfo, +}; + +static int +parse_imagecreate_dict (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + plfield_t f = { "images", 0, QFArray, parse_array, + &qfv_imagecreate_dict }; + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr = 0; + int ret; + + if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) { + imagecreate_t *imagecreate = data; + imagecreate->count = arr->size; + imagecreate->info = (VkImageCreateInfo *) arr->a; + } else { + //FIXME leaky boat when succeeds + if (arr) { + free (arr); + } + } + return ret; +} + +static int +parse_imageviewcreate_dict (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + plfield_t f = { "images", 0, QFArray, parse_array, + &qfv_imageviewcreate_dict }; + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr = 0; + int ret; + + if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) { + imageviewcreate_t *imageviewcreate = data; + imageviewcreate->count = arr->size; + imageviewcreate->info = (VkImageViewCreateInfo *) arr->a; + } else { + //FIXME leaky boat when succeeds + if (arr) { + free (arr); + } + } + return ret; +} + +qfv_imageset_t * +QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + imagecreate_t create = {}; + + pltype_t type = PL_Type (item); + + if (type == QFDictionary) { + if (!parse_object (ctx, item, parse_imagecreate_dict, &create, + properties)) { + return 0; + } + } else { + Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); + return 0; + } + + __auto_type set = QFV_AllocImages (create.count, malloc); + for (uint32_t i = 0; i < create.count; i++) { + dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]); + + const char *name = PL_KeyAtIndex (item, i); + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); + QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); + } + + return set; +} + +qfv_imageviewset_t * +QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, + plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + imageviewcreate_t create = {}; + + pltype_t type = PL_Type (item); + + if (type == QFDictionary) { + if (!parse_object (ctx, item, parse_imageviewcreate_dict, &create, + properties)) { + return 0; + } + } else { + Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); + return 0; + } + + __auto_type set = QFV_AllocImageViews (create.count, malloc); + for (uint32_t i = 0; i < create.count; i++) { + dfunc->vkCreateImageView (device->dev, &create.info[i], 0, &set->a[i]); + + const char *name = PL_KeyAtIndex (item, i); + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); + QFV_AddHandle (ctx->imageViews, name, (uint64_t) set->a[i]); + } + + return set; +} + +VkFramebuffer +QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkFramebufferCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkFramebufferCreateInfo, &cInfo, + properties)) { + return 0; + } + + VkFramebuffer framebuffer; + dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); + + return framebuffer; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index c443e98e3..f8aea8a7f 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -4,6 +4,8 @@ typedef struct parsectx_s { struct exprctx_s *ectx; struct vulkan_ctx_s *vctx; + struct plitem_s *properties; + void *data; } parsectx_t; #include "QF/cexpr.h" @@ -32,12 +34,29 @@ exprenum_t *QFV_GetEnum (const char *name); uint64_t QFV_GetHandle (struct hashtab_s *tab, const char *name); void QFV_AddHandle (struct hashtab_s *tab, const char *name, uint64_t handle); -VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); -VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist); -VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist); +VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, - plitem_t *plist); -VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist); -VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist); + plitem_t *plist, + plitem_t *properties); +VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkImage QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkImageView QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +struct qfv_imageset_s *QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +struct qfv_imageviewset_s *QFV_ParseImageViewSet (vulkan_ctx_t *ctx, + plitem_t *plist, + plitem_t *properties); +VkFramebuffer QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index c3a0bfdd9..ced50835a 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -20,6 +20,9 @@ VkGraphicsPipelineCreateInfo, VkDescriptorPoolCreateInfo, VkSamplerCreateInfo, + VkImageCreateInfo, + VkImageViewCreateInfo, + VkFramebufferCreateInfo, ); parse = { VkSubpassDescription = { @@ -282,6 +285,48 @@ fields = (basePipelineHandle); }; basePipelineIndex = auto; + }; + VkImageCreateInfo = { + flags = auto; + imageType = auto; + format = auto; + extent = auto; + mipLevels = auto; + arrayLayers = auto; + samples = auto; + tiling = auto; + usage = auto; + sharingMode = skip; // FIXME for now + queueFamilyIndexCount = skip; // FIXME for now + pQueueFamilyIndices = skip; // FIXME for now + initialLayout = auto; + }; + VkImageViewCreateInfo = { + flags = auto; + image = { + type = (custom, (QFDictionary, QFString), + parse_VkImage); + fields = (image); + }; + viewType = auto; + format = auto; + components = auto; + subresourceRange = auto; + }; + VkFramebufferCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + renderPass = { + type = (custom, QFString, parse_VkShaderModule); + fields = (renderPass); + }; + attachments = { + type = (array, VkImageView); + size = attachmentCount; + values = pAttachments; + }; + width = auto; + height = auto; + layers = auto; } } } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 67598dc96..973e5445b 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -64,16 +64,65 @@ #include "r_internal.h" #include "vid_vulkan.h" -void -Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) +static const char *alias_pass_names[] = { + "depth", + "g-buffer", + "translucent", +}; + +static void +emit_commands (VkCommandBuffer cmd, int pose1, int pose2, + qfv_alias_skin_t *skin, + void *vert_constants, int vert_size, + void *frag_constants, int frag_size, + aliashdr_t *hdr, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + + __auto_type mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); + + VkDeviceSize offsets[] = { + pose1 * hdr->poseverts * sizeof (aliasvrt_t), + pose2 * hdr->poseverts * sizeof (aliasvrt_t), + 0, + }; + VkBuffer buffers[] = { + mesh->vertex_buffer, + mesh->vertex_buffer, + mesh->uv_buffer, + }; + int bindingCount = skin ? 3 : 2; + + dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, + VK_INDEX_TYPE_UINT32); + dfunc->vkCmdPushConstants (cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, vert_size, vert_constants); + if (skin) { + dfunc->vkCmdPushConstants (cmd, actx->layout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 68, frag_size, frag_constants); + aframe->imageInfo[0].imageView = skin->view; + dfunc->vkCmdPushDescriptorSetKHR (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, + 0, ALIAS_IMAGE_INFOS, + aframe->descriptors + + ALIAS_BUFFER_INFOS); + } + dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); +} + +void +Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) +{ + aliasctx_t *actx = ctx->alias_context; + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; model_t *model = ent->model; aliashdr_t *hdr; - qfv_alias_mesh_t *mesh; qfv_alias_skin_t *skin; float vertex_constants[17]; byte fragment_constants[3][4]; @@ -81,7 +130,6 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) if (!(hdr = model->aliashdr)) { hdr = Cache_Get (&model->cache); } - mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); memcpy (vertex_constants, ent->transform, sizeof (ent->transform)); vertex_constants[16] = R_AliasGetLerpedFrames (ent, hdr); @@ -97,90 +145,26 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) QuatCopy (skin->colora, fragment_constants[1]); QuatCopy (skin->colorb, fragment_constants[2]); - VkDeviceSize offsets[] = { - ent->pose1 * hdr->poseverts * sizeof (aliasvrt_t), - ent->pose2 * hdr->poseverts * sizeof (aliasvrt_t), - 0, - }; - VkBuffer buffers[] = { - mesh->vertex_buffer, - mesh->vertex_buffer, - mesh->uv_buffer, - }; - dfunc->vkCmdBindVertexBuffers (aframe->cmd, 0, 3, buffers, offsets); - dfunc->vkCmdBindIndexBuffer (aframe->cmd, mesh->index_buffer, 0, - VK_INDEX_TYPE_UINT32); - dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, sizeof (vertex_constants), vertex_constants); - dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, - VK_SHADER_STAGE_FRAGMENT_BIT, - 68, sizeof (fragment_constants), - fragment_constants); - aframe->imageInfo[0].imageView = skin->view; - dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, - 0, ALIAS_IMAGE_INFOS, - aframe->descriptors - + ALIAS_BUFFER_INFOS); - dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); + emit_commands (aframe->cmdSet.a[QFV_aliasDepth], ent->pose1, ent->pose2, + 0, vertex_constants, sizeof (vertex_constants), + fragment_constants, sizeof (fragment_constants), + hdr, ctx); } static void -calc_lighting (qfv_light_t *light, entity_t *ent) -{ - vec3_t ambient_color; - //FIXME should be ent->position - float l = R_LightPoint (&r_worldentity.model->brush, r_origin) / 128.0; - - //XXX l = max (light, max (ent->model->min_light, ent->min_light)); - light->type = 2; - VectorSet (1, 1, 1, ambient_color); //FIXME - // position doubles as ambient light - VectorScale (ambient_color, l, light->position); - VectorSet (-1, 0, 0, light->direction); //FIXME - VectorCopy (light->position, light->color); -} - -void -Vulkan_AliasBegin (vulkan_ctx_t *ctx) +alias_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, + vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - - dlight_t *lights[ALIAS_LIGHTS]; - //XXX quat_t fog; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = aframe->cmd; - DARRAY_APPEND (cframe->subCommand, cmd); - - //FIXME ambient needs to be per entity - aframe->lights->light_count = 1; - calc_lighting (&aframe->lights->lights[0], 0); - R_FindNearLights (r_origin, ALIAS_LIGHTS - 1, lights); - for (int i = 0; i < ALIAS_LIGHTS - 1; i++) { - if (!lights[i]) { - break; - } - aframe->lights->light_count++; - VectorCopy (lights[i]->color, aframe->lights->lights[i + 1].color); - VectorCopy (lights[i]->origin, aframe->lights->lights[i + 1].position); - aframe->lights->lights[i + 1].dist = lights[i]->radius; - aframe->lights->lights[i + 1].type = 0; - } - - //FIXME need per frame matrices - aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - aframe->bufferInfo[1].buffer = aframe->light_buffer; dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, + ctx->renderpass, 0, cframe->framebuffer, 0, 0, 0, }; @@ -192,7 +176,7 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->pipeline); + pipeline); //VkDescriptorSet sets[] = { // aframe->descriptors[0].dstSet, // aframe->descriptors[1].dstSet, @@ -213,15 +197,43 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; } -void -Vulkan_AliasEnd (vulkan_ctx_t *ctx) +static void +alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - aliasctx_t *actx = ctx->alias_context; + dfunc->vkEndCommandBuffer (cmd); +} + +void +Vulkan_AliasBegin (vulkan_ctx_t *ctx) +{ + aliasctx_t *actx = ctx->alias_context; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - dfunc->vkEndCommandBuffer (aframe->cmd); + + //XXX quat_t fog; + DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth], + aframe->cmdSet.a[QFV_aliasDepth]); + DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer], + aframe->cmdSet.a[QFV_aliasGBuffer]); + + //FIXME need per frame matrices + aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + + alias_begin_subpass (aframe->cmdSet.a[QFV_aliasDepth], actx->depth, ctx); + alias_begin_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], actx->gbuf, ctx); +} + +void +Vulkan_AliasEnd (vulkan_ctx_t *ctx) +{ + aliasctx_t *actx = ctx->alias_context; + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + + alias_end_subpass (aframe->cmdSet.a[QFV_aliasDepth], ctx); + alias_end_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], ctx); } static VkDescriptorBufferInfo base_buffer_info = { @@ -247,7 +259,6 @@ void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; @@ -257,7 +268,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&actx->frames, frames); actx->frames.grow = 0; - actx->pipeline = Vulkan_CreatePipeline (ctx, "alias"); + actx->depth = Vulkan_CreatePipeline (ctx, "alias_depth"); + actx->gbuf = Vulkan_CreatePipeline (ctx, "alias_gbuf"); actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); @@ -276,43 +288,22 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) }*/ //__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); - __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); - - __auto_type lbuffers = QFV_AllocBufferSet (frames, alloca); - for (size_t i = 0; i < frames; i++) { - lbuffers->a[i] = QFV_CreateBuffer (device, sizeof (qfv_light_buffer_t), - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, - lbuffers->a[i], - va (ctx->va_ctx, "buffer:alias:%s:%zd", - "lights", i)); - } - VkMemoryRequirements requirements; - dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0], - &requirements); - actx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - frames * requirements.size, 0); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - actx->light_memory, va (ctx->va_ctx, - "memory:alias:%s", "lights")); - byte *light_data; - dfunc->vkMapMemory (device->dev, actx->light_memory, 0, - frames * requirements.size, 0, (void **) &light_data); - //__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; - aframe->cmd = cmdBuffers->a[i]; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - aframe->cmd, - va (ctx->va_ctx, "cmd:alias:%zd", i)); - aframe->light_buffer = lbuffers->a[i]; - aframe->lights = (qfv_light_buffer_t *) (light_data + i * requirements.size); - QFV_BindBufferMemory (device, lbuffers->a[i], actx->light_memory, - i * requirements.size); + DARRAY_INIT (&aframe->cmdSet, QFV_aliasNumPasses); + DARRAY_RESIZE (&aframe->cmdSet, QFV_aliasNumPasses); + aframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet); + + for (int j = 0; j < QFV_aliasNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + aframe->cmdSet.a[j], + va (ctx->va_ctx, "cmd:alias:%zd:%s", i, + alias_pass_names[j])); + } for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { aframe->bufferInfo[j] = base_buffer_info; aframe->descriptors[j] = base_buffer_write; @@ -333,7 +324,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) } void -Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx) +Vulkan_Alias_Shutdown (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -341,11 +332,11 @@ Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx) for (size_t i = 0; i < actx->frames.size; i++) { __auto_type aframe = &actx->frames.a[i]; - dfunc->vkDestroyBuffer (device->dev, aframe->light_buffer, 0); + free (aframe->cmdSet.a); } - dfunc->vkFreeMemory (device->dev, actx->light_memory, 0); - dfunc->vkDestroyPipeline (device->dev, actx->pipeline, 0); - DARRAY_CLEAR (&actx->frames); + dfunc->vkDestroyPipeline (device->dev, actx->depth, 0); + dfunc->vkDestroyPipeline (device->dev, actx->gbuf, 0); + free (actx->frames.a); free (actx); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 7028aa754..895caed49 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -69,6 +69,12 @@ #include "r_internal.h" #include "vid_vulkan.h" +static const char *bsp_pass_names[] = { + "depth", + "g-buffer", + "translucent", +}; + static float identity[] = { 1, 0, 0, 0, 0, 1, 0, 0, @@ -779,33 +785,44 @@ bind_view (qfv_bsp_tex tex, VkImageView view, bspframe_t *bframe, + BSP_BUFFER_INFOS); } +static void +push_transform (vec_t *transform, VkPipelineLayout layout, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +{ + dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, 16 * sizeof (float), transform); +} + +static void +push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +{ + dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof (fragconst_t), fragconst); +} + +static void +push_descriptors (int count, VkWriteDescriptorSet *descriptors, + VkPipelineLayout layout, qfv_devfuncs_t *dfunc, + VkCommandBuffer cmd) +{ + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, count, descriptors); +} + static void draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) { elements_t *el; - /*if (colloc >= 0) { - float *color; - color = ec->color; - if (!color) - color = bctx->default_color; - if (!QuatCompare (color, bctx->last_color)) { - QuatCopy (color, bctx->last_color); - qfeglVertexAttrib4fv (quake_bsp.color.location, color); - } - }*/ if (ec->transform) { - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), ec->transform); + push_transform (ec->transform, layout, dfunc, cmd); } else { //FIXME should cache current transform - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), identity); + push_transform (identity, layout, dfunc, cmd); } for (el = ec->elements; el; el = el->next) { - //FIXME check if these are contiguous and if so merge into one - //command if (!el->index_count) continue; dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index, @@ -828,35 +845,18 @@ get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) } static void -bsp_begin (vulkan_ctx_t *ctx) +bsp_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - //XXX quat_t fog; - - bctx->default_color[3] = 1; - QuatCopy (bctx->default_color, bctx->last_color); - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = bframe->bsp_cmd; - DARRAY_APPEND (cframe->subCommand, cmd); - - //FIXME need per frame matrices - bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - bframe->imageInfo[0].imageView = 0; // set by tex chain loop - bframe->imageInfo[1].imageView = 0; // set by tex chain loop - bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); - bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, - bctx->default_skysheet); - bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, - bctx->default_skybox); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, + ctx->renderpass, 0, cframe->framebuffer, 0, 0, 0, }; @@ -868,7 +868,7 @@ bsp_begin (vulkan_ctx_t *ctx) dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->main); + pipeline); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); @@ -893,14 +893,54 @@ bsp_begin (vulkan_ctx_t *ctx) } static void -bsp_end (vulkan_ctx_t *ctx) +bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; + dfunc->vkEndCommandBuffer (cmd); +} + +static void +bsp_begin (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + //XXX quat_t fog; + + bctx->default_color[3] = 1; + QuatCopy (bctx->default_color, bctx->last_color); + + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - dfunc->vkEndCommandBuffer (bframe->bsp_cmd); + + DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth], + bframe->cmdSet.a[QFV_bspDepth]); + DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer], + bframe->cmdSet.a[QFV_bspGBuffer]); + + //FIXME need per frame matrices + bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + bframe->imageInfo[0].imageView = 0; // set by tex chain loop + bframe->imageInfo[1].imageView = 0; // set by tex chain loop + bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); + bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, + bctx->default_skysheet); + bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, + bctx->default_skybox); + + //FIXME pipeline + bsp_begin_subpass (bframe->cmdSet.a[QFV_bspDepth], bctx->main, ctx); + bsp_begin_subpass (bframe->cmdSet.a[QFV_bspGBuffer], bctx->main, ctx); +} + +static void +bsp_end (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + + bsp_end_subpass (bframe->cmdSet.a[QFV_bspDepth], ctx); + bsp_end_subpass (bframe->cmdSet.a[QFV_bspGBuffer], ctx); } /*static void @@ -982,8 +1022,6 @@ spin (mat4_t mat, bspctx_t *bctx) static void sky_begin (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bctx->default_color[3] = 1; @@ -993,8 +1031,10 @@ sky_begin (vulkan_ctx_t *ctx) __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = bframe->sky_cmd; - DARRAY_APPEND (cframe->subCommand, cmd); + + //FIXME where should skys go? g-buffer is overkill. Translucent pre-pass? + DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], + bframe->cmdSet.a[QFV_bspTranslucent]); //FIXME need per frame matrices bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; @@ -1006,54 +1046,18 @@ sky_begin (vulkan_ctx_t *ctx) bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, bctx->default_skybox); - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, - 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, - bctx->sky); - 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 offsets[] = { 0 }; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, - VK_INDEX_TYPE_UINT32); - - // push VP matrices - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 1, bframe->descriptors + 0); - // push static images - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 5, bframe->descriptors + 1); - - //XXX glsl_Fog_GetColor (fog); - //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; + //FIXME sky pass + bsp_begin_subpass (bframe->cmdSet.a[QFV_bspTranslucent], bctx->sky, ctx); } static void sky_end (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - dfunc->vkEndCommandBuffer (bframe->sky_cmd); + + //FIXME sky pass + bsp_end_subpass (bframe->cmdSet.a[QFV_bspTranslucent], ctx); } static inline void @@ -1133,13 +1137,13 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) Vulkan_FlushLightmaps (ctx); bsp_begin (ctx); - dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), identity); + push_transform (identity, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspDepth]); + push_transform (identity, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); fragconst_t frag_constants = { time: vr_data.realtime }; - dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, - VK_SHADER_STAGE_FRAGMENT_BIT, - 64, sizeof (fragconst_t), &frag_constants); + push_fragconst (&frag_constants, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; @@ -1153,13 +1157,15 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) ctx->default_white); bframe->imageInfo[1].imageView = get_view (tex->glow, ctx->default_black); - dfunc->vkCmdPushDescriptorSetKHR (bframe->bsp_cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 2, bframe->descriptors + 1); + + push_descriptors (2, bframe->descriptors + 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, bframe->bsp_cmd); + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspDepth]); + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1246,22 +1252,24 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) return; sky_begin (ctx); - dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), identity); + //FIXME sky pass + push_transform (identity, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTranslucent]); fragconst_t frag_constants = { time: vr_data.realtime }; - dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, - VK_SHADER_STAGE_FRAGMENT_BIT, - 64, sizeof (fragconst_t), &frag_constants); + push_fragconst (&frag_constants, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTranslucent]); for (is = bctx->sky_chain; is; is = is->tex_chain) { surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black), - bframe, bframe->sky_cmd, bctx->layout, dfunc); + bframe, + bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bctx->layout, dfunc); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); + draw_elechain (ec, bctx->layout, dfunc,//FIXME + bframe->cmdSet.a[QFV_bspTranslucent]); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1271,11 +1279,12 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - bind_view (qfv_bsp_skysheet, - get_view (tex->tex, ctx->default_black), - bframe, bframe->sky_cmd, bctx->layout, dfunc); + bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black), + bframe, bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bctx->layout, dfunc); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); + draw_elechain (ec, bctx->layout, dfunc,//FIXME + bframe->cmdSet.a[QFV_bspTranslucent]); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1453,23 +1462,21 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); - __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); - for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; - bframe->bsp_cmd = cmdBuffers->a[i * 3 + 0]; - bframe->turb_cmd = cmdBuffers->a[i * 3 + 1]; - bframe->sky_cmd = cmdBuffers->a[i * 3 + 2]; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - bframe->bsp_cmd, - va (ctx->va_ctx, "cmd:bsp:%zd", i)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - bframe->turb_cmd, - va (ctx->va_ctx, "cmd:turb:%zd", i)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - bframe->sky_cmd, - va (ctx->va_ctx, "cmd:sky:%zd", i)); + + DARRAY_INIT (&bframe->cmdSet, QFV_bspNumPasses); + DARRAY_RESIZE (&bframe->cmdSet, QFV_bspNumPasses); + bframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &bframe->cmdSet); + + for (int j = 0; j < QFV_bspNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + bframe->cmdSet.a[i], + va (ctx->va_ctx, "cmd:bsp:%zd:%s", i, + bsp_pass_names[j])); + } for (int j = 0; j < BSP_BUFFER_INFOS; j++) { bframe->bufferInfo[j] = base_buffer_info; @@ -1495,6 +1502,11 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; + for (size_t i = 0; i < bctx->frames.size; i++) { + __auto_type bframe = &bctx->frames.a[i]; + free (bframe->cmdSet.a); + } + dfunc->vkDestroyPipeline (device->dev, bctx->main, 0); dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0); DARRAY_CLEAR (&bctx->texture_chains); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 93b73d7b3..43b246273 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -696,7 +696,8 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = dframe->cmd; - DARRAY_APPEND (cframe->subCommand, cmd); + //FIXME which pass? + DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], cmd); VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, @@ -708,7 +709,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, + ctx->renderpass, 0, cframe->framebuffer, 0, 0, 0 }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 0132bf6d0..a6f444798 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -78,6 +78,10 @@ static const char quakeforge_pipeline[] = #include "libs/video/renderer/vulkan/qfpipeline.plc" ; +static const char quakeforge_renderpass[] = +#include "libs/video/renderer/vulkan/deferred.plc" +; + cvar_t *vulkan_frame_count; cvar_t *vulkan_presentation_mode; cvar_t *msaaSamples; @@ -163,6 +167,7 @@ void Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_Printf ("Vulkan_Init_Common\n"); + QFV_InitParse (ctx); Vulkan_Init_Cvars (); ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version @@ -185,9 +190,9 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) QFV_DestroyPipeline (ctx->device, ctx->pipeline); } if (ctx->frames.size) { - Vulkan_DestroyFramebuffers (ctx); + Vulkan_DestroyFrames (ctx); } - if (ctx->renderpass.colorImage) { + if (ctx->renderpass) { Vulkan_DestroyRenderPass (ctx); } if (ctx->swapchain) { @@ -216,6 +221,15 @@ void Vulkan_CreateDevice (vulkan_ctx_t *ctx) { ctx->device = QFV_CreateDevice (ctx, device_extensions); + + //FIXME msaa and deferred rendering... + //also, location + ctx->msaaSamples = 1; + /*ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, + QFV_GetMaxSampleCount (device->physDev)); + if (ctx->msaaSamples > 1) { + name = "renderpass_msaa"; + }*/ } void @@ -257,138 +271,54 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) return item; } +static plitem_t * +qfv_load_renderpass (vulkan_ctx_t *ctx, const char *name) +{ + if (!ctx->renderpassDef) { + ctx->renderpassDef = PL_GetPropertyList (quakeforge_renderpass, + &ctx->hashlinks); + } + + plitem_t *item = ctx->renderpassDef; + if (!item || !(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading %s\n", name); + } else { + Sys_Printf ("Found %s def\n", name); + } + return item; +} + +static size_t +get_image_size (VkImage image, qfv_device_t *device) +{ + qfv_devfuncs_t *dfunc = device->funcs; + size_t size; + size_t align; + + VkMemoryRequirements requirements; + dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); + size = requirements.size; + align = requirements.alignment - 1; + size = (size + align) & ~(align); + return size; +} + void Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { const char *name = "renderpass";//FIXME - qfv_device_t *device = ctx->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *df = device->funcs; - VkCommandBuffer cmd = ctx->cmdbuffer; - qfv_swapchain_t *sc = ctx->swapchain; - ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, - QFV_GetMaxSampleCount (device->physDev)); - if (ctx->msaaSamples > 1) { - name = "renderpass_msaa"; - } + plitem_t *item = qfv_load_renderpass (ctx, name); - //FIXME a tad inconsistent - plitem_t *item = qfv_load_pipeline (ctx, name); - if (!item) { - return; - } - - qfv_imageresource_t *colorImage = malloc (sizeof (*colorImage)); - qfv_imageresource_t *depthImage = malloc (sizeof (*depthImage)); - - VkExtent3D extent = {sc->extent.width, sc->extent.height, 1}; - - Sys_MaskPrintf (SYS_VULKAN, "color resource\n"); - colorImage->image - = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - sc->format, extent, 1, 1, ctx->msaaSamples, - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT - | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - colorImage->object - = QFV_AllocImageMemory (device, colorImage->image, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); - QFV_BindImageMemory (device, colorImage->image, colorImage->object, 0); - colorImage->view - = QFV_CreateImageView (device, colorImage->image, - VK_IMAGE_VIEW_TYPE_2D, - sc->format, VK_IMAGE_ASPECT_COLOR_BIT); - Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n", - colorImage->image, colorImage->object, colorImage->view); - - Sys_MaskPrintf (SYS_VULKAN, "depth resource\n"); - VkFormat depthFormat = VK_FORMAT_D32_SFLOAT; - depthImage->image - = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - depthFormat, extent, 1, 1, ctx->msaaSamples, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - depthImage->object - = QFV_AllocImageMemory (device, depthImage->image, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); - QFV_BindImageMemory (device, depthImage->image, depthImage->object, 0); - depthImage->view - = QFV_CreateImageView (device, depthImage->image, - VK_IMAGE_VIEW_TYPE_2D, - depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); - Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n", - depthImage->image, depthImage->object, depthImage->view); - - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - - df->vkWaitForFences (dev, 1, &ctx->fence, VK_TRUE, ~0ull); - df->vkResetCommandBuffer (cmd, 0); - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, - }; - df->vkBeginCommandBuffer (cmd, &beginInfo); - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_Color]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_Color]; - barrier.image = colorImage->image; - - df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, - 0, 0, - 0, 0, - 1, &barrier); - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_DepthStencil]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_DepthStencil]; - barrier.image = depthImage->image; - if (depthFormat == VK_FORMAT_D32_SFLOAT_S8_UINT - || depthFormat == VK_FORMAT_D24_UNORM_S8_UINT) { - barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - - df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, - 0, 0, - 0, 0, - 1, &barrier); - df->vkEndCommandBuffer (cmd); - - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 0, 0, 0, - 1, &cmd, - 0, 0 - }; - df->vkResetFences (dev, 1, &ctx->fence); - df->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); - - ctx->renderpass.colorImage = colorImage; - ctx->renderpass.depthImage = depthImage; - ctx->renderpass.renderpass = QFV_ParseRenderPass (ctx, item); + ctx->renderpass = QFV_ParseRenderPass (ctx, item, ctx->renderpassDef); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - ctx->renderpass.renderpass, - va (ctx->va_ctx, "pipeline:%s", name)); + ctx->renderpass, va (ctx->va_ctx, "renderpass:%s", + name)); } void Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *df = device->funcs; - - df->vkDestroyRenderPass (dev, ctx->renderpass.renderpass, 0); - - df->vkDestroyImageView (dev, ctx->renderpass.colorImage->view, 0); - df->vkDestroyImage (dev, ctx->renderpass.colorImage->image, 0); - df->vkFreeMemory (dev, ctx->renderpass.colorImage->object, 0); - free (ctx->renderpass.colorImage); - ctx->renderpass.colorImage = 0; - - df->vkDestroyImageView (dev, ctx->renderpass.depthImage->view, 0); - df->vkDestroyImage (dev, ctx->renderpass.depthImage->image, 0); - df->vkFreeMemory (dev, ctx->renderpass.depthImage->object, 0); - free (ctx->renderpass.depthImage); - ctx->renderpass.depthImage = 0; } VkPipeline @@ -401,7 +331,7 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found pipeline def %s\n", name); } - VkPipeline pipeline = QFV_ParsePipeline (ctx, item); + VkPipeline pipeline = QFV_ParsePipeline (ctx, item, ctx->pipelineDef); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, va (ctx->va_ctx, "pipeline:%s", name)); return pipeline; @@ -425,7 +355,7 @@ Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found descriptor pool def %s\n", name); } - pool = QFV_ParseDescriptorPool (ctx, item); + pool = QFV_ParseDescriptorPool (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) pool); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, va (ctx->va_ctx, "descriptor_pool:%s", name)); @@ -450,7 +380,7 @@ Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found pipeline layout def %s\n", name); } - layout = QFV_ParsePipelineLayout (ctx, item); + layout = QFV_ParsePipelineLayout (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) layout); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, va (ctx->va_ctx, "pipeline_layout:%s", name)); @@ -475,7 +405,7 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found sampler def %s\n", name); } - sampler = QFV_ParseSampler (ctx, item); + sampler = QFV_ParseSampler (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) sampler); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, va (ctx->va_ctx, "sampler:%s", name)); @@ -500,7 +430,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found descriptor set def %s\n", name); } - set = QFV_ParseDescriptorSetLayout (ctx, item); + set = QFV_ParseDescriptorSetLayout (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) set); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, set, va (ctx->va_ctx, "descriptor_set:%s", name)); @@ -508,7 +438,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) } void -Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) +Vulkan_CreateFrames (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; VkCommandPool cmdpool = ctx->cmdpool; @@ -531,13 +461,16 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) frame->renderDoneSemaphore = QFV_CreateSemaphore (device); frame->cmdBuffer = cmdBuffers->a[i]; - frame->subCommand = malloc (sizeof (qfv_cmdbufferset_t)); - DARRAY_INIT (frame->subCommand, 4); + frame->cmdSetCount = QFV_NumPasses; + frame->cmdSets = malloc (QFV_NumPasses * sizeof (qfv_cmdbufferset_t)); + for (int j = 0; j < QFV_NumPasses; j++) { + DARRAY_INIT (&frame->cmdSets[j], 4); + } } } void -Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) +Vulkan_DestroyFrames (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *df = device->funcs; @@ -553,3 +486,59 @@ Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) DARRAY_CLEAR (&ctx->frames); } + +void +Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + plitem_t *item = qfv_load_renderpass (ctx, "images"); + if (!item) { + return; + } + + __auto_type images = QFV_ParseImageSet (ctx, item, ctx->renderpassDef); + ctx->attachment_images = images; + size_t memSize = 0; + for (size_t i = 0; i < images->size; i++) { + memSize += get_image_size (images->a[i], device); + } + VkDeviceMemory mem; + mem = QFV_AllocImageMemory (device, images->a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memSize, 0); + ctx->attachmentMemory = mem; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mem, "memory:framebuffers"); + size_t offset = 0; + for (size_t i = 0; i < images->size; i++) { + QFV_BindImageMemory (device, images->a[i], mem, offset); + offset += get_image_size (images->a[i], device); + } + + item = qfv_load_renderpass (ctx, "imageViews"); + if (!item) { + return; + } + + __auto_type views = QFV_ParseImageViewSet (ctx, item, ctx->renderpassDef); + ctx->attachment_views = views; + + item = qfv_load_renderpass (ctx, "framebuffer"); + if (!item) { + return; + } + + ctx->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, + malloc); + for (size_t i = 0; i < ctx->framebuffers->size; i++) { + ctx->swapImageIndex = i; + ctx->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, + ctx->renderpassDef); + } +} + +void +Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) +{ +}