From 57968249feb6ec0c8394148d75272909e54e967e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 00:55:45 +0900 Subject: [PATCH] [vulkan] Start work on the alias pipeline --- include/QF/Vulkan/qf_alias.h | 84 ++++++ include/QF/model.h | 13 +- libs/models/alias/vulkan_model_alias.c | 291 ++++++++++++++++++++ libs/video/renderer/Makemodule.am | 10 + libs/video/renderer/vid_render_vulkan.c | 6 +- libs/video/renderer/vulkan/alias.frag | 55 ++++ libs/video/renderer/vulkan/alias.vert | 38 +++ libs/video/renderer/vulkan/qfpipeline.plist | 201 +++++++++++++- libs/video/renderer/vulkan/shader.c | 6 + libs/video/renderer/vulkan/vulkan_bsp.c | 9 +- 10 files changed, 695 insertions(+), 18 deletions(-) create mode 100644 include/QF/Vulkan/qf_alias.h create mode 100644 libs/video/renderer/vulkan/alias.frag create mode 100644 libs/video/renderer/vulkan/alias.vert diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h new file mode 100644 index 000000000..efe3dd0dc --- /dev/null +++ b/include/QF/Vulkan/qf_alias.h @@ -0,0 +1,84 @@ +/* + qf_alias.h + + Vulkan specific brush model stuff + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/1/18 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_alias_h +#define __QF_Vulkan_qf_alias_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" + +typedef struct aliasvrt_s { + float vertex[4]; + float normal[4]; +} aliasvrt_t; + +typedef struct aliasuv_s { + float u, v; +} aliasuv_t; + +typedef struct qfv_alias_mesh_s { + VkBuffer vertex_buffer; + VkBuffer uv_buffer; + VkBuffer index_buffer; + VkDeviceMemory memory; +} qfv_alias_mesh_t; + +typedef struct qfv_light_s { + vec3_t color; + float dist; + vec3_t position; + int type; + vec3_t direction; + float cone; +} qfv_light_t; + +typedef struct qfv_light_buffer_s { + int light_count; + qfv_light_t lights[] __attribute__((aligned(16))); +} qfv_light_buffer_t; + +typedef struct alias_ctx_s { +} alias_ctx_t; + +struct vulkan_ctx_s; +void *Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, + qboolean group, maliasskindesc_t *skindesc, + struct vulkan_ctx_s *ctx); +void Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, + struct vulkan_ctx_s *ctx); +void Vulkan_Mod_LoadExternalSkins (model_t *mod, struct vulkan_ctx_s *ctx); +void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, + void *_m, int _s, int extra, + struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_alias_h diff --git a/include/QF/model.h b/include/QF/model.h index 703d11227..d1129bfce 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -277,10 +277,15 @@ typedef struct { } maliasframedesc_t; typedef struct { - aliasskintype_t type; - int skin; - int texnum; - int fb_texnum; + aliasskintype_t type; + int skin; + union { + struct { + int texnum; + int fb_texnum; + }; + void *tex; + }; } maliasskindesc_t; typedef struct { diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index e69de29bb..97801febc 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -0,0 +1,291 @@ +/* + vulkan_model_alais.c + + Alias model processing for Vulkan + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/1/24 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/va.h" + +#include "QF/modelgen.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_alias.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" + +#include "mod_internal.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +static vec3_t vertex_normals[NUMVERTEXNORMALS] = { +#include "anorms.h" +}; + +static void +vulkan_alias_clear (model_t *m, void *data) +{ +} + +void * +Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, + qboolean group, maliasskindesc_t *skindesc, + vulkan_ctx_t *ctx) +{ + byte *tskin; + int w, h; + + w = pheader->mdl.skinwidth; + h = pheader->mdl.skinheight; + tskin = malloc (skinsize); + memcpy (tskin, skin, skinsize); + Mod_FloodFillSkin (tskin, w, h); + tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin}; + skindesc->tex = Vulkan_LoadTex (ctx, &skin_tex, 1); + free (tskin); + return skin + skinsize; +} + +void +Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, vulkan_ctx_t *ctx) +{ + if (hdr->mdl.ident == HEADER_MDL16) + VectorScale (hdr->mdl.scale, 1/256.0, hdr->mdl.scale); + m->clear = vulkan_alias_clear; +} + +void +Vulkan_Mod_LoadExternalSkins (model_t *mod, vulkan_ctx_t *ctx) +{ +} + +void +Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, + int _s, int extra, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasvrt_t *verts; + aliasuv_t *uv; + trivertx_t *pv; + int *indexmap; + uint32_t *indices; + int numverts; + int numtris; + int i, j; + int pose; + vec3_t pos; + + numverts = hdr->mdl.numverts; + numtris = hdr->mdl.numtris; + + // initialize indexmap to -1 (unduplicated). any other value indicates + // both that the vertex has been duplicated and the index of the + // duplicate vertex. + indexmap = malloc (numverts * sizeof (int)); + memset (indexmap, -1, numverts * sizeof (int)); + + // check for onseam verts, and duplicate any that are associated with + // back-facing triangles + for (i = 0; i < numtris; i++) { + for (j = 0; j < 3; j++) { + int vind = triangles.a[i].vertindex[j]; + if (stverts.a[vind].onseam && !triangles.a[i].facesfront) { + // duplicate the vertex if it has not alreaddy been + // duplicated + if (indexmap[vind] == -1) { + indexmap[vind] = numverts++; + } + } + } + } + + // we now know exactly how many vertices we need, so built the vertex + // and index data arrays + // The layout is: + // vbuf:{vertex, normal} * (numposes * numverts) + // uvbuf:{uv} * (numverts) + // ibuf:{index} * (numtris * 3) + // numverts includes the duplicated seam vertices. + // The vertex buffer will be bound with various offsets based on the + // current and previous pose, uvbuff "statically" bound as uvs are not + // animated by pose, and the same for ibuf: indices will never change for + // the mesh + size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; + size_t vert_count = numverts * hdr->numposes; + size_t vert_size = vert_count * sizeof (aliasvrt_t); + size_t uv_size = numverts * sizeof (aliasuv_t); + size_t ind_size = numverts * sizeof (uint32_t); + vert_size = (vert_size + atom_mask) & ~atom_mask; + uv_size = (uv_size + atom_mask) & ~atom_mask; + ind_size = (ind_size + atom_mask) & ~atom_mask; + size_t buff_size = vert_size + ind_size + uv_size; + + VkBuffer vbuff = QFV_CreateBuffer (device, buff_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + VkBuffer uvbuff = QFV_CreateBuffer (device, buff_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + VkBuffer ibuff = QFV_CreateBuffer (device, buff_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + VkDeviceMemory mem; + mem = QFV_AllocBufferMemory (device, vbuff, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + buff_size, 0); + QFV_BindBufferMemory (device, vbuff, mem, 0); + QFV_BindBufferMemory (device, uvbuff, mem, vert_size); + QFV_BindBufferMemory (device, ibuff, mem, vert_size + uv_size); + + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, buff_size, + ctx->cmdpool); + qfv_packet_t *packet = QFV_PacketAcquire (stage); + verts = QFV_PacketExtend (packet, vert_size); + uv = QFV_PacketExtend (packet, uv_size); + indices = QFV_PacketExtend (packet, ind_size); + + // populate the uvs, duplicating and shifting any that are on the seam + // and associated with back-facing triangles (marked by non-negative + // indexmap entry). + // the s coordinate is shifted right by half the skin width. + for (i = 0; i < hdr->mdl.numverts; i++) { + int vind = indexmap[i]; + uv[i].u = (float) stverts.a[i].s / hdr->mdl.skinwidth; + uv[i].v = (float) stverts.a[i].t / hdr->mdl.skinheight; + if (vind != -1) { + uv[vind] = uv[i]; + uv[vind].u += 0.5; + } + } + + // poputlate the vertex position and normal data, duplicating for + // back-facing on-seam verts (indicated by non-negative indexmap entry) + for (i = 0, pose = 0; i < hdr->numposes; i++, pose += numverts) { + for (j = 0; j < hdr->mdl.numverts; j++) { + pv = &poseverts.a[i][j]; + if (extra) { + VectorMultAdd (pv[hdr->mdl.numverts].v, 256, pv->v, pos); + } else { + VectorCopy (pv->v, pos); + } + VectorCompMultAdd (hdr->mdl.scale_origin, hdr->mdl.scale, + pos, verts[pose + j].vertex); + VectorCopy (vertex_normals[pv->lightnormalindex], + verts[pose + j].normal); + // duplicate on-seam vert associated with back-facing triangle + if (indexmap[j] != -1) { + verts[pose + indexmap[j]] = verts[pose + j]; + } + } + } + + // now build the indices for DrawElements + for (i = 0; i < numverts; i++) { + indexmap[i] = indexmap[i] != -1 ? indexmap[i] : i; + } + for (i = 0; i < numtris; i++) { + for (j = 0; j < 3; j++) { + indices[3 * i + j] = indexmap[triangles.a[i].vertindex[j]]; + } + } + // finished with indexmap + free (indexmap); + + hdr->poseverts = numverts; + + VkBufferMemoryBarrier wr_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + vbuff, 0, vert_size}, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + uvbuff, 0, uv_size}, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ibuff, 0, ind_size}, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 3, wr_barriers, 0, 0); + VkBufferCopy copy_region[] = { + { packet->offset, 0, vert_size }, + { packet->offset + vert_size, 0, uv_size }, + { packet->offset + vert_size + uv_size, 0, ind_size }, + }; + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, + vbuff, 1, ©_region[0]); + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, + uvbuff, 1, ©_region[1]); + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, + ibuff, 1, ©_region[2]); + VkBufferMemoryBarrier rd_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + vbuff, 0, vert_size }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + uvbuff, 0, uv_size }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ibuff, 0, ind_size }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, 0, 1, rd_barriers, 0, 0); + QFV_PacketSubmit (packet); + QFV_DestroyStagingBuffer (stage); + + qfv_alias_mesh_t *mesh = Hunk_Alloc (sizeof (qfv_alias_mesh_t)); + mesh->vertex_buffer = vbuff; + mesh->uv_buffer = uvbuff; + mesh->index_buffer = ibuff; + mesh->memory = mem; + hdr->commands = (byte *) mesh - (byte *) hdr; +} diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 5a30c9f0c..e3b154541 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -269,6 +269,10 @@ quakebspv_src = libs/video/renderer/vulkan/quakebsp.vert quakebspv_c = libs/video/renderer/vulkan/quakebsp.vert.spvc quakebspf_src = libs/video/renderer/vulkan/quakebsp.frag quakebspf_c = libs/video/renderer/vulkan/quakebsp.frag.spvc +aliasv_src = libs/video/renderer/vulkan/alias.vert +aliasv_c = libs/video/renderer/vulkan/alias.vert.spvc +aliasf_src = libs/video/renderer/vulkan/alias.frag +aliasf_c = libs/video/renderer/vulkan/alias.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 @@ -282,6 +286,10 @@ $(quakebspv_c): $(quakebspv_src) $(quakebspf_c): $(quakebspf_src) +$(aliasv_c): $(aliasv_src) + +$(aliasf_c): $(aliasf_src) + $(passthrough_c): $(passthrough_src) $(pushcolor_c): $(pushcolor_src) @@ -291,6 +299,8 @@ vkshader_c = \ $(twodf_c) \ $(quakebspv_c) \ $(quakebspf_c) \ + $(aliasv_c) \ + $(aliasf_c) \ $(passthrough_c) \ $(pushcolor_c) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a54962b52..2b001bcd3 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_alias.h" #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_lightmap.h" @@ -419,18 +420,21 @@ static void vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra) { + Vulkan_Mod_MakeAliasModelDisplayLists (m, hdr, _m, _s, extra, vulkan_ctx); } static void * vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) { - return skin + skinsize; + return Vulkan_Mod_LoadSkin (skin, skinsize, snum, gnum, group, skindesc, + vulkan_ctx); } static void vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) { + Vulkan_Mod_FinalizeAliasModel (m, hdr, vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag new file mode 100644 index 000000000..935fa06b4 --- /dev/null +++ b/libs/video/renderer/vulkan/alias.frag @@ -0,0 +1,55 @@ +#version 450 + +layout (set = 0, binding = 1) uniform sampler2D Texture; +layout (set = 0, binding = 2) uniform sampler2D GlowMap; +layout (set = 0, binding = 3) uniform sampler2D ColorA; +layout (set = 0, binding = 4) uniform sampler2D ColorB; + +struct LightData { + vec3 color; + float dist; + vec3 position; + int type; + vec3 direction; + float cone; +}; + +layout (constant_id = 0) const int MaxLights = 8; +layout (set = 1, binding = 0) uniform Lights { + int light_count; + LightData lights[MaxLights]; +}; + +layout (push_constant) uniform PushConstants { + layout (offset = 80) + vec4 fog; + vec4 color; +}; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec3 position; +layout (location = 2) in vec3 normal; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec4 c; + int i; + vec3 light = vec3 (0); + + c = texture (Texture, st); + c += texture (ColorA, st); + c += texture (ColorB, st); + c += texture (GlowMap, st); + if (MaxLights > 0) { + for (i = 0; i < light_count; i++) { + vec3 dist = lights[i].position - position; + float dd = dot (dist, dist); + float mag = max (0.0, dot (dist, normal)); + light += lights[i].color * mag * lights[i].dist / dd; + } + } + frag_color = c * vec4(light, 1);//fogBlend (c); +} diff --git a/libs/video/renderer/vulkan/alias.vert b/libs/video/renderer/vulkan/alias.vert new file mode 100644 index 000000000..871c3a0c0 --- /dev/null +++ b/libs/video/renderer/vulkan/alias.vert @@ -0,0 +1,38 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Sky; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; + float blend; +}; + +layout (location = 0) in vec4 vertexa; +layout (location = 1) in vec3 normala; +layout (location = 2) in vec4 vertexb; +layout (location = 3) in vec3 normalb; +layout (location = 4) in vec2 uv; + +layout (location = 0) out vec2 st; +layout (location = 1) out vec3 position; +layout (location = 2) out vec3 normal; + +void +main (void) +{ + vec4 vertex; + vec3 norm; + vec4 pos; + + vertex = mix (vertexa, vertexb, blend); + norm = mix (normala, normalb, blend); + pos = (Model * vertex); + gl_Position = Projection * (View * pos); + position = pos.xyz; + normal = mat3 (Model) * norm; + st = uv; +} diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index b5f5cd6cb..5fd0680af 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -11,6 +11,8 @@ twodf = $builtin/twod.frag; quakebspv = $builtin/quakebsp.vert; quakebspf = $builtin/quakebsp.frag; + aliasv = $builtin/alias.vert; + aliasf = $builtin/alias.frag; }; samplers = { quakepic = { @@ -30,7 +32,7 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; - quakebsp = { + quakebsp.sampler = { magFilter = linear; minFilter = linear; mipmapMode = linear; @@ -81,7 +83,7 @@ }, ); }; - quakebsp = { + quakebsp.textures = { flags = push_descriptor; bindings = ( { @@ -122,6 +124,51 @@ }, ); }; + alias.textures = { + flags = push_descriptor; + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 3; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 4; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + alias.lights = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; something = { flags = 0; bindings = ( @@ -144,8 +191,8 @@ twod = { setLayouts = (twod); }; - quakebsp = { - setLayouts = (quakebsp); + quakebsp.layout = { + setLayouts = (quakebsp.textures); pushConstantRanges = ( { stageFlags = vertex; @@ -159,6 +206,21 @@ }, ); }; + alias.layout = { + setLayouts = (alias.textures, alias.lights); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 80; + size = "2 * 4 * 4"; + }, + ); + }; something = { setLayouts = (something); pushConstantRanges = ( @@ -171,6 +233,133 @@ }; }; pipelines = { + alias = { + stages = ( + { stage = vertex; name = main; module = aliasv; }, + { + stage = fragment; + name = main; + module = aliasf; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 0; }, + ); + data = <00000000>; + }; + }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "2 * 4 * 4"; + inputRate = vertex; + }, + { + binding = 1; + stride = "2 * 4 * 4"; + inputRate = vertex; + }, + { + binding = 2; + stride = "2 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + { + location = 1; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 16; + }, + { + location = 2; + binding = 1; + format = r32g32b32a32_sfloat; + offset = 0; + }, + { + location = 3; + binding = 1; + format = r32g32b32a32_sfloat; + offset = 16; + }, + { + location = 4; + binding = 2; + format = r32g32_sfloat; + offset = 0; + }, + ); + }; + inputAssembly = { + topology = triangle; + primitiveRestartEnable = false; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = 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; + }); + }; + dynamic = { + dynamicState = ( viewport, scissor, blend_constants ); + }; + layout = alias; + //renderPass = renderpass; + }; quakebsp.main = { stages = ( { stage = vertex; name = main; module = quakebspv; }, @@ -257,7 +446,7 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = quakebsp; + layout = quakebsp.layout; //renderPass = renderpass; }; quakebsp.skysheet = { @@ -359,7 +548,7 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = quakebsp; + layout = quakebsp.layout; //renderPass = renderpass; }; twod = { diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 4b0fed532..a3cc9e3f0 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -63,6 +63,10 @@ static static #include "libs/video/renderer/vulkan/quakebsp.frag.spvc" static +#include "libs/video/renderer/vulkan/alias.vert.spvc" +static +#include "libs/video/renderer/vulkan/alias.frag.spvc" +static #include "libs/video/renderer/vulkan/passthrough.vert.spvc" static #include "libs/video/renderer/vulkan/pushcolor.frag.spvc" @@ -78,6 +82,8 @@ static shaderdata_t builtin_shaders[] = { { "twod.frag", twod_frag, sizeof (twod_frag) }, { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, { "quakebsp.frag", quakebsp_frag, sizeof (quakebsp_frag) }, + { "alias.vert", alias_vert, sizeof (alias_vert) }, + { "alias.frag", alias_frag, sizeof (alias_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, {} diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 6da253bea..c95a14c97 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1420,13 +1420,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main"); bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp.skysheet"); - bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp"); - bctx->sampler = QFV_GetSampler (ctx, "quakebsp"); - - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "quakebsp"); - } + bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp.layout"); + bctx->sampler = QFV_GetSampler (ctx, "quakebsp.sampler"); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers);