[FFmpeg-devel] [PATCH 3/5] vulkan: use shader objects if supported

Lynne dev at lynne.ee
Sun Sep 29 12:42:50 EEST 2024


Shader objects finally allow completely independent shaders.
---
 libavutil/vulkan.c | 51 +++++++++++++++++++++++++++++++++++++++++++---
 libavutil/vulkan.h |  5 ++---
 2 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index 71581b91a9..8b1c1eb796 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -1601,6 +1601,41 @@ static int init_compute_pipeline(FFVulkanContext *s, FFVulkanShader *shd,
     return 0;
 }
 
+static int create_shader_object(FFVulkanContext *s, FFVulkanShader *shd,
+                                uint8_t *spirv, size_t spirv_len,
+                                const char *entrypoint)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkShaderCreateInfoEXT shader_obj_create = {
+        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
+        .flags = shd->subgroup_info.requiredSubgroupSize ?
+                 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
+        .stage = shd->stage,
+        .nextStage = 0,
+        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
+        .pCode = spirv,
+        .codeSize = spirv_len,
+        .pName = entrypoint,
+        .pSetLayouts = shd->desc_layout,
+        .setLayoutCount = shd->nb_descriptor_sets,
+        .pushConstantRangeCount = shd->push_consts_num,
+        .pPushConstantRanges = shd->push_consts,
+        .pSpecializationInfo = NULL,
+    };
+
+    ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
+                               s->hwctx->alloc, &shd->object);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Unable to create shader object: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
 static int init_descriptors(FFVulkanContext *s, FFVulkanShader *shd)
 {
     VkResult ret;
@@ -1690,7 +1725,11 @@ int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd,
             shd->bound_buffer_indices[i] = i;
     }
 
-    {
+    if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
+        err = create_shader_object(s, shd, spirv, spirv_len, entrypoint);
+        if (err < 0)
+            return err;
+    } else {
         VkShaderModule mod;
         err = create_shader_module(s, shd, &mod, spirv, spirv_len);
         if (err < 0)
@@ -2181,8 +2220,12 @@ void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e,
     VkDeviceSize offsets[1024];
     FFVulkanShaderData *sd = get_shd_data(e, shd);
 
-    /* Bind pipeline */
-    vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
+    if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
+        VkShaderStageFlagBits stages = shd->stage;
+        vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
+    } else {
+        vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
+    }
 
     if (sd->nb_descriptor_sets) {
         if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
@@ -2216,6 +2259,8 @@ void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
                                 s->hwctx->alloc);
 #endif
 
+    if (shd->object)
+        vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
     if (shd->pipeline)
         vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
     if (shd->pipeline_layout)
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index 5391afa4e7..47684e600d 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -194,9 +194,8 @@ typedef struct FFVulkanShader {
     VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info;
 
     /* Base shader object */
-    union {
-        VkPipeline pipeline;
-    };
+    VkShaderEXT object;
+    VkPipeline pipeline;
 
     /* Pipeline layout */
     VkPipelineLayout pipeline_layout;
-- 
2.45.2.753.g447d99e1c3b


More information about the ffmpeg-devel mailing list