From 8f6f32981c0d9b7034ebfd00585fa2722f2541ac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 11:26:20 +0900 Subject: [PATCH] [vulkan] Add some matrix buffers It seems they could all be in the one buffer: there are indications that uniform binding can be fairly fine-grained. I need to investigate that. --- include/QF/Vulkan/qf_vid.h | 4 + include/vid_vulkan.h | 12 ++ libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 9 +- libs/video/renderer/vulkan/vulkan_matrices.c | 204 ++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 1 + 6 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 libs/video/renderer/vulkan/vulkan_matrices.c diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index d5f59cc84..7e30a3a57 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -41,6 +41,10 @@ void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name); +void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyMatrices (struct vulkan_ctx_s *ctx); +void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx, float aspect); +void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 05e127825..3ffa0052c 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -24,6 +24,15 @@ typedef struct vulkan_framebuffer_s { VkDescriptorSet twodDescriptors; } vulkan_framebuffer_t; +typedef struct vulkan_matrices_s { + VkBuffer buffer_2d; + VkBuffer buffer_3d; + VkDeviceMemory memory; + float *projection_2d; + float *projection_3d; + float *view_3d; +} vulkan_matrices_t; + typedef struct vulkan_framebufferset_s DARRAY_TYPE (vulkan_framebuffer_t) vulkan_framebufferset_t; @@ -62,6 +71,9 @@ typedef struct vulkan_ctx_s { size_t curFrame; vulkan_framebufferset_t framebuffers; + // projection and view matrices (model is push constant) + vulkan_matrices_t matrices; + #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 36b013d97..d6187a93a 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -233,6 +233,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/util.h \ libs/video/renderer/vulkan/vkparse.c \ libs/video/renderer/vulkan/vulkan_draw.c \ + libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_vid_common.c libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vkparse_src) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a61a911a2..77368d093 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -63,6 +63,7 @@ vulkan_R_Init (void) qfv_devfuncs_t *dfunc = device->funcs; Vulkan_CreateStagingBuffers (vulkan_ctx); + Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); @@ -276,6 +277,12 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx); } +static void +vulkan_R_ViewChanged (float aspect) +{ + Vulkan_CalcProjectionMatrices (vulkan_ctx, aspect); +} + static vid_model_funcs_t model_funcs = { 0,//vulkan_Mod_LoadExternalTextures, 0,//vulkan_Mod_LoadLighting, @@ -347,7 +354,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { R_AllocEntity, 0,//vulkan_R_RenderView, R_DecayLights, - 0,//vulkan_R_ViewChanged, + vulkan_R_ViewChanged, 0,//vulkan_R_ClearParticles, 0,//vulkan_R_InitParticles, 0,//vulkan_SCR_ScreenShot_f, diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c new file mode 100644 index 000000000..c734f82d0 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -0,0 +1,204 @@ +/* + vid_common_vulkan.c + + Common Vulkan video driver functions + + Copyright (C) 2021 Bill Currie + + 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_MATH_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/device.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +#define MAT_SIZE (16 * sizeof (float)) + +static void +ortho_mat (float *proj, float xmin, float xmax, float ymin, float ymax, + float znear, float zfar) +{ + proj[0] = 2 / (xmax - xmin); + proj[4] = 0; + proj[8] = 0; + proj[12] = -(xmax + xmin) / (xmax - xmin); + + proj[1] = 0; + proj[5] = 2 / (ymax - ymin); + proj[9] = 0; + proj[13] = -(ymax + ymin) / (ymax - ymin); + + proj[2] = 0; + proj[6] = 0; + proj[10] = -2 / (zfar - znear); + proj[14] = -(zfar + znear) / (zfar - znear); + + proj[3] = 0; + proj[7] = 0; + proj[11] = 0; + proj[15] = 1; +} + +static void +persp_mat (float *proj, float xmin, float xmax, float ymin, float ymax, + float aspect) +{ + float fovx, fovy, neard, fard; + + fovx = r_refdef.fov_x; + fovy = r_refdef.fov_y; + neard = r_nearclip->value; + fard = r_farclip->value; + + ymax = neard * tan (fovy * M_PI / 360); // fov_2 / 2 + ymin = -ymax; + xmax = neard * tan (fovx * M_PI / 360); // fov_2 / 2 + xmin = -xmax; + + proj[0] = (2 * neard) / (xmax - xmin); + proj[4] = 0; + proj[8] = (xmax + xmin) / (xmax - xmin); + proj[12] = 0; + + proj[1] = 0; + proj[5] = (2 * neard) / (ymax - ymin); + proj[9] = (ymax + ymin) / (ymax - ymin); + proj[13] = 0; + + proj[2] = 0; + proj[6] = 0; + proj[10] = (fard + neard) / (neard - fard); + proj[14] = (2 * fard * neard) / (neard - fard); + + proj[3] = 0; + proj[7] = 0; + proj[11] = -1; + proj[15] = 0; +} + +void +Vulkan_DestroyMatrices (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + __auto_type mat = &ctx->matrices; + + dfunc->vkUnmapMemory (device->dev, mat->memory); + dfunc->vkFreeMemory (device->dev, mat->memory, 0); + dfunc->vkDestroyBuffer (device->dev, mat->buffer_2d, 0); + dfunc->vkDestroyBuffer (device->dev, mat->buffer_3d, 0); +} + +void +Vulkan_CreateMatrices (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + __auto_type mat = &ctx->matrices; + mat->buffer_2d = QFV_CreateBuffer (device, 1 * MAT_SIZE, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + mat->buffer_3d = QFV_CreateBuffer (device, 2 * MAT_SIZE, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + size_t size = 0; + size_t offset; + VkMemoryRequirements req; + + dfunc->vkGetBufferMemoryRequirements (device->dev, mat->buffer_2d, &req); + size += req.size; + offset = size; + + dfunc->vkGetBufferMemoryRequirements (device->dev, mat->buffer_3d, &req); + offset = (offset + req.alignment - 1) & ~(req.alignment - 1); + size += req.size; + + mat->memory = QFV_AllocBufferMemory (device, mat->buffer_2d, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + size, 0); + QFV_BindBufferMemory (device, mat->buffer_2d, mat->memory, 0); + QFV_BindBufferMemory (device, mat->buffer_3d, mat->memory, offset); + void *data; + dfunc->vkMapMemory (device->dev, mat->memory, 0, size, 0, &data); + mat->projection_2d = data; + mat->projection_3d = mat->projection_2d + offset / sizeof (float); + mat->view_3d = mat->projection_3d + 16; +} + +void +Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx, float aspect) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + __auto_type mat = &ctx->matrices; + + int width = vid.conwidth; + int height = vid.conheight; + + ortho_mat (mat->projection_2d, 0, width, 0, height, -99999, 99999); + persp_mat (mat->projection_3d, 0, width, 0, height, aspect); + + Sys_MaskPrintf (SYS_VULKAN, "ortho:\n"); + Sys_MaskPrintf (SYS_VULKAN, " [[%g, %g, %g, %g],\n", + QuatExpand (mat->projection_2d + 0)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_2d + 4)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_2d + 8)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g]]\n", + QuatExpand (mat->projection_2d + 12)); + Sys_MaskPrintf (SYS_VULKAN, "presp:\n"); + Sys_MaskPrintf (SYS_VULKAN, " [[%g, %g, %g, %g],\n", + QuatExpand (mat->projection_3d + 0)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_3d + 4)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_3d + 8)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g]]\n", + QuatExpand (mat->projection_3d + 12)); + + VkMappedMemoryRange ranges[] = { + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, 0, MAT_SIZE }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, + (mat->projection_3d - mat->projection_2d) * sizeof (float), + MAT_SIZE}, + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index e35d5765c..c166c239b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -175,6 +175,7 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) } QFV_DestroyStagingBuffer (ctx->staging[0]); QFV_DestroyStagingBuffer (ctx->staging[1]); + Vulkan_DestroyMatrices (ctx); ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); clear_table (&ctx->pipelineLayouts);