diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 7de1623d9..90a417849 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -65,6 +65,8 @@ typedef struct qfv_iqm_s { qfv_iqm_skin_t *skins; struct qfv_resource_s *mesh; struct qfv_resource_s *bones; + VkBuffer bones_buffer; + VkDescriptorSet *bones_descriptors; // one per frame FIXME per instance!!! } qfv_iqm_t; typedef enum { @@ -91,15 +93,21 @@ typedef struct iqmctx_s { VkPipeline gbuf; VkPipelineLayout layout; VkSampler sampler; + VkDescriptorPool bones_pool; + VkDescriptorSetLayout bones_setLayout; } iqmctx_t; struct vulkan_ctx_s; struct qfv_renderframe_s; struct entity_s; struct mod_iqm_ctx_s; +struct iqm_s; void Vulkan_Mod_IQMFinish (struct model_s *mod, struct vulkan_ctx_s *ctx); +void Vulkan_IQMAddBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm); +void Vulkan_IQMRemoveBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm); + void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); diff --git a/include/QF/iqm.h b/include/QF/iqm.h index adc5a3313..e5ab7ce85 100644 --- a/include/QF/iqm.h +++ b/include/QF/iqm.h @@ -127,7 +127,7 @@ typedef struct { byte weights[4]; } iqmblend_t; -typedef struct { +typedef struct iqm_s { char *text; int num_meshes; iqmmesh *meshes; diff --git a/libs/models/iqm/vulkan_model_iqm.c b/libs/models/iqm/vulkan_model_iqm.c index c9c7f79c8..69baa6fcb 100644 --- a/libs/models/iqm/vulkan_model_iqm.c +++ b/libs/models/iqm/vulkan_model_iqm.c @@ -81,6 +81,11 @@ vulkan_iqm_clear (model_t *mod, void *data) mod->needload = true; + for (int i = 0; i < iqm->num_meshes; i++) { + Vulkan_IQMRemoveSkin (ctx, &mesh->skins[i]); + } + Vulkan_IQMRemoveBones (ctx, iqm);//FIXME doesn't belong here (per-instance) + QFV_DestroyResource (device, mesh->bones); QFV_DestroyResource (device, mesh->mesh); free (mesh); @@ -162,6 +167,14 @@ iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage, 0, 0, 0, 0, 0, 1, &ib.barrier); memcpy (dst, tex->data, layer_size); + VkBufferImageCopy copy = { + packet->offset, 0, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {tex->width, tex->height, 1}, + }; + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); int mipLevels = QFV_MipLevels (tex->width, tex->height); if (mipLevels == 1) { @@ -225,6 +238,7 @@ vulkan_iqm_load_textures (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, tex = &null_tex; } iqm_transfer_texture (tex, image->image, stage, device); + Vulkan_IQMAddSkin (ctx, skin); } dstring_delete (str); QFV_DestroyStagingBuffer (stage); @@ -236,6 +250,8 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + size_t geom_size = iqm->num_verts * sizeof (iqmgvert_t); size_t rend_size = iqm->num_verts * sizeof (iqmrvert_t); size_t elem_size = iqm->num_elements * sizeof (uint16_t); @@ -350,7 +366,7 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, vec4f_t *bone_data; dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE, 0, (void **)&bone_data); - for (int i = 0; i < 3 * iqm->num_joints; i++) { + for (size_t i = 0; i < ictx->frames.size * iqm->num_joints; i++) { vec4f_t *bone = bone_data + i * 3; bone[0] = (vec4f_t) {1, 0, 0, 0}; bone[1] = (vec4f_t) {0, 1, 0, 0}; @@ -363,12 +379,15 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); dfunc->vkUnmapMemory (device->dev, mesh->bones->memory); + + Vulkan_IQMAddBones (ctx, iqm); //FIXME doesn't belong here (per-instance) } void Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + iqmctx_t *ictx = ctx->iqm_context; iqm_t *iqm = (iqm_t *) mod->aliashdr; mod->clear = vulkan_iqm_clear; mod->data = ctx; @@ -378,10 +397,12 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) // 2 is for image + image view int num_objects = 4 + 2 * iqm->num_meshes; qfv_iqm_t *mesh = calloc (1, sizeof (qfv_iqm_t) + + ictx->frames.size * sizeof (VkDescriptorSet) + 2 * sizeof (qfv_resource_t) + num_objects * sizeof (qfv_resobj_t) + iqm->num_meshes * sizeof (qfv_iqm_skin_t)); - mesh->bones = (qfv_resource_t *) &mesh[1]; + mesh->bones_descriptors = (VkDescriptorSet *) &mesh[1]; + mesh->bones = (qfv_resource_t *)&mesh->bones_descriptors[ictx->frames.size]; mesh->mesh = &mesh->bones[1]; mesh->bones[0] = (qfv_resource_t) { @@ -395,9 +416,9 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) .name = "bones", .type = qfv_res_buffer, .buffer = { - .size = 3 * iqm->num_joints * 3 * sizeof (vec4f_t), + .size = ictx->frames.size * iqm->num_joints * 3 * sizeof (vec4f_t), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, }, }; @@ -460,9 +481,10 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) mesh->geom_buffer = mesh->mesh->objects[0].buffer.buffer; mesh->rend_buffer = mesh->mesh->objects[1].buffer.buffer; mesh->index_buffer = mesh->mesh->objects[2].buffer.buffer; + mesh->bones_buffer = mesh->bones->objects[0].buffer.buffer; + + iqm->extra_data = mesh; vulkan_iqm_load_textures (mod, iqm, mesh, ctx); vulkan_iqm_load_arrays (mod, iqm, mesh, ctx); - - iqm->extra_data = mesh; } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a52e3b7eb..a50cab69e 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -92,6 +92,7 @@ vulkan_R_Init (void) Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); + Vulkan_IQM_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); Vulkan_Sprite_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); @@ -686,16 +687,18 @@ vulkan_vid_render_shutdown (void) df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Mod_ClearAll (); + Vulkan_Compose_Shutdown (vulkan_ctx); Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Sprite_Shutdown (vulkan_ctx); Vulkan_Particles_Shutdown (vulkan_ctx); + Vulkan_IQM_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); - Mod_ClearAll (); Vulkan_Texture_Shutdown (vulkan_ctx); Vulkan_DestroyRenderPasses (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/iqm.plist b/libs/video/renderer/vulkan/iqm.plist deleted file mode 100644 index 4467d8b89..000000000 --- a/libs/video/renderer/vulkan/iqm.plist +++ /dev/null @@ -1,254 +0,0 @@ -{ - setLayouts = { - texture_set = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - }; - pipelineLayouts = { - iqm_layout = { - setLayouts = (matrix_set, texture_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4 + 4"; - }, - ); - }; - }; - - depthStencil = { - test_and_write = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - test_only = { - depthTestEnable = true; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - disable = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - }; - - inputAssembly = { - iqm = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - }; - - vertexInput = { - iqm = { - bindings = ( - { binding = 0; stride = 20; inputRate = vertex; }, - { binding = 1; stride = 40; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position - { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 0; }, // bonindices - { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, // boneweights - - { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord - { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal - { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent - { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color - - ); - }; - }; - - rasterization = { - cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - counter_cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - }; - - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = 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; }; - }, - ); - }; - - attachmentBlendOp = { - disabled = { - blendEnable = false; - 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; - }; - alpha_blend = { - 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; - }; - }; - - pipelines = { - iqm_shadow = { - subpass = 0; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm_shadow.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.iqm.bindings[0]", - "$properties.vertexInput.iqm.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.iqm.attributes[0]", - "$properties.vertexInput.iqm.attributes[1]", - "$properties.vertexInput.iqm.attributes[2]", - "$properties.vertexInput.iqm.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.iqm; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.iqm_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - layout = iqm_layout; - }; - iqm_depth = { - subpass = 0; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm_depth.vert; - }, - ); - vertexInput = { - // depth pass doesn't use UVs - bindings = ( - "$properties.vertexInput.iqm.bindings[0]", - "$properties.vertexInput.iqm.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.iqm.attributes[0]", - "$properties.vertexInput.iqm.attributes[1]", - "$properties.vertexInput.iqm.attributes[2]", - "$properties.vertexInput.iqm.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.iqm; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.iqm_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - layout = iqm_layout; - renderPass = renderpass; - }; - iqm_gbuf = { - subpass = 2; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/iqm_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.iqm; - inputAssembly = $properties.inputAssembly.iqm; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); - }; - layout = iqm_layout; - renderPass = renderpass; - }; - }; -} diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 1587727d2..33fef28d3 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -97,6 +97,16 @@ }, ); }; + bone_pool = { + flags = free_descriptor_set; + maxSets = 512; + bindings = ( + { + type = storage_buffer; + descriptorCount = $properties.descriptorPools.bone_pool.maxSets; + }, + ); + }; texture_pool = { flags = free_descriptor_set; maxSets = 512; @@ -206,6 +216,16 @@ }, ); }; + bone_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; sprite_set = { bindings = ( { @@ -349,6 +369,21 @@ }, ); }; + iqm_layout = { + setLayouts = (matrix_set, texture_set, bone_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4 + 4"; + }, + ); + }; sprite_layout = { setLayouts = (matrix_set, sprite_set); pushConstantRanges = ( @@ -428,6 +463,10 @@ topology = triangle_fan; primitiveRestartEnable = true; }; + iqm = { + topology = triangle_list; + primitiveRestartEnable = false; + }; twod = { topology = triangle_strip; primitiveRestartEnable = true; @@ -466,6 +505,23 @@ { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, ); }; + iqm = { + bindings = ( + { binding = 0; stride = 20; inputRate = vertex; }, + { binding = 1; stride = 40; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position + { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices + { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights + + { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord + { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal + { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent + { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color + + ); + }; particle = { bindings = ( { binding = 0; stride = "4 * 4 * 4"; inputRate = vertex; }, @@ -833,6 +889,61 @@ inputAssembly = $properties.inputAssembly.brush; layout = quakebsp_layout; }; + iqm_depth = { + @inherit = $properties.pipelines.depth_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + mapEntries = ( + // IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + data = "array(1)"; + }; + }, + ); + vertexInput = $properties.vertexInput.iqm; + /*vertexInput = { + bindings = ( + "$properties.vertexInput.iqm.bindings[0]", + ); + attributes = ( + "$properties.vertexInput.iqm.attributes[0]", + "$properties.vertexInput.iqm.attributes[1]", + "$properties.vertexInput.iqm.attributes[2]", + ); + };*/ + inputAssembly = $properties.inputAssembly.iqm; + layout = iqm_layout; + }; + iqm_gbuf = { + @inherit = $properties.pipelines.gbuf_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + mapEntries = ( + // !IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + data = "array(0)"; + }; + }, + { + stage = fragment; + name = main; + module = $builtin/iqm.frag; + }, + ); + vertexInput = $properties.vertexInput.iqm; + inputAssembly = $properties.inputAssembly.iqm; + layout = iqm_layout; + }; partdraw = { @inherit = $properties.pipelines.trans_base; stages = ( diff --git a/libs/video/renderer/vulkan/shader/iqm.frag b/libs/video/renderer/vulkan/shader/iqm.frag index 7f897422c..2ebc47089 100644 --- a/libs/video/renderer/vulkan/shader/iqm.frag +++ b/libs/video/renderer/vulkan/shader/iqm.frag @@ -1,6 +1,6 @@ #version 450 -layout (set = 1, binding = 0) uniform sampler2DArray Skin; +layout (set = 1, binding = 0) uniform sampler2D Skin; layout (push_constant) uniform PushConstants { layout (offset = 68) @@ -15,7 +15,7 @@ layout (location = 1) in vec4 position; layout (location = 2) in vec3 normal; layout (location = 3) in vec3 tangent; layout (location = 4) in vec3 bitangent; -layout (location = 5) in vec3 color; +layout (location = 5) in vec4 color; layout (location = 0) out vec4 frag_color; layout (location = 1) out vec4 frag_emission; @@ -27,18 +27,19 @@ main (void) { vec4 c; vec4 e; - vec3 n; + //vec3 n; int i; - mat3 tbn = mat3 (tangent, bitangent, normal); + //mat3 tbn = mat3 (tangent, bitangent, normal); - c = texture (Skin, vec3 (texcoord, 0)) * base_color; - c += texture (Skin, vec3 (texcoord, 1)) * unpackUnorm4x8(colorA); - c += texture (Skin, vec3 (texcoord, 2)) * unpackUnorm4x8(colorB); - e = texture (Skin, vec3 (texcoord, 3)); - n = texture (Skin, vec3 (texcoord, 4)).xyz * 2 - 1; + c = texture (Skin, texcoord);// * color; + //c = texture (Skin, vec3 (texcoord, 0)) * color; + //c += texture (Skin, vec3 (texcoord, 1)) * unpackUnorm4x8(colorA); + //c += texture (Skin, vec3 (texcoord, 2)) * unpackUnorm4x8(colorB); + //e = texture (Skin, vec3 (texcoord, 3)); + //n = texture (Skin, vec3 (texcoord, 4)).xyz * 2 - 1; frag_color = c; - frag_emission = e; - frag_normal = vec4(tbn * n, 1); + frag_emission = vec4(0,0,0,1);//e; + frag_normal = vec4(normal,1);//vec4(tbn * n, 1); frag_position = position; } diff --git a/libs/video/renderer/vulkan/shader/iqm.vert b/libs/video/renderer/vulkan/shader/iqm.vert index 590c44118..1f912dcae 100644 --- a/libs/video/renderer/vulkan/shader/iqm.vert +++ b/libs/video/renderer/vulkan/shader/iqm.vert @@ -1,5 +1,7 @@ #version 450 +layout (constant_id = 0) const bool IQMDepthOnly = false; + layout (set = 0, binding = 0) uniform Matrices { mat4 Projection3d; mat4 View; @@ -7,7 +9,7 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection2d; }; -layout (set = 3, binding = 0) buffer Bones { +layout (set = 2, binding = 0) buffer Bones { // NOTE these are transposed, so v * m mat3x4 bones[]; }; @@ -18,7 +20,7 @@ layout (push_constant) uniform PushConstants { }; layout (location = 0) in vec3 vposition; -layout (location = 1) in ivec4 vbones; +layout (location = 1) in uvec4 vbones; layout (location = 2) in vec4 vweights; layout (location = 3) in vec2 vtexcoord; layout (location = 4) in vec3 vnormal; @@ -41,12 +43,16 @@ main (void) m += bones[vbones.w] * vweights.w; vec4 pos = vec4 (Model * vec4(vposition, 1) * m, 1); gl_Position = Projection3d * (View * pos); - position = pos; - mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz), cross(m[2].xyz, m[0].xyz), - cross(m[0].xyz, m[1].xyz)); - normal = mat3 (Model) * vnormal * adjTrans; - tangent = mat3 (Model) * vtangent.xyz * adjTrans; - bitangent = cross (normal, tangent) * vtangent.w; - texcoord = vtexcoord; - color = vcolor; + + if (!IQMDepthOnly) { + position = pos; + mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz), + cross(m[2].xyz, m[0].xyz), + cross(m[0].xyz, m[1].xyz)); + normal = mat3 (Model) * vnormal * adjTrans; + tangent = mat3 (Model) * vtangent.xyz * adjTrans; + bitangent = cross (normal, tangent) * vtangent.w; + texcoord = vtexcoord; + color = vcolor; + } } diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 0e19d4dd6..078667852 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -34,6 +34,7 @@ #include #include "QF/cvar.h" +#include "QF/iqm.h" #include "QF/va.h" #include "QF/scene/entity.h" @@ -42,6 +43,7 @@ #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" @@ -72,7 +74,7 @@ static QFV_Subpass subpass_map[] = { static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, - qfv_iqm_skin_t **skins, + qfv_iqm_skin_t *skins, uint32_t numPC, qfv_push_constants_t *constants, iqm_t *iqm, qfv_renderframe_t *rFrame) { @@ -88,20 +90,28 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, mesh->geom_buffer, mesh->rend_buffer, }; - int bindingCount = skins ? 2 : 1; + int bindingCount = 2;//skins ? 2 : 1; dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, - VK_INDEX_TYPE_UINT32); + VK_INDEX_TYPE_UINT16); QFV_PushConstants (device, cmd, ictx->layout, numPC, constants); for (int i = 0; i < iqm->num_meshes; i++) { if (skins) { VkDescriptorSet sets[] = { - skins[i]->descriptor, + skins[i].descriptor, + mesh->bones_descriptors[ctx->curFrame], }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - ictx->layout, 1, 1, sets, 0, 0); + ictx->layout, 1, 2, sets, 0, 0); + } else { + VkDescriptorSet sets[] = { + mesh->bones_descriptors[ctx->curFrame], + }; + dfunc->vkCmdBindDescriptorSets (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ictx->layout, 2, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * iqm->meshes[i].num_triangles, 1, 3 * iqm->meshes[i].first_triangle, 0, 0); @@ -117,7 +127,7 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; qfv_iqm_t *mesh = iqm->extra_data; - qfv_iqm_skin_t **skins = &mesh->skins; + qfv_iqm_skin_t *skins = mesh->skins; iqm_push_constants_t constants = {}; constants.blend = R_IQMGetLerpedFrames (ent, iqm); @@ -144,8 +154,8 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) }; QuatCopy (ent->renderer.colormod, constants.base_color); - QuatCopy (skins[0]->colora, constants.colorA); - QuatCopy (skins[0]->colorb, constants.colorB); + QuatCopy (skins[0].colora, constants.colorA); + QuatCopy (skins[0].colorb, constants.colorB); QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_iqmDepth], @@ -157,8 +167,8 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) } static void -alias_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, - qfv_renderframe_t *rFrame) +iqm_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, + qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -200,7 +210,7 @@ alias_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, } static void -alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) +iqm_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -222,8 +232,8 @@ Vulkan_IQMBegin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], aframe->cmdSet.a[QFV_iqmGBuffer]); - alias_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame); - alias_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame); + iqm_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame); + iqm_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame); } void @@ -233,8 +243,69 @@ Vulkan_IQMEnd (qfv_renderframe_t *rFrame) iqmctx_t *ictx = ctx->iqm_context; iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; - alias_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx); - alias_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx); + iqm_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx); + iqm_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx); +} + +static VkWriteDescriptorSet base_buffer_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + 0, 0, 0 +}; + +void +Vulkan_IQMAddBones (vulkan_ctx_t *ctx, iqm_t *iqm) +{ + qfvPushDebug (ctx, "Vulkan_IQMAddBones"); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; + int num_sets = ictx->frames.size; + + //FIXME kinda dumb + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (num_sets, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = ictx->bones_setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, ictx->bones_pool, + layouts); + for (size_t i = 0; i < sets->size; i++) { + mesh->bones_descriptors[i] = sets->a[i]; + } + free (sets); + + VkDescriptorBufferInfo bufferInfo[num_sets]; + size_t bones_size = iqm->num_joints * 3 * sizeof (vec4f_t); + for (int i = 0; i < num_sets; i++) { + bufferInfo[i].buffer = mesh->bones_buffer; + bufferInfo[i].offset = i * bones_size; + bufferInfo[i].range = bones_size; + }; + VkWriteDescriptorSet write[num_sets]; + for (int i = 0; i < num_sets; i++) { + write[i] = base_buffer_write; + write[i].dstSet = mesh->bones_descriptors[i]; + write[i].pBufferInfo = &bufferInfo[i]; + } + dfunc->vkUpdateDescriptorSets (device->dev, num_sets, write, 0, 0); + + qfvPopDebug (ctx); +} + +void +Vulkan_IQMRemoveBones (vulkan_ctx_t *ctx, iqm_t *iqm) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; + int num_sets = ictx->frames.size; + + dfunc->vkFreeDescriptorSets (device->dev, ictx->bones_pool, num_sets, + mesh->bones_descriptors); } void @@ -267,11 +338,14 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&ictx->frames, frames); ictx->frames.grow = 0; - ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "alias_depth"); - ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "alias_gbuf"); - ictx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); + ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "iqm_depth"); + ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "iqm_gbuf"); + ictx->layout = Vulkan_CreatePipelineLayout (ctx, "iqm_layout"); ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); + ictx->bones_pool = Vulkan_CreateDescriptorPool (ctx, "bone_pool"); + ictx->bones_setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "bone_set"); + for (size_t i = 0; i < frames; i++) { __auto_type aframe = &ictx->frames.a[i]; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index af5ae3dd1..a68022c32 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -51,7 +51,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" -//#include "QF/Vulkan/qf_iqm.h" +#include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" @@ -95,7 +95,7 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) } while (0) RE_LOOP (alias, Alias); - //RE_LOOP (iqm, IQM); + RE_LOOP (iqm, IQM); RE_LOOP (sprite, Sprite); }