From ba6450d0b4630abca73d6b0a9dd46140495aad92 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:52:27 +0900 Subject: [PATCH] [vulkan] Make a start on the 2D pipeline Short wrappers for Draw functins are in vid_render_vulkan.c so the vulkan context can be passed on to the actual functions. The 2D shaders are set up similar to those in glsl, but with full 32-bit color (rgba) support instead of paletted. However, the textures are not loaded yet, nor is anything bound. --- include/QF/Vulkan/draw.h | 237 ++++++++++++++++++ include/QF/Vulkan/qf_draw.h | 52 +++- include/QF/Vulkan/qf_vid.h | 2 +- include/vid_vulkan.h | 3 + libs/video/renderer/Makemodule.am | 12 +- libs/video/renderer/vid_render_vulkan.c | 154 ++++++++++-- libs/video/renderer/vulkan/device.c | 3 +- libs/video/renderer/vulkan/qfpipeline.plist | 224 +++++++++++------ libs/video/renderer/vulkan/shader.c | 6 + libs/video/renderer/vulkan/twod.frag | 19 ++ libs/video/renderer/vulkan/twod.vert | 27 ++ libs/video/renderer/vulkan/vulkan_draw.c | 142 ++++++++--- .../video/renderer/vulkan/vulkan_vid_common.c | 19 +- 13 files changed, 742 insertions(+), 158 deletions(-) create mode 100644 include/QF/Vulkan/draw.h create mode 100644 libs/video/renderer/vulkan/twod.frag create mode 100644 libs/video/renderer/vulkan/twod.vert diff --git a/include/QF/Vulkan/draw.h b/include/QF/Vulkan/draw.h new file mode 100644 index 000000000..8f6b78889 --- /dev/null +++ b/include/QF/Vulkan/draw.h @@ -0,0 +1,237 @@ +/* + draw.h + + Video buffer handling definitions and prototypes + + Copyright (C) 1996-1997 Id Software, Inc. + + 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_draw_h +#define __QF_draw_h + +/** \defgroup video Video Sub-sytem */ + +/** \defgroup video_renderer Renderer Sub-system + \ingroup video +*/ + +/** \defgroup video_renderer_draw Generic draw functions + \ingroup video_renderer +*/ +///@{ + +#include "QF/wad.h" + +extern byte *draw_chars; + +/** Initialize the draw stuff. +*/ +void Draw_Init (void); + +/** Draws one 8*8 graphics character with 0 being transparent. + It can be clipped to the top of the screen to allow the console to be + smoothly scrolled off. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param ch 8 bit character to draw. + \note The character drawn is from the quake character set, which is + (by default) standard ascii for 0x20-0x7e (white). 0xa0-0xfe is + also standard ascii (brown). 0x01-0x1f and 0x80-0x9f are + various drawing characters, and 0x7f is a backwards arrow. +*/ +void Draw_Character (int x, int y, unsigned ch); + +/** Draws a character string to the screen. + No line wrapping is performed. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param str 8 bit character string to draw. + \note See Draw_Character() for character set description. + String is normal nul terminated C string. +*/ +void Draw_String (int x, int y, const char *str); + +/** Draws a character sub-string to the screen. + No line wrapping is performed. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param str 8 bit character string to draw. + \param count Maximum characters of the string to draw. + \note See Draw_Character() for character set description. + Draws up to \p count characters, or stops at the first nul + character. +*/ +void Draw_nString (int x, int y, const char *str, int count); + +/** Draws a character string to the screen. + No line wrapping is performed. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param str 8 bit character string to draw. + \note See Draw_Character() for character set description. + String is normal nul terminated C string. + Characters of the string are forced to have their high bit set + (ie, they will be in the range 0x80-0xff). +*/ +void Draw_AltString (int x, int y, const char *str); + +/** Draw the console background with various optional effects. + \param lines Vertical size in pixels of the console. + \param alpha Console transparency level (255 = opaque). + \note \p alpha is effective only in the OpenGL renderer. Effectively + 255 (opaque) for the software renderer. + + \c gl_conspin causes the background to spin. + + \c gl_constretch causes the background to stretch rather than slide. +*/ +void Draw_ConsoleBackground (int lines, byte alpha); + +/** Draw a crosshair at the center of the screen. + \c crosshair specifies which crosshair (1 = '+', 2 = large 'x' shape, + 3 = fancy '+' shape) + \c cl_crossx and \c cl_crossy offset the crosshair from the center of the + screen. +*/ +void Draw_Crosshair (void); + +/** Draw the specified crosshair on the screen. + \param ch crosshair to draw + \param x horizontal position of the center of the crosshair. + \param y vertical position of the center of the crosshair. + + See Draw_Crosshair() for description of crosshair values. +*/ +void Draw_CrosshairAt (int ch, int x, int y); + +/** Clear a rectangle with a tiled background. + \param x horizontal position of the upper left corner of the rectangle + \param y horizontal position of the upper left corner of the rectangle + \param w width of the rectangle + \param h height of the rectangle + + The background used is the "backtile" WAD lump. +*/ +void Draw_TileClear (int x, int y, int w, int h); + +/** Clear a rectangle with a solid color. + \param x horizontal position of the upper left corner of the rectangle + \param y horizontal position of the upper left corner of the rectangle + \param w width of the rectangle + \param h height of the rectangle + \param c 8 bit color index. + + The color comes from the quake palette. +*/ +void Draw_Fill (int x, int y, int w, int h, int c); + +/** Draw a text box on the screen + \param x horizontal location of the upper left corner of the box + \param y vertical location of the upper left corner of the box + \param width horizontal size in character cells of the region + \param lines vertical size in character cells of the region + \param alpha transparency of the box +*/ +void Draw_TextBox (int x, int y, int width, int lines, byte alpha); + +/** Darken the screen. +*/ +void Draw_FadeScreen (void); + +/** Shift the screen colors. +*/ +void Draw_BlendScreen (quat_t color); +///@} + +/** \defgroup video_renderer_draw_qpic QPic functions + \ingroup video_renderer_draw +*/ +///@{ +/** Load a qpic from the filesystem. + \param path path of the file within the quake filesystem + \param alpha transparency level of the pic. + \return pointer qpic data. + \note Up to MAX_CACHED_PICS qpics can be loaded at a time this way +*/ +qpic_t *Draw_CachePic (const char *path, qboolean alpha); + +/** Remove a qpic from the qpic cache. + + This affects only those qpics that were loaded via Draw_CachePic. + + \param path path of the file within the quake filesystem +*/ +void Draw_UncachePic (const char *path); + +/** Create a qpic from raw data. + + \param width The width of the pic. + \param height The height of the pic. + \param data The raw data bytes. The system palette will be used for + colors. + \return pointer qpic data. +*/ +qpic_t *Draw_MakePic (int width, int height, const byte *data); + +/** Destroy a qpic created by Draw_MakePic. + + \param pic The qpic to destory. +*/ +void Draw_DestroyPic (qpic_t *pic); + +/** Load a qpic from gfx.wad. + \param name name of the was lump to load + \return pointer qpic data. +*/ +qpic_t *Draw_PicFromWad (const char *name); + +/** Draw a qpic to the screen + \param x horizontal location of the upper left corner of the qpic + \param y vertical location of the upper left corner of the qpic + \param pic qpic to draw +*/ +void Draw_Pic (int x, int y, qpic_t *pic); + +/** Draw a qpic to the screen + \param x horizontal location of the upper left corner of the qpic + \param y vertical location of the upper left corner of the qpic + \param pic qpic to draw +*/ +void Draw_Picf (float x, float y, qpic_t *pic); + +/** Draw a sub-region of a qpic to the screan + \param x horizontal screen location of the upper left corner of the + sub-region + \param y vertical screen location of the upper left corner of the + sub-region + \param pic qpic to draw + \param srcx horizontal qpic location of the upper left corner of the + sub-region + \param srcy vertical qpic location of the upper left corner of the + sub-region + \param width horizontal size of the sub-region to be drawn + \param height vertical size of the sub-region to be drawn +*/ +void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); +///@} + +#endif//__QF_draw_h diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index e4716f7ed..b0297c2d0 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -25,13 +25,49 @@ */ -#ifndef __gl_draw_h -#define __gl_draw_h +#ifndef __QF_Vulkan_qf_draw_h +#define __QF_Vulkan_qf_draw_h -void Vulkan_Set2D (void); -void Vulkan_Set2DScaled (void); -void Vulkan_End2D (void); -void Vulkan_DrawReset (void); -void Vulkan_FlushText (void); +struct vulkan_ctx_s; -#endif//__gl_draw_h +void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Character (int x, int y, unsigned ch, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_String (int x, int y, const char *str, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_nString (int x, int y, const char *str, int count, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_AltString (int x, int y, const char *str, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_ConsoleBackground (int lines, byte alpha, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Crosshair (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_CrosshairAt (int ch, int x, int y, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_TileClear (int x, int y, int w, int h, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_FadeScreen (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_BlendScreen (quat_t color, struct vulkan_ctx_s *ctx); +qpic_t *Vulkan_Draw_CachePic (const char *path, qboolean alpha, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_UncachePic (const char *path, struct vulkan_ctx_s *ctx); +qpic_t *Vulkan_Draw_MakePic (int width, int height, const byte *data, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_DestroyPic (qpic_t *pic, struct vulkan_ctx_s *ctx); +qpic_t *Vulkan_Draw_PicFromWad (const char *name, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Pic (int x, int y, qpic_t *pic, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Picf (float x, float y, qpic_t *pic, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_SubPic(int x, int y, qpic_t *pic, + int srcx, int srcy, int width, int height, + struct vulkan_ctx_s *ctx); + +void Vulkan_Set2D (struct vulkan_ctx_s *ctx); +void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); +void Vulkan_End2D (struct vulkan_ctx_s *ctx); +void Vulkan_DrawReset (struct vulkan_ctx_s *ctx); +void Vulkan_FlushText (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_draw_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index d380d1236..f859d93f2 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -40,7 +40,7 @@ void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); -void Vulkan_CreatePipelines (struct vulkan_ctx_s *ctx); +VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name); 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 6aff7ea32..0bc8d629d 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -20,6 +20,8 @@ typedef struct vulkan_framebuffer_s { VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; VkCommandBuffer cmdBuffer; + + VkDescriptorSet twodDescriptors; } vulkan_framebuffer_t; typedef struct vulkan_framebufferset_s @@ -49,6 +51,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; struct hashtab_s *descriptorPools; + struct hashtab_s *samplers; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 990d17d88..1d6c5eaea 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -213,7 +213,7 @@ libs_video_renderer_vid_render_vulkan_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_vulkan_la_LIBADD= $(vulkan_libs) libs_video_renderer_vid_render_vulkan_la_DEPENDENCIES=$(vulkan_libs) libs_video_renderer_vid_render_vulkan_la_SOURCES = \ - $(common_sources) \ + $(video_renderer_common_sources) \ libs/video/renderer/vid_render_vulkan.c \ libs/video/renderer/vulkan/buffer.c \ libs/video/renderer/vulkan/command.c \ @@ -249,16 +249,26 @@ vkparse_src = \ vkparse_plist = \ $(srcdir)/libs/video/renderer/vulkan/vkparse.plist +twodv_src = libs/video/renderer/vulkan/twod.vert +twodv_c = libs/video/renderer/vulkan/twod.vert.spvc +twodf_src = libs/video/renderer/vulkan/twod.frag +twodf_c = libs/video/renderer/vulkan/twod.frag.spvc passthrough_src = libs/video/renderer/vulkan/passthrough.vert passthrough_c = libs/video/renderer/vulkan/passthrough.vert.spvc pushcolor_src = libs/video/renderer/vulkan/pushcolor.frag pushcolor_c = libs/video/renderer/vulkan/pushcolor.frag.spvc +$(twodv_c): $(twodv_src) + +$(twodf_c): $(twodf_src) + $(passthrough_c): $(passthrough_src) $(pushcolor_c): $(pushcolor_src) vkshader_c = \ + $(twodv_c) \ + $(twodf_c) \ $(passthrough_c) \ $(pushcolor_c) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a4299d827..f84f9eb84 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -39,6 +39,7 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" @@ -66,7 +67,8 @@ vulkan_R_Init (void) Vulkan_CreateFramebuffers (vulkan_ctx); // FIXME this should be staged so screen updates can begin while pipelines // are being built - Vulkan_CreatePipelines (vulkan_ctx); + vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); + Vulkan_Draw_Init (vulkan_ctx); qfv_swapchain_t *sc = vulkan_ctx->swapchain; @@ -81,7 +83,7 @@ vulkan_R_Init (void) VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, vulkan_ctx->renderpass.renderpass, 0, { {0, 0}, sc->extent }, - 2, clearValues + 2, clearValues + 2 }; for (size_t i = 0; i < vulkan_ctx->framebuffers.size; i++) { __auto_type framebuffer = &vulkan_ctx->framebuffers.a[i]; @@ -153,18 +155,124 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) } } +static void +vulkan_Draw_Character (int x, int y, unsigned ch) +{ + Vulkan_Draw_Character (x, y, ch, vulkan_ctx); +} + +static void +vulkan_Draw_String (int x, int y, const char *str) +{ + Vulkan_Draw_String (x, y, str, vulkan_ctx); +} + +static void +vulkan_Draw_nString (int x, int y, const char *str, int count) +{ + Vulkan_Draw_nString (x, y, str, count, vulkan_ctx); +} + +static void +vulkan_Draw_AltString (int x, int y, const char *str) +{ + Vulkan_Draw_AltString (x, y, str, vulkan_ctx); +} + +static void +vulkan_Draw_ConsoleBackground (int lines, byte alpha) +{ + Vulkan_Draw_ConsoleBackground (lines, alpha, vulkan_ctx); +} + +static void +vulkan_Draw_Crosshair (void) +{ + Vulkan_Draw_Crosshair (vulkan_ctx); +} + +static void +vulkan_Draw_CrosshairAt (int ch, int x, int y) +{ + Vulkan_Draw_CrosshairAt (ch, x, y, vulkan_ctx); +} + +static void +vulkan_Draw_TileClear (int x, int y, int w, int h) +{ + Vulkan_Draw_TileClear (x, y, w, h, vulkan_ctx); +} + +static void +vulkan_Draw_Fill (int x, int y, int w, int h, int c) +{ + Vulkan_Draw_Fill (x, y, w, h, c, vulkan_ctx); +} + +static void +vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha) +{ + Vulkan_Draw_TextBox (x, y, width, lines, alpha, vulkan_ctx); +} + +static void +vulkan_Draw_FadeScreen (void) +{ + Vulkan_Draw_FadeScreen (vulkan_ctx); +} + +static void +vulkan_Draw_BlendScreen (quat_t color) +{ + Vulkan_Draw_BlendScreen (color, vulkan_ctx); +} + static qpic_t * vulkan_Draw_CachePic (const char *path, qboolean alpha) { - return 0; + return Vulkan_Draw_CachePic (path, alpha, vulkan_ctx); } -static qpic_t qpic = { 1, 1, {0} }; +static void +vulkan_Draw_UncachePic (const char *path) +{ + Vulkan_Draw_UncachePic (path, vulkan_ctx); +} static qpic_t * vulkan_Draw_MakePic (int width, int height, const byte *data) { - return &qpic; + return Vulkan_Draw_MakePic (width, height, data, vulkan_ctx); +} + +static void +vulkan_Draw_DestroyPic (qpic_t *pic) +{ + Vulkan_Draw_DestroyPic (pic, vulkan_ctx); +} + +static qpic_t * +vulkan_Draw_PicFromWad (const char *name) +{ + return Vulkan_Draw_PicFromWad (name, vulkan_ctx); +} + +static void +vulkan_Draw_Pic (int x, int y, qpic_t *pic) +{ + Vulkan_Draw_Pic (x, y, pic, vulkan_ctx); +} + +static void +vulkan_Draw_Picf (float x, float y, qpic_t *pic) +{ + Vulkan_Draw_Picf (x, y, pic, vulkan_ctx); +} + +static void +vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height) +{ + Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx); } static vid_model_funcs_t model_funcs = { @@ -194,26 +302,26 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t vulkan_vid_render_funcs = { - 0,//vulkan_Draw_Character, - 0,//vulkan_Draw_String, - 0,//vulkan_Draw_nString, - 0,//vulkan_Draw_AltString, - 0,//vulkan_Draw_ConsoleBackground, - 0,//vulkan_Draw_Crosshair, - 0,//vulkan_Draw_CrosshairAt, - 0,//vulkan_Draw_TileClear, - 0,//vulkan_Draw_Fill, - 0,//vulkan_Draw_TextBox, - 0,//vulkan_Draw_FadeScreen, - 0,//vulkan_Draw_BlendScreen, + vulkan_Draw_Character, + vulkan_Draw_String, + vulkan_Draw_nString, + vulkan_Draw_AltString, + vulkan_Draw_ConsoleBackground, + vulkan_Draw_Crosshair, + vulkan_Draw_CrosshairAt, + vulkan_Draw_TileClear, + vulkan_Draw_Fill, + vulkan_Draw_TextBox, + vulkan_Draw_FadeScreen, + vulkan_Draw_BlendScreen, vulkan_Draw_CachePic, - 0,//vulkan_Draw_UncachePic, + vulkan_Draw_UncachePic, vulkan_Draw_MakePic, - 0,//vulkan_Draw_DestroyPic, - 0,//vulkan_Draw_PicFromWad, - 0,//vulkan_Draw_Pic, - 0,//vulkan_Draw_Picf, - 0,//vulkan_Draw_SubPic, + vulkan_Draw_DestroyPic, + vulkan_Draw_PicFromWad, + vulkan_Draw_Pic, + vulkan_Draw_Picf, + vulkan_Draw_SubPic, vulkan_SCR_UpdateScreen, SCR_DrawRam, diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 0457d0570..86ba71f73 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -165,7 +165,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, family, 1, &priority }; - VkPhysicalDeviceFeatures features; + VkPhysicalDeviceFeatures features = {}; VkDeviceCreateInfo dCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, 1, &qCreateInfo, @@ -173,7 +173,6 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) next, ext, &features }; - memset (&features, 0, sizeof (features)); qfv_device_t *device = calloc (1, sizeof (qfv_device_t) + sizeof (qfv_devfuncs_t)); device->funcs = (qfv_devfuncs_t *) (device + 1); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 1f9c6de46..03a4243b2 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -7,8 +7,61 @@ // $builtin refers to compiled-in shaders passthrough = $builtin/passthrough.vert; pushcolor = $builtin/pushcolor.frag; + twodv = $builtin/twod.vert; + twodf = $builtin/twod.frag; + }; + samplers = { + quakepic = { + magFilter = nearest; + minFilter = nearest; + mipmapMode = nearest; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = 0;//FIXME false!!! + maxAnisotropy = 0; + compareEnable = 0;//FIXME false!!! + compareOp = always; + minLod = 0; + maxLod = 0.25f; + borderColor = float_transparent_black; + unnormalizedCoordinates = 0;//FIXME false!!! + }; + }; + descriptorPools = { + twod = { + flags = 0; + maxSets = $swapchain.images.size; + bindings = ( + { + type = uniform_buffer; + descriptorCount = $swapchain.images.size; + }, + { + type = combined_image_sampler; + descriptorCount = $swapchain.images.size; + }, + ); + }; }; setLayouts = { + twod = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; something = { flags = 0; bindings = ( @@ -28,6 +81,9 @@ }; }; pipelineLayouts = { + twod = { + setLayouts = (twod); + }; something = { setLayouts = (something); pushConstantRanges = ( @@ -39,88 +95,96 @@ ); }; }; - pipeline = { - stages = ( - { stage = vertex; name = main; module = passthrough; }, - { stage = fragment; name = main; module = pushcolor; }, - ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, + pipelines = { + twod = { + stages = ( + { stage = vertex; name = main; module = twodv; }, + { stage = fragment; name = main; module = twodf; }, ); + 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 = 4; + }, + ); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = 0; + }; + 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 = 0; + rasterizerDiscardEnable = 0; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = 0; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = 0; + minSampleShading = 0.5f; + alphaToCoverageEnable = 0; + alphaToOneEnable = 0; + }; + depthStencil = { + depthTestEnable = 1; + depthWriteEnable = 1; + depthCompareOp = less; + depthBoundsTestEnable = 0; + stencilTestEnable = 0; + }; + colorBlend = { + logicOpEnable = 0; + attachments = ({ + blendEnable = 0; + srcColorBlendFactor = src_color; + dstColorBlendFactor = zero; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = zero; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = twod; + //renderPass = renderpass; }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = 0; - }; - 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 = 0; - rasterizerDiscardEnable = 0; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = 0; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = 0; - minSampleShading = 0.5f; - alphaToCoverageEnable = 0; - alphaToOneEnable = 0; - }; - depthStencil = { - depthTestEnable = 1; - depthWriteEnable = 1; - depthCompareOp = less; - depthBoundsTestEnable = 0; - stencilTestEnable = 0; - }; - colorBlend = { - logicOpEnable = 0; - attachments = ({ - blendEnable = 0; - srcColorBlendFactor = src_color; - dstColorBlendFactor = zero; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = zero; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - layout = something; - //renderPass = renderpass; }; renderpass = { attachments = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index f0064bb35..25e1049ea 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -54,6 +54,10 @@ #include "vid_vulkan.h" +static +#include "libs/video/renderer/vulkan/twod.vert.spvc" +static +#include "libs/video/renderer/vulkan/twod.frag.spvc" static #include "libs/video/renderer/vulkan/passthrough.vert.spvc" static @@ -66,6 +70,8 @@ typedef struct shaderdata_s { } shaderdata_t; static shaderdata_t builtin_shaders[] = { + { "twod.vert", twod_vert, sizeof (twod_vert) }, + { "twod.frag", twod_frag, sizeof (twod_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, {} diff --git a/libs/video/renderer/vulkan/twod.frag b/libs/video/renderer/vulkan/twod.frag new file mode 100644 index 000000000..83bda0874 --- /dev/null +++ b/libs/video/renderer/vulkan/twod.frag @@ -0,0 +1,19 @@ +#version 450 + +layout (set = 0, binding = 1) uniform sampler2D Texture; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec4 color; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec4 pix; + + pix = texture (Texture, st); + if (pix.a < 0.5) + discard; + frag_color = pix * color; +} diff --git a/libs/video/renderer/vulkan/twod.vert b/libs/video/renderer/vulkan/twod.vert new file mode 100644 index 000000000..83655d6a7 --- /dev/null +++ b/libs/video/renderer/vulkan/twod.vert @@ -0,0 +1,27 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Model; +}; +/** Vertex position. + + x, y, s, t + + \a vertex provides the onscreen location at which to draw the icon + (\a x, \a y) and texture coordinate for the icon (\a s=z, \a t=w). +*/ +layout (location = 0) in vec4 vertex; +layout (location = 1) in vec4 vcolor; + +layout (location = 0) out vec2 st; +layout (location = 1) out vec4 color; + +void +main (void) +{ + gl_Position = Projection * vec4 (vertex.xy, 0.0, 1.0); + st = vertex.zw; + color = vcolor; +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 628306044..7f5e11111 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -3,10 +3,10 @@ 2D drawing support for Vulkan - Copyright (C) 2011 Bill Currie + Copyright (C) 2021 Bill Currie Author: Bill Currie - Date: 2011/12/23 + Date: 2021/1/10 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -49,10 +49,24 @@ #include "QF/sys.h" #include "QF/vid.h" +#include "compat.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" #include "r_internal.h" +#include "vid_vulkan.h" +#include "vkparse.h" + +//FIXME move into a context struct +VkImage conchars_image; +VkDeviceMemory conchars_memory; +VkImageView conchars_view; +VkSampler conchars_sampler; + +VkPipeline twod; static qpic_t * pic_data (const char *name, int w, int h, const byte *data) @@ -67,135 +81,189 @@ pic_data (const char *name, int w, int h, const byte *data) } qpic_t * -vulkan_Draw_MakePic (int width, int height, const byte *data) +Vulkan_Draw_MakePic (int width, int height, const byte *data, + vulkan_ctx_t *ctx) { return pic_data (0, width, height, data); } void -vulkan_Draw_DestroyPic (qpic_t *pic) +Vulkan_Draw_DestroyPic (qpic_t *pic, vulkan_ctx_t *ctx) { } qpic_t * -vulkan_Draw_PicFromWad (const char *name) +Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) { return pic_data (0, 1, 1, (const byte *)""); } qpic_t * -vulkan_Draw_CachePic (const char *path, qboolean alpha) +Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) { return pic_data (0, 1, 1, (const byte *)""); } void -vulkan_Draw_UncachePic (const char *path) +Vulkan_Draw_UncachePic (const char *path, vulkan_ctx_t *ctx) { } void -vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha) +Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, + vulkan_ctx_t *ctx) +{ +} + +static void +Vulkan_Draw_Shutdown (void *data) +{ + vulkan_ctx_t *ctx = data; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyPipeline (device->dev, twod, 0); + dfunc->vkDestroyImageView (device->dev, conchars_view, 0); + dfunc->vkFreeMemory (device->dev, conchars_memory, 0); + dfunc->vkDestroyImage (device->dev, conchars_image, 0); +} + +void +Vulkan_Draw_Init (vulkan_ctx_t *ctx) +{ + Sys_RegisterShutdown (Vulkan_Draw_Shutdown, ctx); + + qfv_device_t *device = ctx->device; + qpic_t *charspic = Draw_Font8x8Pic (); + VkExtent3D extent = { charspic->width, charspic->height, 1 }; + conchars_image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_A8B8G8R8_UNORM_PACK32, + extent, 1, 1, + VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, + 1); + conchars_memory = QFV_AllocImageMemory (device, conchars_image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_BindImageMemory (device, conchars_image, conchars_memory, 0); + conchars_view = QFV_CreateImageView (device, conchars_image, + VK_IMAGE_VIEW_TYPE_2D, + VK_FORMAT_A8B8G8R8_UNORM_PACK32, + VK_IMAGE_ASPECT_COLOR_BIT); + conchars_sampler = Hash_Find (ctx->samplers, "quakepic"); + + twod = Vulkan_CreatePipeline (ctx, "twod"); + + handleref_t *h; + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (ctx->framebuffers.size, alloca); + for (size_t i = 0; i < layouts->size; i++) { + h = Hash_Find (ctx->setLayouts, "twod"); + layouts->a[i] = (VkDescriptorSetLayout) h->handle; + } + h = Hash_Find (ctx->descriptorPools, "twod"); + __auto_type pool = (VkDescriptorPool) h->handle; + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); + for (size_t i = 0; i < ctx->framebuffers.size; i++) { + ctx->framebuffers.a[i].twodDescriptors = sets->a[i]; + } +} + +void +Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Init (void) +Vulkan_Draw_String (int x, int y, const char *str, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Character (int x, int y, unsigned int chr) +Vulkan_Draw_nString (int x, int y, const char *str, int count, + vulkan_ctx_t *ctx) { } void -vulkan_Draw_String (int x, int y, const char *str) +Vulkan_Draw_AltString (int x, int y, const char *str, vulkan_ctx_t *ctx) { } void -vulkan_Draw_nString (int x, int y, const char *str, int count) +Vulkan_Draw_CrosshairAt (int ch, int x, int y, vulkan_ctx_t *ctx) { } void -vulkan_Draw_AltString (int x, int y, const char *str) +Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) { } void -vulkan_Draw_CrosshairAt (int ch, int x, int y) +Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Crosshair (void) +Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Pic (int x, int y, qpic_t *pic) +Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, + int srcx, int srcy, int width, int height, + vulkan_ctx_t *ctx) { } void -vulkan_Draw_Picf (float x, float y, qpic_t *pic) +Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) { } void -vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, - int height) +Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) { } void -vulkan_Draw_ConsoleBackground (int lines, byte alpha) +Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) { } void -vulkan_Draw_TileClear (int x, int y, int w, int h) +Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx) { } void -vulkan_Draw_Fill (int x, int y, int w, int h, int c) +Vulkan_Set2D (vulkan_ctx_t *ctx) { } void -vulkan_Draw_FadeScreen (void) +Vulkan_Set2DScaled (vulkan_ctx_t *ctx) { } void -Vulkan_Set2D (void) +Vulkan_End2D (vulkan_ctx_t *ctx) { } void -Vulkan_Set2DScaled (void) +Vulkan_DrawReset (vulkan_ctx_t *ctx) { } void -Vulkan_End2D (void) +Vulkan_FlushText (vulkan_ctx_t *ctx) { } void -Vulkan_DrawReset (void) -{ -} - -void -Vulkan_FlushText (void) -{ -} - -void -vulkan_Draw_BlendScreen (quat_t color) +Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) { } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 3f701e27a..c2b17d0fe 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -420,18 +420,25 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) ctx->renderpass.depthImage = 0; } -void -Vulkan_CreatePipelines (vulkan_ctx_t *ctx) +VkPipeline +Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) { qfv_load_pipeline (ctx); plitem_t *item = ctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, "pipeline"))) { - Sys_Printf ("error loading pipeline\n"); + if (!item || !(item = PL_ObjectForKey (item, "pipelines"))) { + Sys_Printf ("error loading pipelines\n"); + return 0; } else { - Sys_Printf ("Found pipeline def\n"); + Sys_Printf ("Found pipelines def\n"); } - ctx->pipeline = QFV_ParsePipeline (ctx, item); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading pipeline %s\n", name); + return 0; + } else { + Sys_Printf ("Found pipeline def %s\n", name); + } + return QFV_ParsePipeline (ctx, item); } void