From db6c76d583f5aa5f2e0cef9352988fcbf9c615ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 12:20:32 +0900 Subject: [PATCH] [vulkan] Abandon bindless rendering At least for now, it is more trouble than it is worth as it (or my implementation of it) breaks lavapipe and renderdoc. --- include/QF/Vulkan/qf_alias.h | 7 +- include/QF/Vulkan/qf_bsp.h | 8 +- include/QF/Vulkan/qf_texture.h | 12 ++ include/vid_vulkan.h | 1 + libs/models/brush/vulkan_model_brush.c | 4 + libs/video/renderer/vulkan/qfpipeline.plist | 62 ++------- .../renderer/vulkan/shader/alias_gbuf.frag | 14 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 10 +- .../video/renderer/vulkan/shader/bsp_sky.frag | 26 ++-- .../renderer/vulkan/shader/bsp_turb.frag | 10 +- .../renderer/vulkan/shader/particle.frag | 2 - .../renderer/vulkan/shader/sprite_depth.frag | 2 - .../renderer/vulkan/shader/sprite_gbuf.frag | 2 - libs/video/renderer/vulkan/vulkan_alias.c | 112 ++-------------- libs/video/renderer/vulkan/vulkan_bsp.c | 124 +++++++----------- libs/video/renderer/vulkan/vulkan_texture.c | 72 ++++++++++ 16 files changed, 183 insertions(+), 285 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index c42602d39..08ca86e94 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -60,7 +60,7 @@ typedef struct qfv_alias_skin_s { VkImageView view; byte colora[4]; byte colorb[4]; - int texind; + VkDescriptorSet descriptor; } qfv_alias_skin_t; typedef enum { @@ -85,13 +85,8 @@ typedef struct aliasctx_s { aliasframeset_t frames; VkPipeline depth; VkPipeline gbuf; - VkDescriptorSet descriptors; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; VkPipelineLayout layout; - unsigned maxImages; VkSampler sampler; - aliasindset_t texindices; } aliasctx_t; struct vulkan_ctx_s; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 0f5d54f7a..38c738c43 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -46,7 +46,7 @@ typedef struct vulktex_s { struct elechain_s *elechain; struct elechain_s **elechain_tail; struct qfv_tex_s *tex; - int texind; + VkDescriptorSet descriptor; } vulktex_t; typedef struct bspvert_s { @@ -96,7 +96,6 @@ typedef struct bspframe_s { typedef struct fragconst_s { quat_t fog; float time; - int texind; } fragconst_t; typedef struct bspframeset_s @@ -138,6 +137,7 @@ typedef struct bspctx_s { struct qfv_tex_s *default_skybox; struct qfv_tex_s *skybox_tex; + VkDescriptorSet skybox_descriptor; vec4f_t sky_rotation[2]; vec4f_t sky_velocity; vec4f_t sky_fix; @@ -152,11 +152,7 @@ typedef struct bspctx_s { struct bsppoly_s *polys; VkSampler sampler; - VkDescriptorSet descriptors; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; VkPipelineLayout layout; - unsigned maxImages; VkDeviceMemory texture_memory; VkPipeline depth; diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index fec02a8f9..eadbc8b16 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -10,6 +10,11 @@ typedef struct qfv_tex_s { VkImageView view; } qfv_tex_t; +typedef struct texturectx_s { + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; +} texturectx_t; + void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, int alpha, int count); qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip, @@ -22,5 +27,12 @@ VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx); void Vulkan_Texture_Shutdown (struct vulkan_ctx_s *ctx); +VkDescriptorSet Vulkan_CreateCombinedImageSampler (struct vulkan_ctx_s *ctx, + VkImageView view, + VkSampler sampler); +VkDescriptorSet Vulkan_CreateTextureDescriptor (struct vulkan_ctx_s *ctx, + qfv_tex_t *tex, + VkSampler sampler); +void Vulkan_FreeTexture (struct vulkan_ctx_s *ctx, VkDescriptorSet texture); #endif//__QF_Vulkan_qf_texture_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index e0be2a993..66d394181 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -56,6 +56,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *imageViews; struct hashtab_s *renderpasses; + struct texturectx_s *texture_context; struct matrixctx_s *matrix_context; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 471cfac4c..2fcc9f5bd 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -83,6 +83,10 @@ vulkan_brush_clear (model_t *mod, void *data) vulktex_t *tex = tx->render; dfunc->vkDestroyImage (device->dev, tex->tex->image, 0); dfunc->vkDestroyImageView (device->dev, tex->tex->view, 0); + if (tex->descriptor) { + Vulkan_FreeTexture (ctx, tex->descriptor); + tex->descriptor = 0; + } } dfunc->vkFreeMemory (device->dev, mctx->texture_memory, 0); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index dfd5e1a43..d503ac144 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -4,7 +4,6 @@ //needs to agree on the size, so it might as well set maxSamplers //directly (and any other such variable) maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; - maxImages = "min (256u, $physDevLimits.maxPerStageDescriptorSampledImages - 8u)"; }; samplers = { quakepic = { @@ -99,16 +98,12 @@ ); }; texture_pool = { - flags = 0; - maxSets = 1; + flags = free_descriptor_set; + maxSets = 512; bindings = ( { - type = sampler; - descriptorCount = 1; - }, - { - type = sampled_image; - descriptorCount = $properties.limits.maxImages; + type = combined_image_sampler; + descriptorCount = $properties.descriptorPools.texture_pool.maxSets; }, ); }; @@ -205,16 +200,10 @@ bindings = ( { binding = 0; - descriptorType = sampler; + descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; }, - { - binding = 1; - descriptorType = sampled_image; - descriptorCount = $properties.limits.maxImages; - stageFlags = fragment; - }, ); }; quakebsp_set = $properties.setLayouts.texture_set; @@ -333,7 +322,7 @@ setLayouts = (matrix_set, twod_set); }; quakebsp_layout = { - setLayouts = (matrix_set, quakebsp_set); + setLayouts = (matrix_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; @@ -343,7 +332,7 @@ { stageFlags = fragment; offset = 64; - size = 32; + size = "4 * 4 + 4"; }, ); }; @@ -697,13 +686,6 @@ stage = fragment; name = main; module = $builtin/alias_gbuf.frag; - specializationInfo = { - mapEntries = ( - // MaxTextures - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(uint($properties.limits.maxImages))"; - }; }, ); vertexInput = $properties.vertexInput.alias; @@ -773,13 +755,6 @@ stage = fragment; name = main; module = $builtin/bsp_gbuf.frag; - specializationInfo = { - mapEntries = ( - // MaxTextures - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(uint($properties.limits.maxImages))"; - }; }, ); vertexInput = $properties.vertexInput.brush; @@ -817,14 +792,12 @@ module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( - // MaxTextures - { size = 4; offset = 8; constantID = 0; }, // doSkyBox - { size = 4; offset = 4; constantID = 1; }, + { size = 4; offset = 4; constantID = 0; }, // doSkySheet - { size = 4; offset = 0; constantID = 2; }, + { size = 4; offset = 0; constantID = 1; }, ); - data = "array(0, 1, uint($properties.limits.maxImages))"; + data = "array(0, 1)"; }; }, ); @@ -858,14 +831,12 @@ module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( - // MaxTextures - { size = 4; offset = 8; constantID = 0; }, // doSkyBox - { size = 4; offset = 0; constantID = 1; }, + { size = 4; offset = 0; constantID = 0; }, // doSkySheet - { size = 4; offset = 4; constantID = 2; }, + { size = 4; offset = 4; constantID = 1; }, ); - data = "array(0, 1, uint($properties.limits.maxImages))"; + data = "array(0, 1)"; }; }, ); @@ -897,13 +868,6 @@ stage = fragment; name = main; module = $builtin/bsp_turb.frag; - specializationInfo = { - mapEntries = ( - // MaxTextures - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(uint($properties.limits.maxImages))"; - }; }, ); vertexInput = $properties.vertexInput.brush; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 28c37fec8..2b751a0c7 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -1,13 +1,9 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray skins[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray Skin; layout (push_constant) uniform PushConstants { layout (offset = 68) - uint texind; uint colorA; uint colorB; vec4 base_color; @@ -30,10 +26,10 @@ main (void) vec4 e; int i; vec3 light = vec3 (0); - c = texture (sampler2DArray(skins[texind], samp), vec3 (st, 0)) * base_color; - c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 1)) * unpackUnorm4x8(colorA); - c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 2)) * unpackUnorm4x8(colorB); - e = texture (sampler2DArray(skins[texind], samp), vec3 (st, 3)); + c = texture (Skin, vec3 (st, 0)) * base_color; + c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA); + c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); + e = texture (Skin, vec3 (st, 3)); frag_color = c; frag_emission = e; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 7d1c7c3c9..843148635 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -1,15 +1,11 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray textures[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; - int texind; }; layout (location = 0) in vec4 tl_st; @@ -41,8 +37,8 @@ main (void) vec3 e_st = vec3 (tl_st.xy, 1); vec2 l_st = vec2 (tl_st.zw); - c = texture (sampler2DArray (textures[texind], samp), t_st); - e = texture (sampler2DArray (textures[texind], samp), e_st); + c = texture (Texture, t_st); + e = texture (Texture, e_st); frag_color = c;//fogBlend (c); frag_emission = e; frag_normal = vec4 (normal, 0); diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index dc6fe6d6a..25ccf9ba0 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -1,19 +1,15 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; layout (constant_id = 1) const bool doSkyBox = false; layout (constant_id = 2) const bool doSkySheet = false; -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray sheet_tex[MaxTextures]; -layout (set = 1, binding = 1) uniform textureCube cube_tex[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray SkySheet; +layout (set = 2, binding = 0) uniform samplerCube SkyBox; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; - int sheet_ind; - int cube_ind; }; layout (location = 0) in vec4 tl_st; @@ -34,7 +30,7 @@ fogBlend (vec4 color) } vec4 -sky_sheet (vec3 dir, float time, texture2DArray tex) +sky_sheet (vec3 dir, float time) { float len; vec2 flow = vec2 (1.0, 1.0); @@ -50,8 +46,8 @@ sky_sheet (vec3 dir, float time, texture2DArray tex) st1 = vec3 (base + flow * time / 8.0, 0); st2 = vec3 (base + flow * time / 16.0, 1); - c1 = texture (sampler2DArray(tex, samp), st1); - c2 = texture (sampler2DArray(tex, samp), st2); + c1 = texture (SkySheet, st1); + c2 = texture (SkySheet, st2); c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); @@ -59,7 +55,7 @@ sky_sheet (vec3 dir, float time, texture2DArray tex) } vec4 -sky_box (vec3 dir, float time, textureCube tex) +sky_box (vec3 dir, float time) { // NOTE: quake's world is right-handed with Z up and X forward, but // Vulkan's cube maps are left-handed with Y up and Z forward. The @@ -67,21 +63,21 @@ sky_box (vec3 dir, float time, textureCube tex) // to do here is swizzle the Y and Z coordinates dir = normalize(dir); //return vec4(dir.xyz, 1) * 0.5 + vec4(0.5); - return texture (samplerCube (tex, samp), dir.xzy); + return texture (SkyBox, dir.xzy); } vec4 sky_color (vec3 dir, float time) { if (!doSkySheet) { - return sky_box (dir, time, cube_tex[cube_ind]); + return sky_box (dir, time); } if (!doSkyBox) { - return sky_sheet (dir, time, sheet_tex[sheet_ind]); + return sky_sheet (dir, time); } else { // can see through the sheet (may look funny when looking down) // maybe have 4 sheet layers instead of 2? - vec4 c1 = sky_sheet (dir, time, sheet_tex[sheet_ind]); - vec4 c2 = sky_box (dir, time, cube_tex[cube_ind]); + vec4 c1 = sky_sheet (dir, time); + vec4 c2 = sky_box (dir, time); return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); return vec4 (1, 0, 1, 1); } diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index bee7a6a02..35faa1428 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -1,15 +1,11 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray textures[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; - int texind; }; layout (location = 0) in vec4 tl_st; @@ -50,7 +46,7 @@ main (void) vec3 t_st = vec3 (warp_st (tl_st.xy, time), 0); vec3 e_st = vec3 (warp_st (tl_st.xy, time), 1); - c = texture (sampler2DArray (textures[texind], samp), t_st); - e = texture (sampler2DArray (textures[texind], samp), e_st); + c = texture (Texture, t_st); + e = texture (Texture, e_st); frag_color = c + e;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag index e9272912f..167c1f014 100644 --- a/libs/video/renderer/vulkan/shader/particle.frag +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -1,7 +1,5 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - layout (location = 0) in vec4 uv_tr; layout (location = 1) in vec4 color; diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.frag b/libs/video/renderer/vulkan/shader/sprite_depth.frag index 3d7b95522..d44ba3725 100644 --- a/libs/video/renderer/vulkan/shader/sprite_depth.frag +++ b/libs/video/renderer/vulkan/shader/sprite_depth.frag @@ -1,7 +1,5 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - layout (set = 1, binding = 1) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag index bb2716def..a890ca94d 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag @@ -1,7 +1,5 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - layout (set = 1, binding = 1) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index d40ea4562..f1ceed2d3 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -114,6 +114,11 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, dfunc->vkCmdPushConstants (cmd, actx->layout, VK_SHADER_STAGE_FRAGMENT_BIT, 68, frag_size, frag_constants); + VkDescriptorSet sets[] = { + skin->descriptor, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, 1, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); } @@ -133,9 +138,9 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) float blend; } vertex_constants; struct { - uint32_t texind; byte colorA[4]; byte colorB[4]; + float pad; float base_color[4]; float fog[4]; } fragment_constants; @@ -154,7 +159,7 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } - fragment_constants.texind = skin->texind; + fragment_constants.pad = 0; QuatCopy (ent->renderer.colormod, fragment_constants.base_color); QuatCopy (skin->colora, fragment_constants.colorA); QuatCopy (skin->colorb, fragment_constants.colorB); @@ -205,10 +210,9 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - actx->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 0, 2, sets, 0, 0); + actx->layout, 0, 1, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); @@ -274,74 +278,25 @@ Vulkan_AliasDepthRange (qfv_renderframe_t *rFrame, &viewport); } -static VkDescriptorImageInfo base_sampler_info = { }; -static VkDescriptorImageInfo base_image_info = { - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -}; -static VkWriteDescriptorSet base_sampler_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, -}; -static VkWriteDescriptorSet base_image_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, -}; - void Vulkan_AliasAddSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - - if (!actx->texindices.size) { - Sys_Error ("ran out of skins (smart texture handling not implemented)"); - } - skin->texind = DARRAY_REMOVE (&actx->texindices); - - VkDescriptorImageInfo imageInfo[1]; - imageInfo[0] = base_image_info; - imageInfo[0].imageView = skin->view; - - VkWriteDescriptorSet write[2]; - write[0] = base_image_write; - write[0].dstSet = actx->descriptors; - write[0].dstArrayElement = skin->texind; - write[0].descriptorCount = 1; - write[0].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + skin->descriptor = Vulkan_CreateCombinedImageSampler (ctx, skin->view, + actx->sampler); } void Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - aliasctx_t *actx = ctx->alias_context; - - DARRAY_APPEND (&actx->texindices, skin->texind); - - VkDescriptorImageInfo imageInfo[1]; - imageInfo[0] = base_image_info; - imageInfo[0].imageView = ctx->default_magenta_array->view; - - VkWriteDescriptorSet write[2]; - write[0] = base_image_write; - write[0].dstSet = actx->descriptors; - write[0].dstArrayElement = skin->texind; - write[0].descriptorCount = 1; - write[0].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + Vulkan_FreeTexture (ctx, skin->descriptor); + skin->descriptor = 0; } void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "alias init"); @@ -358,49 +313,6 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); - //FIXME too many places - __auto_type limits = device->physDev->properties.limits; - actx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); - actx->pool = Vulkan_CreateDescriptorPool (ctx, "alias_pool"); - actx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "alias_set"); - //FIXME kinda dumb - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = actx->setLayout; - } - __auto_type sets = QFV_AllocateDescriptorSet (device, actx->pool, layouts); - actx->descriptors = sets->a[0]; - free (sets); - - DARRAY_INIT (&actx->texindices, actx->maxImages); - DARRAY_RESIZE (&actx->texindices, actx->maxImages); - actx->texindices.grow = 0; - actx->texindices.maxSize = actx->maxImages; - for (unsigned i = 0; i < actx->maxImages; i++) { - actx->texindices.a[i] = i; - } - - VkDescriptorImageInfo samplerInfo[1]; - samplerInfo[0] = base_sampler_info; - samplerInfo[0].sampler = actx->sampler; - - VkDescriptorImageInfo imageInfo[actx->maxImages]; - for (unsigned i = 0; i < actx->maxImages; i++) { - imageInfo[i] = base_image_info; - imageInfo[i].imageView = ctx->default_magenta_array->view; - } - VkWriteDescriptorSet write[2]; - write[0] = base_sampler_write; - write[0].dstSet = actx->descriptors; - write[0].pImageInfo = samplerInfo; - write[1] = base_image_write; - write[1].dstSet = actx->descriptors; - write[1].descriptorCount = actx->maxImages; - write[1].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); - - - for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index db0877881..697d46070 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -162,8 +162,11 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; vulktex_t *tex = tx->render; - tex->texind = bctx->texture_chains.size; - DARRAY_APPEND (&bctx->texture_chains, tex); + if (tex->tex) { + DARRAY_APPEND (&bctx->texture_chains, tex); + tex->descriptor = Vulkan_CreateTextureDescriptor (ctx, tex->tex, + bctx->sampler); + } tex->tex_chain = 0; tex->tex_chain_tail = &tex->tex_chain; tex->elechain = 0; @@ -261,29 +264,9 @@ clear_textures (vulkan_ctx_t *ctx) bctx->texture_chains.size = 0; } -static VkDescriptorImageInfo base_sampler_info = { }; -static VkDescriptorImageInfo base_image_info = { - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -}; -static VkWriteDescriptorSet base_sampler_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, -}; -static VkWriteDescriptorSet base_image_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, -}; - void Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; - int i; model_t *m; mod_brush_t *brush = &r_worldentity.renderer.model->brush; @@ -306,33 +289,6 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) brush->numsubmodels = 1; // no support for submodels in non-world model register_textures (brush, ctx); } - if (bctx->texture_chains.size > bctx->maxImages) { - Sys_Error ("smart texture handling not implemented, want %zd textures," - "can support %d.", - bctx->texture_chains.size, bctx->maxImages); - } - - VkDescriptorImageInfo samplerInfo[1]; - samplerInfo[0] = base_sampler_info; - samplerInfo[0].sampler = bctx->sampler; - - VkDescriptorImageInfo imageInfo[bctx->maxImages]; - for (unsigned i = 0; i < bctx->maxImages; i++) { - imageInfo[i] = base_image_info; - imageInfo[i].imageView = ctx->default_magenta_array->view; - if (i && i < bctx->texture_chains.size) { - imageInfo[i].imageView = bctx->texture_chains.a[i]->tex->view; - } - } - VkWriteDescriptorSet write[2]; - write[0] = base_sampler_write; - write[0].dstSet = bctx->descriptors; - write[0].pImageInfo = samplerInfo; - write[1] = base_image_write; - write[1].dstSet = bctx->descriptors; - write[1].descriptorCount = bctx->maxImages; - write[1].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); } static elechain_t * @@ -803,12 +759,14 @@ push_transform (vec_t *transform, VkPipelineLayout layout, } static void -push_texind (int32_t texind, VkPipelineLayout layout, - qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +bind_texture (vulktex_t *tex, uint32_t setnum, VkPipelineLayout layout, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) { - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, - /*FIXME 64*/ 64 + field_offset (fragconst_t, texind), - sizeof (int32_t), &texind); + VkDescriptorSet sets[] = { + tex->descriptor, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, setnum, 1, sets, 0, 0); } static void @@ -892,10 +850,9 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - bctx->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, sets, 0, 0); + layout, 0, 1, sets, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -928,8 +885,10 @@ bsp_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], bframe->cmdSet.a[QFV_bspGBuffer]); + qfvPushDebug (ctx, "bsp_begin_subpass"); bsp_begin_subpass (QFV_bspDepth, bctx->depth, bctx->layout, rFrame); bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, bctx->layout, rFrame); + qfvPopDebug (ctx); } static void @@ -957,7 +916,9 @@ turb_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspTurb]); + qfvPushDebug (ctx, "bsp_begin_subpass"); bsp_begin_subpass (QFV_bspTurb, bctx->turb, bctx->layout, rFrame); + qfvPopDebug (ctx); } static void @@ -1008,11 +969,13 @@ sky_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspSky]); + qfvPushDebug (ctx, "bsp_begin_subpass"); if (bctx->skybox_tex) { bsp_begin_subpass (QFV_bspSky, bctx->skybox, bctx->layout, rFrame); } else { bsp_begin_subpass (QFV_bspSky, bctx->skysheet, bctx->layout, rFrame); } + qfvPopDebug (ctx); } static void @@ -1114,8 +1077,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) build_tex_elechain (tex, bctx, bframe); - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspGBuffer]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, @@ -1171,8 +1134,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTurb]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); @@ -1188,8 +1151,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTurb]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); @@ -1221,6 +1184,9 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) return; sky_begin (rFrame); + vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; + bind_texture (&skybox, 2, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); push_transform (identity, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); fragconst_t frag_constants = { time: vr_data.realtime }; @@ -1230,8 +1196,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspSky]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); @@ -1247,8 +1213,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspSky]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); @@ -1410,20 +1376,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); - //FIXME too many places - __auto_type limits = device->physDev->properties.limits; - bctx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); - bctx->pool = Vulkan_CreateDescriptorPool (ctx, "quakebsp_pool"); - bctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "quakebsp_set"); - //FIXME kinda dumb - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = bctx->setLayout; - } - __auto_type sets = QFV_AllocateDescriptorSet (device, bctx->pool, layouts); - bctx->descriptors = sets->a[0]; - free (sets); - for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; @@ -1440,6 +1392,11 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bsp_pass_names[j])); } } + + bctx->skybox_descriptor + = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + bctx->sampler); + qfvPopDebug (ctx); } @@ -1509,6 +1466,7 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) if (bctx->skybox_tex) { Vulkan_UnloadTex (ctx, bctx->skybox_tex); + Vulkan_FreeTexture (ctx, bctx->skybox_descriptor); } bctx->skybox_tex = 0; @@ -1518,6 +1476,9 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) if (!*sky || !strcasecmp (sky, "none")) { Sys_MaskPrintf (SYS_vulkan, "Skybox unloaded\n"); + bctx->skybox_descriptor + = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + bctx->sampler); return; } @@ -1558,6 +1519,9 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) } } if (bctx->skybox_tex) { + bctx->skybox_descriptor + = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + bctx->sampler); Sys_MaskPrintf (SYS_vulkan, "Skybox %s loaded\n", sky); } } diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index b90601102..611836cc2 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" @@ -426,6 +427,14 @@ static tex_t default_magenta_tex = {1, 1, tex_rgba, 1, 0, magenta_data}; void Vulkan_Texture_Init (vulkan_ctx_t *ctx) { + qfvPushDebug (ctx, "texture init"); + + texturectx_t *tctx = calloc (1, sizeof (texturectx_t)); + ctx->texture_context = tctx; + + tctx->pool = Vulkan_CreateDescriptorPool (ctx, "texture_pool"); + tctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "texture_set"); + ctx->default_black = Vulkan_LoadTex (ctx, &default_black_tex, 1, "default_black"); ctx->default_white = Vulkan_LoadTex (ctx, &default_white_tex, 1, @@ -440,6 +449,7 @@ Vulkan_Texture_Init (vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + qfvPopDebug (ctx); } void @@ -450,3 +460,65 @@ Vulkan_Texture_Shutdown (vulkan_ctx_t *ctx) Vulkan_UnloadTex (ctx, ctx->default_magenta); Vulkan_UnloadTex (ctx, ctx->default_magenta_array); } + +static VkDescriptorImageInfo base_image_info = { + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, +}; +static VkWriteDescriptorSet base_image_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, +}; + +VkDescriptorSet +Vulkan_CreateCombinedImageSampler (vulkan_ctx_t *ctx, VkImageView view, + VkSampler sampler) +{ + qfvPushDebug (ctx, "Vulkan_CreateCombinedImageSampler"); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + texturectx_t *tctx = ctx->texture_context; + + //FIXME kinda dumb + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = tctx->setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, tctx->pool, layouts); + VkDescriptorSet descriptor = sets->a[0]; + free (sets); + + VkDescriptorImageInfo imageInfo[1]; + imageInfo[0] = base_image_info; + imageInfo[0].sampler = sampler; + imageInfo[0].imageView = view; + + VkWriteDescriptorSet write[1]; + write[0] = base_image_write; + write[0].dstSet = descriptor; + write[0].pImageInfo = imageInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + + qfvPopDebug (ctx); + + return descriptor; +} + +VkDescriptorSet +Vulkan_CreateTextureDescriptor (vulkan_ctx_t *ctx, qfv_tex_t *tex, + VkSampler sampler) +{ + return Vulkan_CreateCombinedImageSampler (ctx, tex->view, sampler); +} + +void +Vulkan_FreeTexture (vulkan_ctx_t *ctx, VkDescriptorSet texture) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + texturectx_t *tctx = ctx->texture_context; + + dfunc->vkFreeDescriptorSets (device->dev, tctx->pool, 1, &texture); +}